Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apis/vshn/v1/dbaas_vshn_garage.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
cpv1 "github.com/crossplane/crossplane/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -131,6 +132,7 @@ type XVSHNGarageSpec struct {
// Parameters are the configurable fields of a VSHNGarage.
Parameters VSHNGarageParameters `json:"parameters,omitempty"`

CompositionRef cpv1.CompositionReference `json:"compositionRef,omitempty"`
xpv1.ResourceSpec `json:",inline"`
}

Expand Down Expand Up @@ -214,6 +216,14 @@ func (v *VSHNGarage) GetBackupRetention() K8upRetentionPolicy {
return K8upRetentionPolicy{}
}

func (v *XVSHNGarage) GetInstanceNamespace() string {
return fmt.Sprintf("vshn-garage-%s", v.GetName())
}

func (v *XVSHNGarage) GetInstances() int {
return v.Spec.Parameters.Instances
}

// GetBackupSchedule returns the current backup schedule
func (v *VSHNGarage) GetBackupSchedule() string {
return v.Status.Schedules.Backup
Expand Down
1 change: 1 addition & 0 deletions apis/vshn/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions cmd/sliexporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/vshn/appcat/v4/pkg/common/utils"
maintenancecontroller "github.com/vshn/appcat/v4/pkg/sliexporter/maintenance_controller"
"github.com/vshn/appcat/v4/pkg/sliexporter/probes"
vshngaragecontroller "github.com/vshn/appcat/v4/pkg/sliexporter/vshngarage_controller"
vshnkeycloakcontroller "github.com/vshn/appcat/v4/pkg/sliexporter/vshnkeycloak_controller"
vshnmariadbcontroller "github.com/vshn/appcat/v4/pkg/sliexporter/vshnmariadb_controller"
vshnminiocontroller "github.com/vshn/appcat/v4/pkg/sliexporter/vshnminio_controller"
Expand Down Expand Up @@ -177,6 +178,20 @@ func (s *sliProber) executeSLIProber(cmd *cobra.Command, _ []string) error {
return err
}
}
if utils.IsKindAvailable(vshnv1.GroupVersion, "XVSHNGarage", ctrl.GetConfigOrDie()) {
log.Info("Enabling VSHNGarage controller")
if err = (&vshngaragecontroller.VSHNGarageReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
ProbeManager: &probeManager,
StartupGracePeriod: startupGraceMin * time.Minute,
GarageDialer: probes.NewGarage,
ScClient: scClient,
}).SetupWithManager(mgr); err != nil {
log.Error(err, "unable to create controller", "controller", "VSHNGarage")
return err
}
}
if utils.IsKindAvailable(vshnv1.GroupVersion, "XVSHNMariaDB", ctrl.GetConfigOrDie()) {
log.Info("Enabling VSHNMariaDB controller")
if err = (&vshnmariadbcontroller.VSHNMariaDBReconciler{
Expand Down
1 change: 0 additions & 1 deletion config/controller/webhooks.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
Expand Down
15 changes: 15 additions & 0 deletions config/sliexporter/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ rules:
- get
- list
- watch
- apiGroups:
- garage.rajsingh.info
resources:
- garagebuckets
- garagekeys
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- managedupgrade.appuio.io
resources:
Expand All @@ -24,10 +35,12 @@ rules:
- apiGroups:
- vshn.appcat.vshn.io
resources:
- vshngarages
- vshnmariadbs
- vshnminios
- vshnpostgresqls
- vshnredis
- xvshngarages
- xvshnkeycloaks
- xvshnmariadbs
- xvshnminios
Expand All @@ -40,10 +53,12 @@ rules:
- apiGroups:
- vshn.appcat.vshn.io
resources:
- vshngarages/status
- vshnmariadbs/status
- vshnminios/status
- vshnpostgresqls/status
- vshnredis/status
- xvshngarages/status
- xvshnkeycloaks/status
- xvshnmariadbs/status
- xvshnminios/status
Expand Down
9 changes: 9 additions & 0 deletions crds/vshn.appcat.vshn.io_xvshngarages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ spec:
spec:
description: XVSHNGarageSpec defines the desired state of a VSHNGarage.
properties:
compositionRef:
description: A CompositionReference references a Composition.
properties:
name:
description: Name of the Composition.
type: string
required:
- name
type: object
deletionPolicy:
default: Delete
description: |-
Expand Down
3 changes: 3 additions & 0 deletions pkg/comp-functions/functions/vshngarage/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ func DeployGarage(ctx context.Context, comp *vshnv1.VSHNGarage, svc *runtime.Ser
"memory": calcResources.Mem,
},
},
"adminKey": map[string]any{
Comment thread
TheBigLee marked this conversation as resolved.
"enabled": true,
},
"storageDataSpace": calcResources.Disk.String(),
"storageMetadataSpace": comp.Spec.Parameters.Service.MetadataStorage,
}
Expand Down
127 changes: 127 additions & 0 deletions pkg/sliexporter/probes/garage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package probes

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"

miniolib "github.com/minio/minio-go/v7"
)

