diff --git a/apis/quay/v1/quayregistry_types.go b/apis/quay/v1/quayregistry_types.go index 0e960033a..3b0753e8e 100644 --- a/apis/quay/v1/quayregistry_types.go +++ b/apis/quay/v1/quayregistry_types.go @@ -18,6 +18,7 @@ package v1 import ( "errors" + "os" "strings" "k8s.io/apimachinery/pkg/api/meta" @@ -25,8 +26,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) -type QuayVersion string - const ( SupportsRoutesAnnotation = "supports-routes" ClusterHostnameAnnotation = "router-canonical-hostname" @@ -36,28 +35,76 @@ const ( StorageBucketNameAnnotation = "storage-bucketname" StorageAccessKeyAnnotation = "storage-access-key" StorageSecretKeyAnnotation = "storage-secret-key" + + defaultVersionStreamKey = "DEFAULT_STREAM" +) + +type QuayStream string + +const ( + QuayUpstream QuayStream = "upstream" + QuayDownstream QuayStream = "downstream" + + QuayStreamNone QuayStream = "" ) +type QuayVersion string + const ( - QuayVersionVader QuayVersion = "vader" - QuayVersionQuiGon QuayVersion = "qui-gon" + // Upstream versions + QuayVersionVader QuayVersion = "vader" + + // Downstream versions + QuayVersion340 QuayVersion = "v3.4.0" + // QuayVersionDev is used to provide Kustomize overrides. QuayVersionDev QuayVersion = "dev" + + QuayVersionNone QuayVersion = "" ) -var quayVersions = map[QuayVersion]int{ - QuayVersionDev: 0, - QuayVersionQuiGon: 1, - QuayVersionVader: 2, +var quayVersions = map[QuayVersion]struct { + Next QuayVersion + Stream QuayStream +}{ + QuayVersionVader: { + Next: "", + Stream: QuayUpstream, + }, + QuayVersion340: { + Next: "", + Stream: QuayDownstream, + }, + QuayVersionDev: { + Next: QuayVersionDev, + Stream: QuayStreamNone, + }, + QuayVersionNone: { + Next: QuayVersionNone, + Stream: QuayStreamNone, + }, +} + +// Next returns the version that succeeds this version. +func (version QuayVersion) Next() QuayVersion { + return quayVersions[version].Next +} + +// Stream returns the source for this version. +func (version QuayVersion) Stream() QuayStream { + return quayVersions[version].Stream } func mostRecentVersion() QuayVersion { - var mostRecent QuayVersion - mostRecentRank := 0 - for v, rank := range quayVersions { - if rank > mostRecentRank { - mostRecent = v - mostRecentRank = rank + defaultVersionStream := QuayUpstream + if os.Getenv(defaultVersionStreamKey) == string(QuayDownstream) { + defaultVersionStream = QuayDownstream + } + + mostRecent := QuayVersionNone + for version, info := range quayVersions { + if info.Stream == defaultVersionStream && info.Next == QuayVersionNone { + mostRecent = version } } @@ -197,18 +244,32 @@ func ComponentsMatch(firstComponents, secondComponents []Component) bool { func EnsureDesiredVersion(quay *QuayRegistry) (*QuayRegistry, error) { updatedQuay := quay.DeepCopy() - if updatedQuay.Spec.DesiredVersion == "" { - updatedQuay.Spec.DesiredVersion = mostRecentVersion() + if quay.Status.CurrentVersion == QuayVersionNone { + if updatedQuay.Spec.DesiredVersion == QuayVersionNone { + updatedQuay.Spec.DesiredVersion = mostRecentVersion() + return updatedQuay, nil + } - return updatedQuay, nil - } + if _, ok := quayVersions[updatedQuay.Spec.DesiredVersion]; !ok { + return updatedQuay, errors.New("invalid `desiredVersion`: " + string(updatedQuay.Spec.DesiredVersion)) + } + } else { + if updatedQuay.Spec.DesiredVersion == QuayVersionNone { + updatedQuay.Spec.DesiredVersion = quay.Status.CurrentVersion + return updatedQuay, nil + } - if quay.Status.CurrentVersion != "" && quayVersions[quay.Status.CurrentVersion] > quayVersions[updatedQuay.Spec.DesiredVersion] { - return updatedQuay, errors.New("cannot downgrade from `currentVersion`: " + string(quay.Status.CurrentVersion) + " > " + string(updatedQuay.Spec.DesiredVersion)) - } + if quay.Spec.DesiredVersion == quay.Status.CurrentVersion { + return updatedQuay, nil + } - if _, ok := quayVersions[updatedQuay.Spec.DesiredVersion]; !ok { - return updatedQuay, errors.New("invalid `desiredVersion`: " + string(updatedQuay.Spec.DesiredVersion)) + if _, ok := quayVersions[updatedQuay.Spec.DesiredVersion]; !ok { + return updatedQuay, errors.New("invalid `desiredVersion`: " + string(updatedQuay.Spec.DesiredVersion)) + } + + if updatedQuay.Spec.DesiredVersion != quay.Status.CurrentVersion.Next() { + return updatedQuay, errors.New("cannot downgrade from `currentVersion`: " + string(quay.Status.CurrentVersion) + " > " + string(updatedQuay.Spec.DesiredVersion)) + } } return updatedQuay, nil diff --git a/apis/quay/v1/quayregistry_types_test.go b/apis/quay/v1/quayregistry_types_test.go index 9e2f1de3c..2c937d7d0 100644 --- a/apis/quay/v1/quayregistry_types_test.go +++ b/apis/quay/v1/quayregistry_types_test.go @@ -194,6 +194,22 @@ var ensureDesiredVersionTests = []struct { expected QuayVersion expectedErr error }{ + { + "DesiredVersionEmptyCurrentVersionEmpty", + QuayRegistry{}, + QuayVersionVader, + nil, + }, + { + "DesiredVersionEmptyCurrentVersionSet", + QuayRegistry{ + Status: QuayRegistryStatus{ + CurrentVersion: QuayVersionVader, + }, + }, + QuayVersionVader, + nil, + }, { "InvalidDesiredVersion", QuayRegistry{ @@ -205,33 +221,40 @@ var ensureDesiredVersionTests = []struct { errors.New("invalid `desiredVersion`: not-a-real-version"), }, { - "EmptyDesiredVersion", - QuayRegistry{}, - QuayVersionVader, + "DevOverrideDesiredVersionCurrentVersionEmpty", + QuayRegistry{ + Spec: QuayRegistrySpec{ + DesiredVersion: QuayVersionDev, + }, + }, + QuayVersionDev, nil, }, { - "DevOverrideDesiredVersion", + "DevOverrideDesiredVersionCurrentVersionSet", QuayRegistry{ Spec: QuayRegistrySpec{ DesiredVersion: QuayVersionDev, }, + Status: QuayRegistryStatus{ + CurrentVersion: QuayVersionVader, + }, }, - QuayVersionDev, - nil, + QuayVersionVader, + errors.New("cannot downgrade from `currentVersion`: vader > dev"), }, { "DowngradeProhibited", QuayRegistry{ Spec: QuayRegistrySpec{ - DesiredVersion: QuayVersionQuiGon, + DesiredVersion: QuayVersionDev, }, Status: QuayRegistryStatus{ CurrentVersion: QuayVersionVader, }, }, QuayVersionVader, - errors.New("cannot downgrade from `currentVersion`: qui-gon > vader"), + errors.New("cannot downgrade from `currentVersion`: vader > dev"), }, } diff --git a/deploy/manifests/quay-operator/0.0.1/quay-operator.clusterserviceversion.yaml b/deploy/manifests/quay-operator/0.0.1/quay-operator.clusterserviceversion.yaml index 7171c9de7..3fc73f728 100644 --- a/deploy/manifests/quay-operator/0.0.1/quay-operator.clusterserviceversion.yaml +++ b/deploy/manifests/quay-operator/0.0.1/quay-operator.clusterserviceversion.yaml @@ -18,6 +18,7 @@ metadata: "name": "example-registry" }, "spec": { + "desiredVersion": "v3.4.0", "configBundleSecret": "example-registry-config-bundle", "components": [ {"kind": "clair", "managed": true}, @@ -25,7 +26,8 @@ metadata: {"kind": "objectstorage", "managed": true}, {"kind": "redis", "managed": true}, {"kind": "horizontalpodautoscaler", "managed": true}, - {"kind": "route", "managed": true} + {"kind": "route", "managed": true}, + {"kind": "mirror", "managed": true} ] } } @@ -62,8 +64,7 @@ spec: displayName: Desired Version description: Declares the version of Quay that should deployed and managed. Defaults to latest version. x-descriptors: - - 'urn:alm:descriptor:com.tectonic.ui:select:padme' - - 'urn:alm:descriptor:com.tectonic.ui:select:qui-gon' + - 'urn:alm:descriptor:com.tectonic.ui:select:v3.4.0' - 'urn:alm:descriptor:com.tectonic.ui:advanced' - path: components displayName: Components @@ -116,6 +117,9 @@ spec: valueFrom: fieldRef: fieldPath: metadata.annotations['olm.targetNamespaces'] + # NOTE: This controls the default value for `desiredVersion` if left blank. + - name: DEFAULT_STREAM + value: downstream image: quay.io/projectquay/quay-operator@sha256:4f88b7231dcac284893e7c6371ee631fccf592b553d0df76e624068bc9bb7553 name: quay-operator volumeMounts: diff --git a/kustomize/overlays/downstream/v3.4.0/kustomization.yaml b/kustomize/overlays/downstream/v3.4.0/kustomization.yaml new file mode 100644 index 000000000..afbb1fb57 --- /dev/null +++ b/kustomize/overlays/downstream/v3.4.0/kustomization.yaml @@ -0,0 +1,19 @@ +# Overlay variant for Project Quay "padme" release. +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +commonAnnotations: + quay-version: v3.4.0 +bases: + - ../../../tmp +images: + - name: quay.io/projectquay/quay + newName: quay.io/quay/quay + newTag: v3.4.0-osbs + - name: quay.io/projectquay/clair + newName: quay.io/quay/clair + newTag: v3.4.0-osbs + - name: redis + newName: registry.access.redhat.com/rhscl/redis-32-rhel7 + - name: postgres + newName: registry.access.redhat.com/rhscl/postgresql-10-rhel7 + newTag: 1-35 diff --git a/kustomize/overlays/downstream/v3.4.0/upgrade/kustomization.yaml b/kustomize/overlays/downstream/v3.4.0/upgrade/kustomization.yaml new file mode 100644 index 000000000..9c4795a3a --- /dev/null +++ b/kustomize/overlays/downstream/v3.4.0/upgrade/kustomization.yaml @@ -0,0 +1,24 @@ +# Overlay variant for upgrading to Red Hat Quay "v3.4.0" release. +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +commonAnnotations: + quay-version: v3.4.0 +bases: + - ../../../../tmp +patchesStrategicMerge: + # Scale the app deployment to 0 pods in order to run all migrations present in the new container image using the "upgrade" deployment. + - ./quay.deployment.patch.yaml + - ./upgrade.deployment.patch.yaml +images: + - name: quay.io/projectquay/quay + newName: quay.io/quay/quay + newTag: v3.4.0-osbs + - name: quay.io/projectquay/clair + newName: quay.io/quay/clair + newTag: v3.4.0-osbs + - name: redis + newName: registry.access.redhat.com/rhscl/redis-32-rhel7 + - name: postgres + newName: registry.access.redhat.com/rhscl/postgresql-10-rhel7 + newTag: 1-35 + # FIXME(alecmerdler): Need to handle `redhat-pull-secret` (potentially with a `secretGenerator`?)... diff --git a/kustomize/overlays/upstream/qui-gon/upgrade/quay.deployment.patch.yaml b/kustomize/overlays/downstream/v3.4.0/upgrade/quay.deployment.patch.yaml similarity index 79% rename from kustomize/overlays/upstream/qui-gon/upgrade/quay.deployment.patch.yaml rename to kustomize/overlays/downstream/v3.4.0/upgrade/quay.deployment.patch.yaml index a39ce878e..3b630d6b3 100644 --- a/kustomize/overlays/upstream/qui-gon/upgrade/quay.deployment.patch.yaml +++ b/kustomize/overlays/downstream/v3.4.0/upgrade/quay.deployment.patch.yaml @@ -3,6 +3,6 @@ kind: Deployment metadata: name: quay-app annotations: - quay-upgrade: qui-gon + quay-upgrade: v3.4.0 spec: replicas: 0 diff --git a/kustomize/overlays/upstream/qui-gon/upgrade/upgrade.deployment.patch.yaml b/kustomize/overlays/downstream/v3.4.0/upgrade/upgrade.deployment.patch.yaml similarity index 80% rename from kustomize/overlays/upstream/qui-gon/upgrade/upgrade.deployment.patch.yaml rename to kustomize/overlays/downstream/v3.4.0/upgrade/upgrade.deployment.patch.yaml index fa36e003e..65d3548e4 100644 --- a/kustomize/overlays/upstream/qui-gon/upgrade/upgrade.deployment.patch.yaml +++ b/kustomize/overlays/downstream/v3.4.0/upgrade/upgrade.deployment.patch.yaml @@ -3,6 +3,6 @@ kind: Deployment metadata: name: quay-app-upgrade annotations: - quay-upgrade: qui-gon + quay-upgrade: v3.4.0 spec: replicas: 1 diff --git a/kustomize/overlays/upstream/qui-gon/kustomization.yaml b/kustomize/overlays/upstream/qui-gon/kustomization.yaml deleted file mode 100644 index b175ce70e..000000000 --- a/kustomize/overlays/upstream/qui-gon/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Overlay variant for Project Quay "qui-gon" release. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -commonAnnotations: - quay-version: qui-gon -bases: - - ../../../tmp -images: - - name: quay.io/projectquay/quay - newTag: qui-gon - - name: quay.io/projectquay/clair - newTag: qui-gon diff --git a/kustomize/overlays/upstream/qui-gon/upgrade/kustomization.yaml b/kustomize/overlays/upstream/qui-gon/upgrade/kustomization.yaml deleted file mode 100644 index 1f1e7e89b..000000000 --- a/kustomize/overlays/upstream/qui-gon/upgrade/kustomization.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# Overlay variant for upgrading to Project Quay "qui-gon" release. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -commonAnnotations: - quay-version: qui-gon -bases: - - ../../../../tmp -patchesStrategicMerge: - # Scale the app deployment to 0 pods in order to run all migrations present in the new container image using the "upgrade" deployment. - - ./quay.deployment.patch.yaml - - ./upgrade.deployment.patch.yaml -images: - - name: quay.io/projectquay/quay - newTag: qui-gon - - name: quay.io/projectquay/clair - newTag: qui-gon diff --git a/pkg/kustomize/kustomize.go b/pkg/kustomize/kustomize.go index b50da1266..eb85a919f 100644 --- a/pkg/kustomize/kustomize.go +++ b/pkg/kustomize/kustomize.go @@ -47,11 +47,11 @@ func appDir() string { } func overlayDir(desiredVersion v1.QuayVersion) string { - return filepath.Join(kustomizeDir(), "overlays", "upstream", string(desiredVersion)) + return filepath.Join(kustomizeDir(), "overlays", string(desiredVersion.Stream()), string(desiredVersion)) } func upgradeOverlayDir(desiredVersion v1.QuayVersion) string { - return filepath.Join(kustomizeDir(), "overlays", "upstream", string(desiredVersion), "upgrade") + return filepath.Join(kustomizeDir(), "overlays", string(desiredVersion.Stream()), string(desiredVersion), "upgrade") } func check(err error) { diff --git a/pkg/kustomize/kustomize_test.go b/pkg/kustomize/kustomize_test.go index 0e6b95cbc..7d1f2ced1 100644 --- a/pkg/kustomize/kustomize_test.go +++ b/pkg/kustomize/kustomize_test.go @@ -332,7 +332,7 @@ var inflateTests = []struct { }, }, Spec: v1.QuayRegistrySpec{ - DesiredVersion: v1.QuayVersionQuiGon, + DesiredVersion: v1.QuayVersionVader, Components: []v1.Component{ {Kind: "postgres", Managed: true}, {Kind: "clair", Managed: true},