diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d11f20ee8..54c13a00b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: env: # Common versions - GO_VERSION: '1.21.6' + GO_VERSION: '1.22.0' GOLANGCI_VERSION: 'v1.55.2' DOCKER_BUILDX_VERSION: 'v0.10.0' diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml index 84b9f8872..622e6b25f 100644 --- a/.github/workflows/promote.yml +++ b/.github/workflows/promote.yml @@ -21,7 +21,7 @@ on: env: # Common versions - GO_VERSION: '1.21.6' + GO_VERSION: '1.22.0' # Common users. We can't run a step 'if secrets.AWS_USR != ""' but we can run # a step 'if env.AWS_USR' != ""', so we copy these to succinctly test whether diff --git a/ADOPTERS.md b/ADOPTERS.md index 9a9aa6a3f..b03687857 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -51,7 +51,7 @@ This list is sorted in the order that organizations were added to it. | [PITS Global Data Recovery Services](https://www.pitsdatarecovery.net/) | @pheianox | Declarative configuration and integration with CI/CD pipelines | | [NASA Science Cloud](https://smce.nasa.gov/) | [ramon.e.ramirez-linan@nasa.gov](mailto:ramon.e.ramirez-linan@nasa.gov) ([@rezuma](https://github.com/rezuma)) | [NASA Science Cloud](https://smce.nasa.gov) has created compositions to deploy the Open Science Studio, a jupyterhub based platform that connects to HPC in the cloud and foster NASA Open Science Initiative. Navteca ([@navteca](https://github.com/Navteca)) has been helping NASA with this initiative | | [Navteca](https://navteca.com/) | [rlinan@navteca.com](mailto:rlinan@navteca.com) ([@navteca](https://github.com/Navteca)) | [Navteca](https://www.navteca.com) is adopting Crossplane to deploy [Voice Atlas](https://www.voiceatlas.com) a cloud based product that let customer connect corporate knowledge with any Large Language Model and offered to be consumed by users through any channel (slack, MS Teams, Website, etc) | -| [SAP](https://sap.com/) | [d.small@sap.com](mailto:d.small@sap.com)| [SAP](https://sap.com) uses Crossplane as part of a solution that gives teams owning micro-services the ability to provision hyper-scaler hosted backing services such as Redis on demand. | +| [SAP](https://sap.com/) | [opensource@sap.com](mailto:opensource@sap.com)
[@dee0sap](https://github.com/dee0sap)| [SAP](https://sap.com)'s internal Crossplane community is continuously growing and extending the use of Crossplane within SAP in different products. Our teams developed Crossplane providers for internal use and continue contributing new providers to the Crossplane ecosystem. We also contributed a framework that supports end-to-end tests for Crossplane providers to the project.
[SAP Open Source Report 2023](https://dam.sap.com/mac/app/e/pdf/preview/embed/NG3Cg8G?ltr=a&rc=10&includeRelatedAssets=true)
As of February 2024, SAP is ramping up the use of Crossplane with currently 100+ KRM based control planes with Crossplane and other technologies and 1000s of Managed Resources in different qualification grades. | [Airnity](https://airnity.com/) | [hello@airnity.com](mailto:hello@airnity.com) | [Airnity](https://airnity.com/) uses Crossplane to deploy a worldwide cellular connectivity platform for the automotive industry. | | [Intility](https://intility.com/) | @daniwk @JonasKs | We orchestrate our metacloud's infrastructure in production using Crossplane. | | [codecentric](https://www.codecentric.de/) | @jonashackt | Software engineering & Infrastructure automation/GitOps consulting, where the Kubernetes ecosystem is continuously evaluated for best suited tooling for our clients - and Crossplane is a definitive shooting star, which will for sure kick off a broad adoption soon. Currently we're in the process of evaluating and showcasing crossplane to our customers. | diff --git a/cluster/charts/crossplane/templates/rbac-manager-managed-clusterroles.yaml b/cluster/charts/crossplane/templates/rbac-manager-managed-clusterroles.yaml index 1354396fb..2ddd200c7 100644 --- a/cluster/charts/crossplane/templates/rbac-manager-managed-clusterroles.yaml +++ b/cluster/charts/crossplane/templates/rbac-manager-managed-clusterroles.yaml @@ -187,74 +187,5 @@ rules: - apiextensions.crossplane.io resources: ["*"] verbs: [get, list, watch] -{{- if .Values.rbacManager.managementPolicy }} ---- -# The below ClusterRoles are aggregated to the namespaced RBAC roles created by -# the Crossplane RBAC manager when it is running in --manage=All mode. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "crossplane.name" . }}:aggregate-to-ns-admin - labels: - rbac.crossplane.io/aggregate-to-ns-admin: "true" - rbac.crossplane.io/base-of-ns-admin: "true" - app: {{ template "crossplane.name" . }} - {{- include "crossplane.labels" . | indent 4 }} -rules: -# Crossplane namespace admins have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane namespace admins may need to read or otherwise interact with -# resource claim connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] -# Crossplane namespace admins have access to view the roles that they may be -# able to grant to other subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [roles] - verbs: [get, list, watch] -# Crossplane namespace admins have access to grant the access they have to other -# subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [rolebindings] - verbs: ["*"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "crossplane.name" . }}:aggregate-to-ns-edit - labels: - rbac.crossplane.io/aggregate-to-ns-edit: "true" - rbac.crossplane.io/base-of-ns-edit: "true" - app: {{ template "crossplane.name" . }} - {{- include "crossplane.labels" . | indent 4 }} -rules: -# Crossplane namespace editors have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane namespace editors may need to read or otherwise interact with -# resource claim connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "crossplane.name" . }}:aggregate-to-ns-view - labels: - rbac.crossplane.io/aggregate-to-ns-view: "true" - rbac.crossplane.io/base-of-ns-view: "true" - app: {{ template "crossplane.name" . }} - {{- include "crossplane.labels" . | indent 4 }} -rules: -# Crossplane namespace viewers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -{{- end }} {{- end }} {{- end }} diff --git a/cmd/crank/xpkg/push.go b/cmd/crank/xpkg/push.go index 0f7ea5fcd..eca0aee0d 100644 --- a/cmd/crank/xpkg/push.go +++ b/cmd/crank/xpkg/push.go @@ -36,6 +36,7 @@ import ( "github.com/crossplane/crossplane-runtime/pkg/logging" "github.com/crossplane/crossplane/internal/xpkg" + "github.com/crossplane/crossplane/internal/xpkg/upbound" "github.com/crossplane/crossplane/internal/xpkg/upbound/credhelper" ) @@ -62,6 +63,9 @@ type pushCmd struct { // Flags. Keep sorted alphabetically. PackageFiles []string `short:"f" type:"existingfile" placeholder:"PATH" help:"A comma-separated list of xpkg files to push."` + // Common Upbound API configuration. + upbound.Flags `embed:""` + // Internal state. These aren't part of the user-exposed CLI structure. fs afero.Fs } @@ -91,6 +95,11 @@ func (c *pushCmd) AfterApply() error { // Run runs the push cmd. func (c *pushCmd) Run(logger logging.Logger) error { //nolint:gocyclo // This feels easier to read as-is. + upCtx, err := upbound.NewFromFlags(c.Flags, upbound.AllowMissingProfile()) + if err != nil { + return err + } + tag, err := name.NewTag(c.Package, name.WithDefaultRegistry(xpkg.DefaultRegistry)) if err != nil { return errors.Wrapf(err, errFmtNewTag, c.Package) @@ -112,7 +121,11 @@ func (c *pushCmd) Run(logger logging.Logger) error { //nolint:gocyclo // This fe } kc := authn.NewMultiKeychain( - authn.NewKeychainFromHelper(credhelper.New()), + authn.NewKeychainFromHelper(credhelper.New( + credhelper.WithLogger(logger), + credhelper.WithProfile(upCtx.ProfileName), + credhelper.WithDomain(upCtx.Domain.Hostname()), + )), authn.DefaultKeychain, ) diff --git a/internal/controller/apiextensions/composite/composition_render.go b/internal/controller/apiextensions/composite/composition_render.go index d3bbce4ad..f43c5c80a 100644 --- a/internal/controller/apiextensions/composite/composition_render.go +++ b/internal/controller/apiextensions/composite/composition_render.go @@ -32,8 +32,8 @@ const ( errMarshalProtoStruct = "cannot marshal protobuf Struct to JSON" errSetControllerRef = "cannot set controller reference" - errFmtKindChanged = "cannot change the kind of a composed resource from %s to %s (possible composed resource template mismatch)" - errFmtNamePrefixLabel = "cannot find top-level composite resource name label %q in composite resource metadata" + errFmtKindOrGroupChanged = "cannot change the kind or group of a composed resource from %s to %s (possible composed resource template mismatch)" + errFmtNamePrefixLabel = "cannot find top-level composite resource name label %q in composite resource metadata" // TODO(negz): Include more detail such as field paths if they exist. // Perhaps require each patch type to have a String() method to help @@ -61,13 +61,16 @@ func RenderFromJSON(o resource.Object, data []byte) error { o.SetName(name) o.SetNamespace(namespace) - // This resource already had a GVK (probably because it already exists), but + // This resource already had a GK (probably because it already exists), but // when we rendered its template it changed. This shouldn't happen. Either - // someone changed the kind in the template or we're trying to use the wrong - // template (e.g. because the order of an array of anonymous templates + // someone changed the kind or group in the template, or we're trying to use the + // wrong template (e.g. because the order of an array of anonymous templates // changed). - if !gvk.Empty() && o.GetObjectKind().GroupVersionKind() != gvk { - return errors.Errorf(errFmtKindChanged, gvk, o.GetObjectKind().GroupVersionKind()) + // Please note, we don't check for version changes, as versions can change. For example, + // if a composed resource was created with a template that has a version of "v1alpha1", + // and then the template is updated to "v1beta1", the composed resource will still be valid. + if !gvk.Empty() && o.GetObjectKind().GroupVersionKind().GroupKind() != gvk.GroupKind() { + return errors.Errorf(errFmtKindOrGroupChanged, gvk, o.GetObjectKind().GroupVersionKind()) } return nil diff --git a/internal/controller/apiextensions/composite/composition_render_test.go b/internal/controller/apiextensions/composite/composition_render_test.go index 772ed4587..59697114d 100644 --- a/internal/controller/apiextensions/composite/composition_render_test.go +++ b/internal/controller/apiextensions/composite/composition_render_test.go @@ -62,8 +62,25 @@ func TestRenderFromJSON(t *testing.T) { err: errors.Wrap(errInvalidChar, errUnmarshalJSON), }, }, - "ExistingGVKChanged": { - reason: "We should return an error if unmarshalling the base template changed the composed resource's group, version, or kind", + "ExistingGroupChanged": { + reason: "We should return an error if unmarshalling the base template changed the composed resource's group.", + args: args{ + o: composed.New(composed.FromReference(corev1.ObjectReference{ + APIVersion: "example.org/v1", + Kind: "Potato", + })), + data: []byte(`{"apiVersion": "foo.io/v1", "kind": "Potato"}`), + }, + want: want{ + o: composed.New(composed.FromReference(corev1.ObjectReference{ + APIVersion: "foo.io/v1", + Kind: "Potato", + })), + err: errors.Errorf(errFmtKindOrGroupChanged, "example.org/v1, Kind=Potato", "foo.io/v1, Kind=Potato"), + }, + }, + "ExistingKindChanged": { + reason: "We should return an error if unmarshalling the base template changed the composed resource's kind.", args: args{ o: composed.New(composed.FromReference(corev1.ObjectReference{ APIVersion: "example.org/v1", @@ -76,7 +93,23 @@ func TestRenderFromJSON(t *testing.T) { APIVersion: "example.org/v1", Kind: "Different", })), - err: errors.Errorf(errFmtKindChanged, "example.org/v1, Kind=Potato", "example.org/v1, Kind=Different"), + err: errors.Errorf(errFmtKindOrGroupChanged, "example.org/v1, Kind=Potato", "example.org/v1, Kind=Different"), + }, + }, + "VersionCanChange": { + reason: "We should accept version changes in the base template.", + args: args{ + o: composed.New(composed.FromReference(corev1.ObjectReference{ + APIVersion: "example.org/v1alpha1", + Kind: "Potato", + })), + data: []byte(`{"apiVersion": "example.org/v1beta1", "kind": "Potato"}`), + }, + want: want{ + o: composed.New(composed.FromReference(corev1.ObjectReference{ + APIVersion: "example.org/v1beta1", + Kind: "Potato", + })), }, }, "NewComposedResource": { diff --git a/internal/xpkg/upbound/credhelper/credhelper.go b/internal/xpkg/upbound/credhelper/credhelper.go index b5cc3133e..cf68fa35f 100644 --- a/internal/xpkg/upbound/credhelper/credhelper.go +++ b/internal/xpkg/upbound/credhelper/credhelper.go @@ -113,8 +113,10 @@ func (h *Helper) List() (map[string]string, error) { // Get gets credentials for the supplied server. func (h *Helper) Get(serverURL string) (string, string, error) { if !strings.Contains(serverURL, h.domain) { + h.log.Debug("Supplied server URL is not supported by this credentials helper", "serverURL", serverURL, "domain", h.domain) return "", "", errors.New(errUnsupportedDomain) } + h.log.Debug("Getting credentials for server", "serverURL", serverURL) if err := h.src.Initialize(); err != nil { return "", "", errors.Wrap(err, errInitializeSource) } @@ -124,11 +126,13 @@ func (h *Helper) Get(serverURL string) (string, string, error) { } var p config.Profile if h.profile == "" { + h.log.Debug("No profile specified, using default profile") _, p, err = conf.GetDefaultUpboundProfile() if err != nil { return "", "", errors.Wrap(err, errGetDefaultProfile) } } else { + h.log.Debug("Using specified profile", "profile", h.profile) p, err = conf.GetUpboundProfile(h.profile) if err != nil { return "", "", errors.Wrap(err, errGetProfile) diff --git a/test/e2e/manifests/apiextensions/composition/bind-existing-xr/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/bind-existing-xr/setup/provider.yaml index 687921dae..b82f2c560 100644 --- a/test/e2e/manifests/apiextensions/composition/bind-existing-xr/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/bind-existing-xr/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true diff --git a/test/e2e/manifests/apiextensions/composition/composition-selection/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/composition-selection/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/composition-selection/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/composition-selection/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/composition/functions/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/functions/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/functions/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/functions/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/composition/minimal/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/minimal/setup/provider.yaml index 687921dae..b82f2c560 100644 --- a/test/e2e/manifests/apiextensions/composition/minimal/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/minimal/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true diff --git a/test/e2e/manifests/apiextensions/composition/patch-and-transform/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/patch-and-transform/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/patch-and-transform/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/patch-and-transform/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/composition/propagate-field-removals/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/propagate-field-removals/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/propagate-field-removals/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/propagate-field-removals/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/composition/realtime-compositions/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/realtime-compositions/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/realtime-compositions/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/realtime-compositions/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/composition/realtime-revision-selection/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/realtime-revision-selection/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/realtime-revision-selection/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/realtime-revision-selection/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/composition/validation/setup/provider.yaml b/test/e2e/manifests/apiextensions/composition/validation/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/composition/validation/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/composition/validation/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/apiextensions/environment/setup/provider.yaml b/test/e2e/manifests/apiextensions/environment/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/apiextensions/environment/setup/provider.yaml +++ b/test/e2e/manifests/apiextensions/environment/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/lifecycle/upgrade/setup/provider.yaml b/test/e2e/manifests/lifecycle/upgrade/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/lifecycle/upgrade/setup/provider.yaml +++ b/test/e2e/manifests/lifecycle/upgrade/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/pkg/deployment-runtime-config/setup/provider.yaml b/test/e2e/manifests/pkg/deployment-runtime-config/setup/provider.yaml index 2f8d0708f..66236a152 100644 --- a/test/e2e/manifests/pkg/deployment-runtime-config/setup/provider.yaml +++ b/test/e2e/manifests/pkg/deployment-runtime-config/setup/provider.yaml @@ -3,5 +3,5 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true \ No newline at end of file diff --git a/test/e2e/manifests/pkg/externally-managed-service-account/setup/provider.yaml b/test/e2e/manifests/pkg/externally-managed-service-account/setup/provider.yaml index cb5a59985..ec82101bd 100644 --- a/test/e2e/manifests/pkg/externally-managed-service-account/setup/provider.yaml +++ b/test/e2e/manifests/pkg/externally-managed-service-account/setup/provider.yaml @@ -3,7 +3,7 @@ kind: Provider metadata: name: provider-nop spec: - package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 + package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.1 ignoreCrossplaneConstraints: true runtimeConfigRef: name: provider-external-sa \ No newline at end of file