type VSHNGarage struct {
minioClient *miniolib.Client
httpClient *http.Client
adminURL string
adminToken string
bucketName string
Service string
Name string
ClaimNamespace string
InstanceNamespace string
HighAvailable bool
Organization string
ServiceLevel string
CompositionName string
}

func (g VSHNGarage) Close() error {
return nil
}

func (g VSHNGarage) GetInfo() ProbeInfo {
return ProbeInfo{
Service: g.Service,
Name: g.Name,
ClaimNamespace: g.ClaimNamespace,
InstanceNamespace: g.InstanceNamespace,
HighAvailable: g.HighAvailable,
Organization: g.Organization,
ServiceLevel: g.ServiceLevel,
CompositionName: g.CompositionName,
}
}

func (g VSHNGarage) Probe(ctx context.Context) error {
if err := g.checkAdminHealth(ctx); err != nil {
return err
}
return g.checkS3Write(ctx)
}

func (g VSHNGarage) checkAdminHealth(ctx context.Context) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, g.adminURL+"/v2/GetClusterHealth", nil)
if err != nil {
return fmt.Errorf("cannot create admin health request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+g.adminToken)

resp, err := g.httpClient.Do(req)
if err != nil {
return fmt.Errorf("admin health check failed: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
Comment thread
TheBigLee marked this conversation as resolved.
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("admin API returned status %d: %s", resp.StatusCode, body)
}

var health struct {
Status string `json:"status"`
}
if err := json.NewDecoder(resp.Body).Decode(&health); err != nil {
return fmt.Errorf("cannot decode admin health response: %w", err)
}
if health.Status != "healthy" {
return fmt.Errorf("garage cluster health is %q", health.Status)
}
return nil
}

func (g VSHNGarage) checkS3Write(ctx context.Context) error {
x := bytes.NewBufferString("This file is auto-generated, do not edit, VSHN SLI Exporter purposes")
_, err := g.minioClient.PutObject(ctx, g.bucketName, "vshn-sli-probe", x, int64(x.Len()), miniolib.PutObjectOptions{ContentType: "application/octet-stream"})
return err
}

func NewGarage(service, name, claimNamespace, instanceNamespace, organization, sla, compositionName, endpointURL, adminToken, bucketName string, ha bool, opts miniolib.Options) (*VSHNGarage, error) {
u, err := url.Parse(endpointURL)
if err != nil {
return nil, fmt.Errorf("cannot parse garage endpoint %q: %w", endpointURL, err)
}
Comment thread
TheBigLee marked this conversation as resolved.
if u.Host == "" {
return nil, fmt.Errorf("garage endpoint %q has no host (add scheme, e.g. http://)", endpointURL)
}
if u.Scheme != "http" && u.Scheme != "https" {
return nil, fmt.Errorf("garage endpoint %q has unsupported scheme %q (must be http or https)", endpointURL, u.Scheme)
}

opts.Secure = u.Scheme == "https"
minioClient, err := miniolib.New(u.Host, &opts)
if err != nil {
return nil, err
}

adminURL := fmt.Sprintf("%s://%s:3903", u.Scheme, u.Hostname())

Comment thread
TheBigLee marked this conversation as resolved.
return &VSHNGarage{
minioClient: minioClient,
httpClient: &http.Client{Timeout: 5 * time.Second},
adminURL: adminURL,
adminToken: adminToken,
bucketName: bucketName,
Service: service,
Name: name,
ClaimNamespace: claimNamespace,
InstanceNamespace: instanceNamespace,
HighAvailable: ha,
Organization: organization,
ServiceLevel: sla,
CompositionName: compositionName,
}, nil
}
Loading
Loading