Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fleet: implement buckup plugin #381

Merged
merged 6 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
35 changes: 29 additions & 6 deletions docs/content/en/references/fleet_v1alpha1_types.html
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,17 @@ <h3 id="fleet.kurator.dev/v1alpha1.BackupStorage">BackupStorage
</em>
</td>
<td>
<p>SecretName represents the name of the secret containing the object store credentials.
To access the backup storage location, the secret must include the following keys:</p>
<p>The structure of the secret varies depending on the object storage provider:</p>
<ul>
<li><code>access-key</code>: The access-key/account/username for object storage authentication.</li>
<li><code>secret-key</code>: The secret-key/password for object storage authentication.</li>
<li><p>For AWS S3, Minio or Huawei Cloud, the secret should contain the following keys:</p>
<ul>
<li><code>access-key</code>: The access key for S3 authentication.</li>
<li><code>secret-key</code>: The secret key for S3 authentication.</li>
</ul></li>
<li><p>For GCP, the secret should be created according to the official GCP documentation.
see <a href="https://github.com/vmware-tanzu/velero-plugin-for-gcp/blob/main/README.md">https://github.com/vmware-tanzu/velero-plugin-for-gcp/blob/main/README.md</a></p></li>
<li><p>For Azure, the secret should be created according to the official Azure documentation.
see <a href="https://github.com/vmware-tanzu/velero-plugin-for-microsoft-azure/blob/main/README.md">https://github.com/vmware-tanzu/velero-plugin-for-microsoft-azure/blob/main/README.md</a></p></li>
</ul>
</td>
</tr>
Expand Down Expand Up @@ -268,7 +274,7 @@ <h3 id="fleet.kurator.dev/v1alpha1.BackupStorageLocation">BackupStorageLocation
</em>
</td>
<td>
<p>Provider specifies the storage provider type (e.g., aws, gcp, azure).</p>
<p>Provider specifies the storage provider type (e.g., aws, huaweicloud, gcp, azure).</p>
</td>
</tr>
<tr>
Expand All @@ -290,6 +296,7 @@ <h3 id="fleet.kurator.dev/v1alpha1.BackupStorageLocation">BackupStorageLocation
</em>
</td>
<td>
<em>(Optional)</em>
<p>Region specifies the region of the storage.</p>
</td>
</tr>
Expand All @@ -301,7 +308,23 @@ <h3 id="fleet.kurator.dev/v1alpha1.BackupStorageLocation">BackupStorageLocation
</em>
</td>
<td>
<p>Config is a map for additional provider-specific configurations.</p>
<em>(Optional)</em>
<p>Config is a map for additional provider-specific configurations.
# region:
# s3ForcePathStyle:
# s3Url:
# kmsKeyId:
# resourceGroup:
# The ID of the subscription containing the storage account, if different from the cluster’s subscription. (Azure only)
# subscriptionId:
# storageAccount:
# publicUrl:
# Name of the GCP service account to use for this backup storage location. Specify the
# service account here if you want to use workload identity instead of providing the key file.(GCP only)
# serviceAccount:
# Option to skip certificate validation or not if insecureSkipTLSVerify is set to be true, the client side should set the
# flag. For Velero client Command like velero backup describe, velero backup logs needs to add the flag &ndash;insecure-skip-tls-verify
# insecureSkipTLSVerify:</p>
</td>
</tr>
</tbody>
Expand Down
36 changes: 26 additions & 10 deletions manifests/charts/fleet-manager/crds/fleet.kurator.dev_fleet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,30 @@ spec:
config:
additionalProperties:
type: string
description: Config is a map for additional provider-specific
configurations.
description: 'Config is a map for additional provider-specific
configurations. # region: # s3ForcePathStyle:
# s3Url: # kmsKeyId: # resourceGroup: # The
ID of the subscription containing the storage account,
if different from the cluster’s subscription. (Azure
only) # subscriptionId: # storageAccount: # publicUrl:
# Name of the GCP service account to use for this
backup storage location. Specify the # service
account here if you want to use workload identity
instead of providing the key file.(GCP only) # serviceAccount:
# Option to skip certificate validation or not
if insecureSkipTLSVerify is set to be true, the
client side should set the # flag. For Velero client
Command like velero backup describe, velero backup
logs needs to add the flag --insecure-skip-tls-verify
# insecureSkipTLSVerify:'
type: object
endpoint:
description: Endpoint provides the endpoint URL for
the storage.
type: string
provider:
description: Provider specifies the storage provider
type (e.g., aws, gcp, azure).
type (e.g., aws, huaweicloud, gcp, azure).
type: string
region:
description: Region specifies the region of the storage.
Expand All @@ -172,15 +186,17 @@ spec:
- bucket
- endpoint
- provider
- region
type: object
secretName:
description: "SecretName represents the name of the secret
containing the object store credentials. To access the
backup storage location, the secret must include the
following keys: \n - `access-key`: The access-key/account/username
for object storage authentication. - `secret-key`: The
secret-key/password for object storage authentication."
description: "The structure of the secret varies depending
on the object storage provider: \n - For AWS S3, Minio
or Huawei Cloud, the secret should contain the following
keys: - `access-key`: The access key for S3 authentication.
- `secret-key`: The secret key for S3 authentication.
\n - For GCP, the secret should be created according
to the official GCP documentation. see https://github.com/vmware-tanzu/velero-plugin-for-gcp/blob/main/README.md
\n - For Azure, the secret should be created according
to the official Azure documentation. see https://github.com/vmware-tanzu/velero-plugin-for-microsoft-azure/blob/main/README.md"
type: string
required:
- location
Expand Down
37 changes: 30 additions & 7 deletions pkg/apis/fleet/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,26 +283,49 @@ type BackupStorage struct {
// Location specifies where the backup data will be stored.
Location BackupStorageLocation `json:"location"`

// SecretName represents the name of the secret containing the object store credentials.
// To access the backup storage location, the secret must include the following keys:
// The structure of the secret varies depending on the object storage provider:
//
// - For AWS S3, Minio or Huawei Cloud, the secret should contain the following keys:
// - `access-key`: The access key for S3 authentication.
// - `secret-key`: The secret key for S3 authentication.
//
// - For GCP, the secret should be created according to the official GCP documentation.
// see https://github.com/vmware-tanzu/velero-plugin-for-gcp/blob/main/README.md
//
// - For Azure, the secret should be created according to the official Azure documentation.
// see https://github.com/vmware-tanzu/velero-plugin-for-microsoft-azure/blob/main/README.md
//
// - `access-key`: The access-key/account/username for object storage authentication.
// - `secret-key`: The secret-key/password for object storage authentication.
//
// +required
SecretName string `json:"secretName"`
}

