Skip to content

Commit

Permalink
feat: add v0.4.x --> v0.5.x upgrade reconcilers (#1683)
Browse files Browse the repository at this point in the history
Signed-off-by: Kent Rancourt <[email protected]>
  • Loading branch information
krancour committed Apr 2, 2024
1 parent 0c4cd6a commit 2baed56
Show file tree
Hide file tree
Showing 28 changed files with 1,000 additions and 282 deletions.
457 changes: 249 additions & 208 deletions api/v1alpha1/generated.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions api/v1alpha1/generated.proto

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

15 changes: 15 additions & 0 deletions api/v1alpha1/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,18 @@ func patchAnnotation(ctx context.Context, c client.Client, obj client.Object, ke
}
return nil
}

func AddV05CompatibilityLabel(
ctx context.Context,
c client.Client,
obj client.Object,
) error {
patchBytes := []byte(
fmt.Sprintf(
`{"metadata":{"labels":{"%s":"true"}}}`,
V05CompatibilityLabelKey,
),
)
patch := client.RawPatch(types.MergePatchType, patchBytes)
return c.Patch(ctx, obj, patch)
}
2 changes: 2 additions & 0 deletions api/v1alpha1/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ const (
LabelTrueValue = "true"

FinalizerName = "kargo.akuity.io/finalizer"

V05CompatibilityLabelKey = "kargo.akuity.com/v0.5-compatible"
)
2 changes: 2 additions & 0 deletions api/v1alpha1/stage_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ type FreightReference struct {
// the contents of the Freight. i.e. Two pieces of Freight can be compared for
// equality by comparing their Names.
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
// ID is the same as Name. It will be removed in v0.6.0.
ID string `json:"id,omitempty" protobuf:"bytes,8,opt,name=id"`
// Warehouse is the name of the Warehouse that created this Freight.
Warehouse string `json:"warehouse,omitempty" protobuf:"bytes,6,opt,name=warehouse"`
// Commits describes specific Git repository commits.
Expand Down
10 changes: 10 additions & 0 deletions charts/kargo/resources/crds/kargo.akuity.io_stages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,9 @@ spec:
type: string
type: object
type: array
id:
description: ID is the same as Name. It will be removed in v0.6.0.
type: string
images:
description: Images describes specific versions of specific container
images.
Expand Down Expand Up @@ -837,6 +840,10 @@ spec:
type: string
type: object
type: array
id:
description: ID is the same as Name. It will be removed in
v0.6.0.
type: string
images:
description: Images describes specific versions of specific
container images.
Expand Down Expand Up @@ -1115,6 +1122,9 @@ spec:
type: string
type: object
type: array
id:
description: ID is the same as Name. It will be removed in v0.6.0.
type: string
images:
description: Images describes specific versions of specific
container images.
Expand Down
3 changes: 3 additions & 0 deletions charts/kargo/resources/crds/kargo.akuity.io_warehouses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ spec:
type: string
type: object
type: array
id:
description: ID is the same as Name. It will be removed in v0.6.0.
type: string
images:
description: Images describes specific versions of specific container
images.
Expand Down
8 changes: 8 additions & 0 deletions charts/kargo/templates/controller/cluster-roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ rules:
- get
- list
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- watch
- apiGroups:
- kargo.akuity.io
resources:
Expand Down
18 changes: 18 additions & 0 deletions charts/kargo/templates/management-controller/cluster-roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ rules:
- rolebindings
verbs:
- create
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- watch
- apiGroups:
- kargo.akuity.io
resources:
Expand All @@ -39,6 +47,16 @@ rules:
- get
- list
- watch
- apiGroups:
- kargo.akuity.io
resources:
- freights
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- kargo.akuity.io
resources:
Expand Down
7 changes: 7 additions & 0 deletions cmd/controlplane/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -78,6 +79,12 @@ func newControllerCommand() *cobra.Command {
err,
)
}
if err = extv1.AddToScheme(scheme); err != nil {
return fmt.Errorf(
"error adding Kubernetes API extensions API to Kargo controller manager scheme: %w",
err,
)
}
if err = kargoapi.AddToScheme(scheme); err != nil {
return fmt.Errorf(
"error adding Kargo API to Kargo controller manager scheme: %w",
Expand Down
35 changes: 35 additions & 0 deletions cmd/controlplane/management_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import (
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/selection"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/metrics/server"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/api/kubernetes"
"github.com/akuity/kargo/internal/controller/management/namespaces"
"github.com/akuity/kargo/internal/controller/management/projects"
"github.com/akuity/kargo/internal/controller/management/upgrade"
"github.com/akuity/kargo/internal/os"
versionpkg "github.com/akuity/kargo/internal/version"
)
Expand Down Expand Up @@ -58,19 +64,40 @@ func newManagementControllerCommand() *cobra.Command {
err,
)
}
if err = extv1.AddToScheme(scheme); err != nil {
return fmt.Errorf(
"error adding Kubernetes API extensions API to Kargo controller manager scheme: %w",
err,
)
}
if err = kargoapi.AddToScheme(scheme); err != nil {
return fmt.Errorf(
"error adding Kargo API to Kargo controller manager scheme: %w",
err,
)
}
secretReq, err :=
labels.NewRequirement(upgrade.SecretTypeLabelKey, selection.Exists, nil)
if err != nil {
return fmt.Errorf(
"error building label requirement for credentials Secrets: %w",
err,
)
}
if kargoMgr, err = ctrl.NewManager(
restCfg,
ctrl.Options{
Scheme: scheme,
Metrics: server.Options{
BindAddress: "0",
},
Cache: cache.Options{
ByObject: map[client.Object]cache.ByObject{
&corev1.Secret{}: {
Label: labels.NewSelector().Add(*secretReq),
},
},
},
},
); err != nil {
return fmt.Errorf("error initializing Kargo controller manager: %w", err)
Expand All @@ -88,6 +115,14 @@ func newManagementControllerCommand() *cobra.Command {
return fmt.Errorf("error setting up Projects reconciler: %w", err)
}

// v0.5.0 upgrade controllers
if err := upgrade.SetupCredentialsReconcilerWithManager(kargoMgr); err != nil {
return fmt.Errorf("error setting up Credentials upgrade reconciler: %w", err)
}
if err := upgrade.SetupFreightReconcilerWithManager(kargoMgr); err != nil {
return fmt.Errorf("error setting up Freight upgrade reconciler: %w", err)
}

if err := kargoMgr.Start(ctx); err != nil {
return fmt.Errorf("error starting kargo manager: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ require (
gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apiextensions-apiserver v0.29.0
k8s.io/component-base v0.29.3 // indirect
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
Expand Down
118 changes: 118 additions & 0 deletions internal/controller/management/upgrade/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package upgrade

import (
"context"
"fmt"
"strings"

log "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/predicate"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
libCreds "github.com/akuity/kargo/internal/credentials"
"github.com/akuity/kargo/internal/logging"
)

const (
SecretTypeLabelKey = "kargo.akuity.io/secret-type" // nolint: gosec
repoLabelValue = "repository"
repoCredsLabelValue = "repo-creds" // nolint: gosec
)

// credentialsReconciler reconciles credentials (Secrets) to upgrade them from
// v0.4-compatible to v0.5-compatible.
type credentialsReconciler struct {
client client.Client
}

// SetupCredentialsReconcilerWithManager initializes a credentialsReconciler
// and registers it with the provided Manager.
func SetupCredentialsReconcilerWithManager(mgr manager.Manager) error {
labelPred, err := predicate.LabelSelectorPredicate(
metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{ // All Secrets that use the old SecretTypeLabelKey
Key: SecretTypeLabelKey,
Operator: metav1.LabelSelectorOpExists,
},
},
},
)
if err != nil {
return err
}
_, err = ctrl.NewControllerManagedBy(mgr).
For(&corev1.Secret{}).
WithEventFilter(
predicate.Funcs{
DeleteFunc: func(event.DeleteEvent) bool {
return false
},
},
).
WithEventFilter(labelPred).
Build(&credentialsReconciler{
client: mgr.GetClient(),
})
return err
}

// Reconcile is part of the main Kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
func (f *credentialsReconciler) Reconcile(
ctx context.Context,
req ctrl.Request,
) (ctrl.Result, error) {
logger := logging.LoggerFromContext(ctx).WithFields(log.Fields{
"namespace": req.NamespacedName.Namespace,
"secret": req.NamespacedName.Name,
})
logger.Debug("reconciling credentials (Secret)")

// Find the Secret
secret := &corev1.Secret{}
if err := f.client.Get(ctx, req.NamespacedName, secret); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}

// Update the credentials to be v0.5-compatible
transformCredentialsSecret(secret)

if err := f.client.Update(ctx, secret); err != nil {
return ctrl.Result{}, err
}

return ctrl.Result{
Requeue: false,
}, nil
}

func transformCredentialsSecret(secret *corev1.Secret) {
// This label is guaranteed to exist because the reconciler uses a predicate
// that requires it.
credType := secret.Labels[SecretTypeLabelKey]
url := string(secret.Data["url"])
if credType == repoCredsLabelValue {
url = fmt.Sprintf(`^%s(/.*)?$`, strings.TrimSuffix(url, "/"))
}

secret.StringData = map[string]string{
libCreds.FieldRepoURL: url,
libCreds.FieldUsername: string(secret.Data[libCreds.FieldUsername]),
libCreds.FieldPassword: string(secret.Data[libCreds.FieldPassword]),
}
if credType == repoCredsLabelValue {
secret.StringData[libCreds.FieldRepoURLIsRegex] = "true"
}

delete(secret.Labels, SecretTypeLabelKey)
secret.Labels[kargoapi.CredentialTypeLabelKey] = string(secret.Data["type"])

secret.Data = nil
}
Loading

0 comments on commit 2baed56

Please sign in to comment.