diff --git a/rollouts/api/v1alpha1/remotesync_types.go b/rollouts/api/v1alpha1/remotesync_types.go index d01d30099..ca36c1eab 100644 --- a/rollouts/api/v1alpha1/remotesync_types.go +++ b/rollouts/api/v1alpha1/remotesync_types.go @@ -57,6 +57,7 @@ type GitInfo struct { } // Oci contains configuration specific to importing resources from an OCI package. +// This definition is copied from https://github.com/GoogleContainerTools/kpt-config-sync/blob/main/pkg/api/configsync/v1beta1/ociconfig.go type OciInfo struct { // image is the OCI image repository URL for the package to sync from. // e.g. `LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY_NAME/PACKAGE_NAME`. diff --git a/rollouts/api/v1alpha1/rollout_types.go b/rollouts/api/v1alpha1/rollout_types.go index 7ea0fef2f..f9b14a4d0 100644 --- a/rollouts/api/v1alpha1/rollout_types.go +++ b/rollouts/api/v1alpha1/rollout_types.go @@ -117,6 +117,8 @@ type PackageSourceType string type PackagesConfig struct { SourceType PackageSourceType `json:"sourceType"` + // TODO(droot): Change Github and Gitlab to pointers because + // One of the the following will be non-nil to follow OneOf semantics. GitHub GitHubSource `json:"github,omitempty"` GitLab GitLabSource `json:"gitlab,omitempty"` OciSource *OCISource `json:"oci,omitempty"` @@ -159,6 +161,7 @@ type GitLabSelector struct { Branch string `json:"branch,omitempty"` } +// OCISource defines configuration to discover OCI packages. type OCISource struct { // image is the OCI image repository URL for the package to sync from. // e.g. `LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY_NAME/PACKAGE_NAME`. @@ -171,6 +174,7 @@ type OCISource struct { // dir is the absolute path of the directory that contains // the local resources. Default: the root directory of the image. + // Note (droot): We will extend `Dir` to express variants of a package at some point. // +optional Dir string `json:"dir,omitempty"` } diff --git a/rollouts/config/crd/bases/gitops.kpt.dev_remotesyncs.yaml b/rollouts/config/crd/bases/gitops.kpt.dev_remotesyncs.yaml index 3f1686aa7..0d5c9682e 100644 --- a/rollouts/config/crd/bases/gitops.kpt.dev_remotesyncs.yaml +++ b/rollouts/config/crd/bases/gitops.kpt.dev_remotesyncs.yaml @@ -118,7 +118,8 @@ spec: type: object oci: description: Oci contains configuration specific to importing - resources from an OCI package. + resources from an OCI package. This definition is copied + from https://github.com/GoogleContainerTools/kpt-config-sync/blob/main/pkg/api/configsync/v1beta1/ociconfig.go properties: auth: description: auth is the type of secret configured for diff --git a/rollouts/config/crd/bases/gitops.kpt.dev_rollouts.yaml b/rollouts/config/crd/bases/gitops.kpt.dev_rollouts.yaml index a947dce47..a725035c3 100644 --- a/rollouts/config/crd/bases/gitops.kpt.dev_rollouts.yaml +++ b/rollouts/config/crd/bases/gitops.kpt.dev_rollouts.yaml @@ -102,7 +102,9 @@ spec: description: Packages source for this Rollout. properties: github: - description: GitHubSource defines the packages source in GitHub. + description: 'TODO(droot): Change Github and Gitlab to pointers + because One of the the following will be non-nil to follow OneOf + semantics.' properties: selector: description: GitHubSelector defines the selector to apply @@ -168,11 +170,13 @@ spec: - selector type: object oci: + description: OCISource defines configuration to discover OCI packages. properties: dir: description: 'dir is the absolute path of the directory that contains the local resources. Default: the root directory - of the image.' + of the image. Note (droot): We will extend `Dir` to express + variants of a package at some point.' type: string image: description: 'image is the OCI image repository URL for the @@ -299,7 +303,8 @@ spec: type: object oci: description: Oci contains configuration specific to importing - resources from an OCI package. + resources from an OCI package. This definition is copied + from https://github.com/GoogleContainerTools/kpt-config-sync/blob/main/pkg/api/configsync/v1beta1/ociconfig.go properties: auth: description: auth is the type of secret configured for @@ -396,7 +401,8 @@ spec: type: object oci: description: Oci contains configuration specific to importing - resources from an OCI package. + resources from an OCI package. This definition is copied + from https://github.com/GoogleContainerTools/kpt-config-sync/blob/main/pkg/api/configsync/v1beta1/ociconfig.go properties: auth: description: auth is the type of secret configured for diff --git a/rollouts/config/samples/test-ns-rollout.yaml b/rollouts/config/samples/test-ns-rollout.yaml index d678ebf81..53a297467 100644 --- a/rollouts/config/samples/test-ns-rollout.yaml +++ b/rollouts/config/samples/test-ns-rollout.yaml @@ -1,3 +1,19 @@ +# Copyright 2023 The kpt Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# An example Rollout that deploys an OCI package +# to the target clusters. apiVersion: gitops.kpt.dev/v1alpha1 kind: Rollout metadata: @@ -8,11 +24,11 @@ spec: sourceType: GCPFleet gcpFleet: projectIds: - - sunilarora-sandbox + - packages: sourceType: OCI oci: - image: us-west1-docker.pkg.dev/sunilarora-sandbox/rollouts-samples/test-namespace:v1 + image: us-west1-docker.pkg.dev/GCP_PROJECT_ID/oci-artifact:v1 dir: . packageToTargetMatcher: type: AllClusters @@ -27,7 +43,7 @@ spec: oci: image: something auth: gcpserviceaccount - gcpServiceAccountEmail: rollouts-samples-reader@sunilarora-sandbox.iam.gserviceaccount.com + gcpServiceAccountEmail: GCP_SA@GCP_PROJECTID.iam.gserviceaccount.com strategy: type: RollingUpdate rollingUpdate: diff --git a/rollouts/controllers/remotesync_controller.go b/rollouts/controllers/remotesync_controller.go index 2334c2c04..62281389d 100644 --- a/rollouts/controllers/remotesync_controller.go +++ b/rollouts/controllers/remotesync_controller.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "reflect" + "strings" "sync" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -194,7 +195,7 @@ func (r *RemoteSyncReconciler) syncExternalSync(ctx context.Context, rs *gitopsv return "", fmt.Errorf("failed to create/update sync: %w", err) } - r.setupWatches(ctx, externalSyncName(rs), rs.Namespace, rs.Spec.ClusterRef) + r.setupWatches(ctx, getExternalSyncName(rs), rs.Namespace, rs.Spec.ClusterRef) syncStatus, err := checkSyncStatus(ctx, dynCl, rs) if err != nil { @@ -348,7 +349,7 @@ func BuildObjectsToApply(remotesync *gitopsv1alpha1.RemoteSync, u := unstructured.Unstructured{Object: newRootSync} u.SetGroupVersionKind(gvk) - u.SetName(externalSyncName(remotesync)) + u.SetName(getExternalSyncName(remotesync)) u.SetNamespace(namespace) labels := u.GetLabels() @@ -418,6 +419,23 @@ func getExternalSyncNamespace(rs *gitopsv1alpha1.RemoteSync) string { } } +// makeRemoteSyncName constructs the name of the RemoteSync object +// by prefixing rolloutName with clusterName. +// For example, RemoteSync object's name for a rollout `app-rollout` and +// target cluster `gke-1` will be `gke-1-app-rollout`. +func makeRemoteSyncName(clusterName, rolloutName string) string { + return fmt.Sprintf("%s-%s", clusterName, rolloutName) +} + +// getExternalSyncName returns the name of the RSync object's name. +// It is derived by stripping away the cluster-name prefix +// from the RemoteSync object's name. We use rollout-name as RSync object's name. +func getExternalSyncName(rrs *gitopsv1alpha1.RemoteSync) string { + clusterRef := rrs.Spec.ClusterRef + clusterName := clusterRef.Name[strings.LastIndex(clusterRef.Name, "/")+1:] + return strings.TrimPrefix(rrs.GetName(), fmt.Sprintf("%s-", clusterName)) +} + // SetupWithManager sets up the controller with the Manager. func (r *RemoteSyncReconciler) SetupWithManager(mgr ctrl.Manager) error { r.channel = make(chan event.GenericEvent, 10) diff --git a/rollouts/controllers/rollout_controller.go b/rollouts/controllers/rollout_controller.go index b18916666..4dfb091cf 100644 --- a/rollouts/controllers/rollout_controller.go +++ b/rollouts/controllers/rollout_controller.go @@ -418,8 +418,7 @@ func (r *RolloutReconciler) computeTargets(ctx context.Context, rs := gitopsv1alpha1.RemoteSync{} key := client.ObjectKey{ Namespace: rollout.Namespace, - // Name: fmt.Sprintf("%s-%s", pkgID(pkg), clusterName), - Name: remoteSyncName(clusterName, rollout.GetName()), + Name: makeRemoteSyncName(clusterName, rollout.GetName()), } // since this RS need to exist, remove it from the deletion list delete(RSkeysToBeDeleted, key) @@ -456,16 +455,6 @@ func (r *RolloutReconciler) computeTargets(ctx context.Context, return targets, nil } -func remoteSyncName(clusterName, rolloutName string) string { - return fmt.Sprintf("%s-%s", clusterName, rolloutName) -} - -func externalSyncName(rrs *gitopsv1alpha1.RemoteSync) string { - clusterRef := rrs.Spec.ClusterRef - clusterName := clusterRef.Name[strings.LastIndex(clusterRef.Name, "/")+1:] - return strings.TrimPrefix(rrs.GetName(), fmt.Sprintf("%s-", clusterName)) -} - // rsNeedsUpdate checks if the underlying remotesync needs to be updated by creating a new RemoteSync object and comparing it to the existing one func rsNeedsUpdate(ctx context.Context, rollout *gitopsv1alpha1.Rollout, currentRS *gitopsv1alpha1.RemoteSync, target *clusterPackagePair) (*gitopsv1alpha1.RemoteSync, bool) { desiredRS := newRemoteSync(rollout, target) @@ -743,8 +732,7 @@ func newRemoteSync(rollout *gitopsv1alpha1.Rollout, target *clusterPackagePair) // or a RootSync in the config-management-system namespace. return &gitopsv1alpha1.RemoteSync{ ObjectMeta: metav1.ObjectMeta{ - // Name: fmt.Sprintf("%s-%s", pkgID(target.packageRef), clusterName), - Name: remoteSyncName(clusterName, rollout.GetName()), + Name: makeRemoteSyncName(clusterName, rollout.GetName()), Namespace: rollout.Namespace, Labels: map[string]string{ rolloutLabel: rollout.Name, @@ -779,16 +767,17 @@ func toSyncSpec(dpkg *packagediscovery.DiscoveredPackage, rollout *gitopsv1alpha case dpkg.OciRepo != nil: syncSpec.SourceType = "oci" syncSpec.Oci = &gitopsv1alpha1.OciInfo{ - // TODO(droot): Repo URL can be an HTTP, GIT or SSH based URL - // Need to make it configurable Image: dpkg.OciRepo.Image, Dir: dpkg.Directory, } - if rollout.Spec.SyncTemplate.RootSync != nil { + // copy the fields from the RSync template + if rollout.Spec.SyncTemplate.RepoSync != nil { + syncSpec.Oci.Auth = rollout.Spec.SyncTemplate.RepoSync.Oci.Auth + syncSpec.Oci.GCPServiceAccountEmail = rollout.Spec.SyncTemplate.RepoSync.Oci.GCPServiceAccountEmail + } else { syncSpec.Oci.Auth = rollout.Spec.SyncTemplate.RootSync.Oci.Auth syncSpec.Oci.GCPServiceAccountEmail = rollout.Spec.SyncTemplate.RootSync.Oci.GCPServiceAccountEmail } - // TODO(droot): support reposync as well default: syncSpec.SourceType = "git" syncSpec.Git = &gitopsv1alpha1.GitInfo{ @@ -804,10 +793,6 @@ func toSyncSpec(dpkg *packagediscovery.DiscoveredPackage, rollout *gitopsv1alpha return syncSpec } -func pkgID(dpkg *packagediscovery.DiscoveredPackage) string { - return dpkg.ID() -} - // SetupWithManager sets up the controller with the Manager. func (r *RolloutReconciler) SetupWithManager(mgr ctrl.Manager) error { if err := gkeclusterapis.AddToScheme(mgr.GetScheme()); err != nil { diff --git a/rollouts/controllers/status.go b/rollouts/controllers/status.go index 21c3eb11c..e4fda8de7 100644 --- a/rollouts/controllers/status.go +++ b/rollouts/controllers/status.go @@ -32,7 +32,7 @@ func checkSyncStatus(ctx context.Context, client dynamic.Interface, remotesync * return "", err } - rs, err := client.Resource(gvr).Namespace(getExternalSyncNamespace(remotesync)).Get(ctx, externalSyncName(remotesync), metav1.GetOptions{}) + rs, err := client.Resource(gvr).Namespace(getExternalSyncNamespace(remotesync)).Get(ctx, getExternalSyncName(remotesync), metav1.GetOptions{}) if err != nil { return "", fmt.Errorf("failed to get %s: %w", gvk.Kind, err) } diff --git a/rollouts/pkg/packagediscovery/oci.go b/rollouts/pkg/packagediscovery/oci.go index 7738e54c3..571767c6d 100644 --- a/rollouts/pkg/packagediscovery/oci.go +++ b/rollouts/pkg/packagediscovery/oci.go @@ -21,6 +21,7 @@ import ( ) // getOCIPackages discovers OCI packages for OCI config. +// TODO(droot): Support variants discovery in the future. func (d *PackageDiscovery) getOCIPackages(ctx context.Context, config gitopsv1alpha1.PackagesConfig) ([]DiscoveredPackage, error) { var discoveredPackages []DiscoveredPackage @@ -28,7 +29,7 @@ func (d *PackageDiscovery) getOCIPackages(ctx context.Context, config gitopsv1al discoveredPackages = append(discoveredPackages, DiscoveredPackage{ Directory: oci.Dir, - OciRepo: &OCIArtifact{ + OciRepo: &OCIRepo{ Image: oci.Image, }, }) diff --git a/rollouts/pkg/packagediscovery/packagediscovery.go b/rollouts/pkg/packagediscovery/packagediscovery.go index 53ae87f60..d509cd664 100644 --- a/rollouts/pkg/packagediscovery/packagediscovery.go +++ b/rollouts/pkg/packagediscovery/packagediscovery.go @@ -64,11 +64,11 @@ type DiscoveredPackage struct { GitLabProject *gitlab.Project // GithubRepo contains the info retrieved from GitHub GitHubRepo *github.Repository - - OciRepo *OCIArtifact + // OciRepo contains info retrieved from the OCI registry + OciRepo *OCIRepo } -type OCIArtifact struct { +type OCIRepo struct { Image string }