type BackupStorageLocation struct {
// Bucket specifies the storage bucket name.
Bucket string `json:"bucket"`
// Provider specifies the storage provider type (e.g., aws, gcp, azure).
// Provider specifies the storage provider type (e.g., aws, huaweicloud, gcp, azure).
Provider string `json:"provider"`
// Endpoint provides the endpoint URL for the storage.
Endpoint string `json:"endpoint"`
// Region specifies the region of the storage.
Region string `json:"region"`
// +optional
Region string `json:"region,omitempty"`
// Config is a map for additional provider-specific configurations.
// # region:
// # s3ForcePathStyle:
// # s3Url:
// # kmsKeyId:
// # resourceGroup:
// # The ID of the subscription containing the storage account, if different from the cluster’s subscription. (Azure only)
// # subscriptionId:
// # storageAccount:
// # publicUrl:
// # Name of the GCP service account to use for this backup storage location. Specify the
// # service account here if you want to use workload identity instead of providing the key file.(GCP only)
// # serviceAccount:
// # Option to skip certificate validation or not if insecureSkipTLSVerify is set to be true, the client side should set the
// # flag. For Velero client Command like velero backup describe, velero backup logs needs to add the flag --insecure-skip-tls-verify
// # insecureSkipTLSVerify:
// +optional
Config map[string]string `json:"config,omitempty"`
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/fleet-manager/fleet.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ import (
const (
FleetKind = "Fleet"
FleetFinalizer = "fleet.kurator.dev"
)

const RequeueAfter = 5 * time.Second
const FleetLabel = "fleet.kurator.dev/fleet-name"
RequeueAfter = 5 * time.Second
FleetLabel = "fleet.kurator.dev/fleet-name"
)

// FleetManager reconciles a Cluster object
type FleetManager struct {
Expand Down
69 changes: 55 additions & 14 deletions pkg/fleet-manager/fleet_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package fleet

import (
"context"
"fmt"
"sync"

hrapiv2b1 "github.com/fluxcd/helm-controller/api/v2beta1"
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
Expand All @@ -35,29 +37,68 @@ const (
PrometheusThanosServiceName = "prometheus-prometheus-thanos"

NoneClusterIP = "None"

FleetPluinLabel = "fleet.kurator.dev/fleet-plugin"
Xieql marked this conversation as resolved.
Show resolved Hide resolved
)

func (f *FleetManager) reconcilePlugins(ctx context.Context, fleet *fleetapi.Fleet, fleetClusters map[ClusterKey]*fleetCluster) (ctrl.Result, error) {
var resources kube.ResourceList

if fleet.Spec.Plugin != nil {
result, ctrlResult, err := f.reconcileMetricPlugin(ctx, fleet, fleetClusters)
if err != nil || ctrlResult.RequeueAfter > 0 {
return ctrlResult, err
type reconcileResult struct {
result kube.ResourceList
ctrlResult ctrl.Result
err error
}

type reconcileFunc func(context.Context, *fleetapi.Fleet, map[ClusterKey]*fleetCluster) (kube.ResourceList, ctrl.Result, error)

funcs := []reconcileFunc{
f.reconcileMetricPlugin,
f.reconcileGrafanaPlugin,
f.reconcileKyvernoPlugin,
f.reconcileBackupPlugin,
}

resultsChannel := make(chan reconcileResult, len(funcs))
var wg sync.WaitGroup

for _, fn := range funcs {
wg.Add(1)
go func(fn reconcileFunc) {
defer wg.Done()
result, ctrlResult, err := fn(ctx, fleet, fleetClusters)
resultsChannel <- reconcileResult{result, ctrlResult, err}
}(fn)
}

go func() {
wg.Wait()
close(resultsChannel)
}()

var errs []error
var ctrlResults []ctrl.Result

for res := range resultsChannel {
if res.err != nil {
errs = append(errs, res.err)
}
if res.ctrlResult.RequeueAfter > 0 {
ctrlResults = append(ctrlResults, res.ctrlResult)
}
resources = append(resources, res.result...)
}
resources = append(resources, result...)

result, ctrlResult, err = f.reconcileGrafanaPlugin(ctx, fleet)
if err != nil || ctrlResult.RequeueAfter > 0 {
return ctrlResult, err
if len(errs) > 0 {
// Combine all errors into one error message
return ctrl.Result{}, fmt.Errorf("encountered multiple errors: %v", errs)
}
resources = append(resources, result...)

result, ctrlResult, err = f.reconcileKyvernoPlugin(ctx, fleet, fleetClusters)
if err != nil || ctrlResult.RequeueAfter > 0 {
return ctrlResult, err
if len(ctrlResults) > 0 {
// Handle multiple ctrlResults
return ctrlResults[0], nil // TODO: if we need strategy about RequeueAfter
Xieql marked this conversation as resolved.
Show resolved Hide resolved
}
resources = append(resources, result...)
}

return f.reconcilePluginResources(ctx, fleet, resources)
Expand Down Expand Up @@ -86,11 +127,11 @@ func (f *FleetManager) reconcilePluginResources(ctx context.Context, fleet *flee
helmReleases := &hrapiv2b1.HelmReleaseList{}
fleetLabels := fleetResourceLables(fleet.Name)
if err := f.Client.List(ctx, helmRepos, client.InNamespace(fleet.Namespace), fleetLabels); err != nil {
log.Error(err, "failed to list helm repositories")
log.Error(err, "failed to list helm repository")
return ctrl.Result{}, err
}
if err := f.Client.List(ctx, helmReleases, client.InNamespace(fleet.Namespace), fleetLabels); err != nil {
log.Error(err, "failed to list helm repositories")
log.Error(err, "failed to list helm release")
return ctrl.Result{}, err
}

Expand Down
Loading