Merge pull request #161 from negz/outofcontrol

Expand support for unstructured types
This commit is contained in:
Nic Cope 2020-04-24 14:32:13 -07:00 committed by GitHub
commit 10ecf0f09a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 549 additions and 219 deletions

View File

@ -168,7 +168,11 @@ func defaultCRManaged(m manager.Manager) crManaged {
ManagedConfiguratorFn(ConfigureNames),
ManagedConfiguratorFn(ConfigureReclaimPolicy),
},
ManagedCreator: NewAPIManagedCreator(m.GetClient(), m.GetScheme()),
ManagedCreator: NewAPIManagedCreator(m.GetClient(), m.GetScheme()),
// TODO(negz): Switch to ConnectionPropagator once this has been
// deprecated for a release or two.
//nolint:staticcheck
ManagedConnectionPropagator: resource.NewAPIManagedConnectionPropagator(m.GetClient(), m.GetScheme()),
}
}
@ -207,12 +211,22 @@ func WithManagedCreator(c ManagedCreator) ReconcilerOption {
// WithManagedConnectionPropagator specifies which ManagedConnectionPropagator
// should be used to propagate resource connection details to their claim.
//
// Deprecated: Use WithConnectionPropagator.
func WithManagedConnectionPropagator(p resource.ManagedConnectionPropagator) ReconcilerOption {
return func(r *Reconciler) {
r.managed.ManagedConnectionPropagator = p
}
}
// WithConnectionPropagator specifies which ConnectionPropagator
// should be used to propagate resource connection details to their claim.
func WithConnectionPropagator(p resource.ConnectionPropagator) ReconcilerOption {
return func(r *Reconciler) {
r.managed.ManagedConnectionPropagator = &resource.APIManagedConnectionPropagator{Propagator: p}
}
}
// WithBinder specifies which Binder should be used to bind
// resources to their claim.
func WithBinder(b Binder) ReconcilerOption {

View File

@ -118,9 +118,14 @@ func NewReconciler(m manager.Manager, of resource.TargetKind, with resource.Mana
client: m.GetClient(),
newTarget: nt,
newManaged: nr,
// TODO(negz): Switch to resource.ConnectionPropagator after this has
// been deprecated for a release or two.
//nolint:staticcheck
propagator: resource.NewAPIManagedConnectionPropagator(m.GetClient(), m.GetScheme()),
log: logging.NewNopLogger(),
record: event.NewNopRecorder(),
log: logging.NewNopLogger(),
record: event.NewNopRecorder(),
}
for _, ro := range o {

View File

@ -44,32 +44,49 @@ const (
// An APIManagedConnectionPropagator propagates connection details by reading
// them from and writing them to a Kubernetes API server.
type APIManagedConnectionPropagator struct {
Propagator ConnectionPropagator
}
// NewAPIManagedConnectionPropagator returns a new APIConnectionPropagator.
//
// Deprecated: Use NewAPIConnectionPropagator.
func NewAPIManagedConnectionPropagator(c client.Client, t runtime.ObjectTyper) *APIManagedConnectionPropagator {
return &APIManagedConnectionPropagator{Propagator: NewAPIConnectionPropagator(c, t)}
}
// PropagateConnection details from the supplied resource.
func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context, to LocalConnectionSecretOwner, mg Managed) error {
return a.Propagator.PropagateConnection(ctx, to, mg)
}
// An APIConnectionPropagator propagates connection details by reading
// them from and writing them to a Kubernetes API server.
type APIConnectionPropagator struct {
client ClientApplicator
typer runtime.ObjectTyper
}
// NewAPIManagedConnectionPropagator returns a new APIManagedConnectionPropagator.
func NewAPIManagedConnectionPropagator(c client.Client, t runtime.ObjectTyper) *APIManagedConnectionPropagator {
return &APIManagedConnectionPropagator{
// NewAPIConnectionPropagator returns a new APIConnectionPropagator.
func NewAPIConnectionPropagator(c client.Client, t runtime.ObjectTyper) *APIConnectionPropagator {
return &APIConnectionPropagator{
client: ClientApplicator{Client: c, Applicator: NewAPIUpdatingApplicator(c)},
typer: t,
}
}
// PropagateConnection details from the supplied resource to the supplied claim.
func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context, o LocalConnectionSecretOwner, mg Managed) error {
// Either this resource does not expose a connection secret, or this claim
// does not want one.
if mg.GetWriteConnectionSecretToReference() == nil || o.GetWriteConnectionSecretToReference() == nil {
// PropagateConnection details from the supplied resource.
func (a *APIConnectionPropagator) PropagateConnection(ctx context.Context, to LocalConnectionSecretOwner, from ConnectionSecretOwner) error {
// Either from does not expose a connection secret, or to does not want one.
if from.GetWriteConnectionSecretToReference() == nil || to.GetWriteConnectionSecretToReference() == nil {
return nil
}
n := types.NamespacedName{
Namespace: mg.GetWriteConnectionSecretToReference().Namespace,
Name: mg.GetWriteConnectionSecretToReference().Name,
Namespace: from.GetWriteConnectionSecretToReference().Namespace,
Name: from.GetWriteConnectionSecretToReference().Name,
}
from := &corev1.Secret{}
if err := a.client.Get(ctx, n, from); err != nil {
fs := &corev1.Secret{}
if err := a.client.Get(ctx, n, fs); err != nil {
return errors.Wrap(err, errGetSecret)
}
@ -77,20 +94,20 @@ func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context
// it references before we propagate it. This ensures a managed resource
// cannot use Crossplane to circumvent RBAC by propagating a secret it does
// not own.
if c := metav1.GetControllerOf(from); c == nil || c.UID != mg.GetUID() {
if c := metav1.GetControllerOf(fs); c == nil || c.UID != from.GetUID() {
return errors.New(errSecretConflict)
}
to := LocalConnectionSecretFor(o, MustGetKind(o, a.typer))
to.Data = from.Data
ts := LocalConnectionSecretFor(to, MustGetKind(to, a.typer))
ts.Data = fs.Data
meta.AllowPropagation(from, to)
meta.AllowPropagation(fs, ts)
if err := a.client.Apply(ctx, to, ConnectionSecretMustBeControllableBy(o.GetUID())); err != nil {
if err := a.client.Apply(ctx, ts, ConnectionSecretMustBeControllableBy(to.GetUID())); err != nil {
return errors.Wrap(err, errCreateOrUpdateSecret)
}
return errors.Wrap(a.client.Update(ctx, from), errUpdateSecret)
return errors.Wrap(a.client.Update(ctx, fs), errUpdateSecret)
}
// An APIPatchingApplicator applies changes to an object by either creating or

View File

@ -36,6 +36,7 @@ import (
)
var (
_ ConnectionPropagator = &APIConnectionPropagator{}
_ ManagedConnectionPropagator = &APIManagedConnectionPropagator{}
)
@ -218,7 +219,7 @@ func TestPropagateConnection(t *testing.T) {
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
api := &APIManagedConnectionPropagator{client: tc.fields.client, typer: tc.fields.typer}
api := &APIConnectionPropagator{client: tc.fields.client, typer: tc.fields.typer}
err := api.PropagateConnection(tc.args.ctx, tc.args.o, tc.args.mg)
if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\napi.PropagateConnection(...): -want error, +got error:\n%s", tc.reason, diff)

View File

@ -66,27 +66,19 @@ func (m *ClaimReferencer) GetClaimReference() *corev1.ObjectReference { return m
type ClassSelector struct{ Sel *metav1.LabelSelector }
// SetClassSelector sets the ClassSelector.
func (m *ClassSelector) SetClassSelector(s *metav1.LabelSelector) {
m.Sel = s
}
func (m *ClassSelector) SetClassSelector(s *metav1.LabelSelector) { m.Sel = s }
// GetClassSelector gets the ClassSelector.
func (m *ClassSelector) GetClassSelector() *metav1.LabelSelector {
return m.Sel
}
func (m *ClassSelector) GetClassSelector() *metav1.LabelSelector { return m.Sel }
// ClassReferencer is a mock that implements ClassReferencer interface.
type ClassReferencer struct{ Ref *corev1.ObjectReference }
// SetClassReference sets the ClassReference.
func (m *ClassReferencer) SetClassReference(r *corev1.ObjectReference) {
m.Ref = r
}
func (m *ClassReferencer) SetClassReference(r *corev1.ObjectReference) { m.Ref = r }
// GetClassReference gets the ClassReference.
func (m *ClassReferencer) GetClassReference() *corev1.ObjectReference {
return m.Ref
}
func (m *ClassReferencer) GetClassReference() *corev1.ObjectReference { return m.Ref }
// ManagedResourceReferencer is a mock that implements ManagedResourceReferencer interface.
type ManagedResourceReferencer struct{ Ref *corev1.ObjectReference }
@ -157,18 +149,50 @@ func (m *CredentialsSecretReferencer) GetCredentialsSecretReference() v1alpha1.S
return m.Ref
}
// A WorkloadReferencer references an OAM Workload type.
type WorkloadReferencer struct{ Ref v1alpha1.TypedReference }
// CompositionReferencer is a mock that implements CompositionReferencer interface.
type CompositionReferencer struct{ Ref *corev1.ObjectReference }
// GetWorkloadReference gets the WorkloadReference.
func (w *WorkloadReferencer) GetWorkloadReference() v1alpha1.TypedReference {
return w.Ref
}
// SetCompositionReference sets the CompositionReference.
func (m *CompositionReferencer) SetCompositionReference(r *corev1.ObjectReference) { m.Ref = r }
// SetWorkloadReference sets the WorkloadReference.
func (w *WorkloadReferencer) SetWorkloadReference(r v1alpha1.TypedReference) {
w.Ref = r
}
// GetCompositionReference gets the CompositionReference.
func (m *CompositionReferencer) GetCompositionReference() *corev1.ObjectReference { return m.Ref }
// CompositionSelector is a mock that implements CompositionSelector interface.
type CompositionSelector struct{ Sel *metav1.LabelSelector }
// SetCompositionSelector sets the CompositionSelector.
func (m *CompositionSelector) SetCompositionSelector(s *metav1.LabelSelector) { m.Sel = s }
// GetCompositionSelector gets the CompositionSelector.
func (m *CompositionSelector) GetCompositionSelector() *metav1.LabelSelector { return m.Sel }
// CompositeResourceReferencer is a mock that implements CompositeResourceReferencer interface.
type CompositeResourceReferencer struct{ Ref *corev1.ObjectReference }
// SetResourceReference sets the composite resource reference.
func (m *CompositeResourceReferencer) SetResourceReference(p *corev1.ObjectReference) { m.Ref = p }
// GetResourceReference gets the composite resource reference.
func (m *CompositeResourceReferencer) GetResourceReference() *corev1.ObjectReference { return m.Ref }
// RequirementReferencer is a mock that implements RequirementReferencer interface.
type RequirementReferencer struct{ Ref *corev1.ObjectReference }
// SetRequirementReference sets the requirement reference.
func (m *RequirementReferencer) SetRequirementReference(p *corev1.ObjectReference) { m.Ref = p }
// GetRequirementReference gets the requirement reference.
func (m *RequirementReferencer) GetRequirementReference() *corev1.ObjectReference { return m.Ref }
// ComposedResourcesReferencer is a mock that implements ComposedResourcesReferencer interface.
type ComposedResourcesReferencer struct{ Refs []corev1.ObjectReference }
// SetResourceReferences sets the composed references.
func (m *ComposedResourcesReferencer) SetResourceReferences(r []corev1.ObjectReference) { m.Refs = r }
// GetResourceReferences gets the composed references.
func (m *ComposedResourcesReferencer) GetResourceReferences() []corev1.ObjectReference { return m.Refs }
// Object is a mock that implements Object interface.
type Object struct {
@ -315,6 +339,83 @@ func (m *Target) DeepCopyObject() runtime.Object {
return out
}
// Composite is a mock that implements Composite interface.
type Composite struct {
metav1.ObjectMeta
CompositionSelector
CompositionReferencer
// TODO(negz): ComposedResourcesReferencer.
RequirementReferencer
Reclaimer
ConnectionSecretWriterTo
v1alpha1.ConditionedStatus
}
// GetObjectKind returns schema.ObjectKind.
func (m *Composite) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
// DeepCopyObject returns a copy of the object as runtime.Object
func (m *Composite) DeepCopyObject() runtime.Object {
out := &Composite{}
j, err := json.Marshal(m)
if err != nil {
panic(err)
}
_ = json.Unmarshal(j, out)
return out
}
// Composed is a mock that implements Composed interface.
type Composed struct {
metav1.ObjectMeta
ConnectionSecretWriterTo
v1alpha1.ConditionedStatus
}
// GetObjectKind returns schema.ObjectKind.
func (m *Composed) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
// DeepCopyObject returns a copy of the object as runtime.Object
func (m *Composed) DeepCopyObject() runtime.Object {
out := &Composed{}
j, err := json.Marshal(m)
if err != nil {
panic(err)
}
_ = json.Unmarshal(j, out)
return out
}
// Requirement is a mock that implements Requirement interface.
type Requirement struct {
metav1.ObjectMeta
CompositionSelector
CompositionReferencer
CompositeResourceReferencer
LocalConnectionSecretWriterTo
v1alpha1.ConditionedStatus
}
// GetObjectKind returns schema.ObjectKind.
func (m *Requirement) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
// DeepCopyObject returns a copy of the object as runtime.Object
func (m *Requirement) DeepCopyObject() runtime.Object {
out := &Requirement{}
j, err := json.Marshal(m)
if err != nil {
panic(err)
}
_ = json.Unmarshal(j, out)
return out
}
// Manager is a mock object that satisfies manager.Manager interface.
type Manager struct {
manager.Manager

View File

@ -121,6 +121,18 @@ type ComposedResourcesReferencer interface {
GetResourceReferences() []corev1.ObjectReference
}
// A RequirementReferencer can reference a requirement resource.
type RequirementReferencer interface {
SetRequirementReference(r *corev1.ObjectReference)
GetRequirementReference() *corev1.ObjectReference
}
// A CompositeResourceReferencer can reference a composite resource.
type CompositeResourceReferencer interface {
SetResourceReference(r *corev1.ObjectReference)
GetResourceReference() *corev1.ObjectReference
}
// An Object is a Kubernetes object.
type Object interface {
metav1.Object
@ -208,22 +220,36 @@ type Target interface {
Conditioned
}
// Composite resource manages one or more Composable resources.
// A Composite resource composes one or more Composed resources.
type Composite interface {
Object
CompositionSelector
CompositionReferencer
ComposedResourcesReferencer
RequirementReferencer
Reclaimer
ConnectionSecretWriterTo
Conditioned
}
// Composable resources can be a resource in a composition.
type Composable interface {
// Composed resources can be a composed into a Composite resource.
type Composed interface {
Object
Conditioned
ConnectionSecretWriterTo
}
// A Requirement for a Composite resource.
type Requirement interface {
Object
CompositionSelector
CompositionReferencer
CompositeResourceReferencer
LocalConnectionSecretWriterTo
Conditioned
}

View File

@ -60,12 +60,19 @@ func (k ClassKind) List() schema.GroupVersionKind {
}
}
// A ManagedKind contains the type metadata for a kind of managed.
// A ManagedKind contains the type metadata for a kind of managed resource.
type ManagedKind schema.GroupVersionKind
// A TargetKind contains the type metadata for a kind of target resource.
type TargetKind schema.GroupVersionKind
// A CompositeKind contains the type metadata for a kind of composite resource.
type CompositeKind schema.GroupVersionKind
// A RequirementKind contains the type metadata for a kind of requirement
// resource.
type RequirementKind schema.GroupVersionKind
// A LocalConnectionSecretOwner may create and manage a connection secret in its
// own namespace.
type LocalConnectionSecretOwner interface {
@ -75,6 +82,16 @@ type LocalConnectionSecretOwner interface {
LocalConnectionSecretWriterTo
}
// A ConnectionPropagator is responsible for propagating information required to
// connect to a resource.
type ConnectionPropagator interface {
PropagateConnection(ctx context.Context, to LocalConnectionSecretOwner, from ConnectionSecretOwner) error
}
// A ConnectionPropagatorFn is a function that satisfies the
// ConnectionPropagator interface.
type ConnectionPropagatorFn func(ctx context.Context, to LocalConnectionSecretOwner, from ConnectionSecretOwner) error
// A ManagedConnectionPropagator is responsible for propagating information
// required to connect to a managed resource (for example the connection secret)
// from the managed resource to its resource claim.

View File

@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructured
// Package composed contains an unstructured composed resource.
package composed
import (
corev1 "k8s.io/api/core/v1"
@ -24,12 +25,13 @@ import (
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
)
// ComposedOption modifies the composable resource.
type ComposedOption func(resource *Composed)
// An Option modifies an unstructured composed resource.
type Option func(resource *Unstructured)
// FromReference sets the metadata of Composed.
func FromReference(ref corev1.ObjectReference) ComposedOption {
return func(cr *Composed) {
// FromReference returns an Option that propagates the metadata in the supplied
// reference to an unstructured composed resource.
func FromReference(ref corev1.ObjectReference) Option {
return func(cr *Unstructured) {
cr.SetGroupVersionKind(ref.GroupVersionKind())
cr.SetName(ref.Name)
cr.SetNamespace(ref.Namespace)
@ -37,28 +39,27 @@ func FromReference(ref corev1.ObjectReference) ComposedOption {
}
}
// NewComposed returns a new *Composed.
func NewComposed(opts ...ComposedOption) *Composed {
cr := &Composed{}
// New returns a new unstructured composed resource.
func New(opts ...Option) *Unstructured {
cr := &Unstructured{}
for _, f := range opts {
f(cr)
}
return cr
}
// Composed is used to operate on the composable resources whose schema
// is not known beforehand.
type Composed struct {
// An Unstructured composed resource.
type Unstructured struct {
unstructured.Unstructured
}
// GetUnstructured returns the underlying *unstructured.Unstructured.
func (cr *Composed) GetUnstructured() *unstructured.Unstructured {
func (cr *Unstructured) GetUnstructured() *unstructured.Unstructured {
return &cr.Unstructured
}
// GetCondition of this Composed.
func (cr *Composed) GetCondition(ct v1alpha1.ConditionType) v1alpha1.Condition {
// GetCondition of this Composed resource.
func (cr *Unstructured) GetCondition(ct v1alpha1.ConditionType) v1alpha1.Condition {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
if err := fieldpath.Pave(cr.Object).GetValueInto("status", &conditioned); err != nil {
@ -67,8 +68,8 @@ func (cr *Composed) GetCondition(ct v1alpha1.ConditionType) v1alpha1.Condition {
return conditioned.GetCondition(ct)
}
// SetConditions of this Composed.
func (cr *Composed) SetConditions(c ...v1alpha1.Condition) {
// SetConditions of this Composed resource.
func (cr *Unstructured) SetConditions(c ...v1alpha1.Condition) {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
_ = fieldpath.Pave(cr.Object).GetValueInto("status", &conditioned)
@ -76,8 +77,8 @@ func (cr *Composed) SetConditions(c ...v1alpha1.Condition) {
_ = fieldpath.Pave(cr.Object).SetValue("status.conditions", conditioned.Conditions)
}
// GetWriteConnectionSecretToReference of this Composed.
func (cr *Composed) GetWriteConnectionSecretToReference() *v1alpha1.SecretReference {
// GetWriteConnectionSecretToReference of this Composed resource.
func (cr *Unstructured) GetWriteConnectionSecretToReference() *v1alpha1.SecretReference {
out := &v1alpha1.SecretReference{}
if err := fieldpath.Pave(cr.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil
@ -85,7 +86,7 @@ func (cr *Composed) GetWriteConnectionSecretToReference() *v1alpha1.SecretRefere
return out
}
// SetWriteConnectionSecretToReference of this Composed.
func (cr *Composed) SetWriteConnectionSecretToReference(r *v1alpha1.SecretReference) {
// SetWriteConnectionSecretToReference of this Composed resource.
func (cr *Unstructured) SetWriteConnectionSecretToReference(r *v1alpha1.SecretReference) {
_ = fieldpath.Pave(cr.Object).SetValue("spec.writeConnectionSecretToRef", r)
}

View File

@ -1,150 +0,0 @@
/*
Copyright 2020 The Crossplane 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.
*/
package unstructured
import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
)
// CompositeOption is used to configure *Composite
type CompositeOption func(*Composite)
// WithGroupVersionKind sets the GroupVersionKind.
func WithGroupVersionKind(gvk schema.GroupVersionKind) CompositeOption {
return func(c *Composite) {
c.SetGroupVersionKind(gvk)
}
}
// NewComposite returns a new *Composite configured via opts.
func NewComposite(opts ...CompositeOption) *Composite {
c := &Composite{}
for _, f := range opts {
f(c)
}
return c
}
// An Composite is the internal representation of the resource generated
// via Crossplane definition types. It is only used for operations in the controller,
// it's not intended to be stored in the api-server.
type Composite struct {
unstructured.Unstructured
}
// GetUnstructured returns the underlying *unstructured.Unstructured.
func (c *Composite) GetUnstructured() *unstructured.Unstructured {
return &c.Unstructured
}
// GetCompositionSelector returns the composition selector.
func (c *Composite) GetCompositionSelector() *v1.LabelSelector {
out := &v1.LabelSelector{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionSelector", out); err != nil {
return nil
}
return out
}
// SetCompositionSelector sets the composition selector.
func (c *Composite) SetCompositionSelector(sel *v1.LabelSelector) {
_ = fieldpath.Pave(c.Object).SetValue("spec.compositionSelector", sel)
}
// GetCompositionReference returns the composition reference.
func (c *Composite) GetCompositionReference() *corev1.ObjectReference {
out := &corev1.ObjectReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRef", out); err != nil {
return nil
}
return out
}
// SetCompositionReference sets the composition reference.
func (c *Composite) SetCompositionReference(ref *corev1.ObjectReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.compositionRef", ref)
}
// GetResourceReferences returns the references of composed resources.
func (c *Composite) GetResourceReferences() []corev1.ObjectReference {
out := &[]corev1.ObjectReference{}
_ = fieldpath.Pave(c.Object).GetValueInto("spec.resourceRefs", out)
return *out
}
// SetResourceReferences sets the references of composed resources.
func (c *Composite) SetResourceReferences(refs []corev1.ObjectReference) {
empty := corev1.ObjectReference{}
finalRefs := []corev1.ObjectReference{}
for _, ref := range refs {
// TODO(muvaf): temporary workaround.
if ref.String() == empty.String() {
continue
}
finalRefs = append(finalRefs, ref)
}
_ = fieldpath.Pave(c.Object).SetValue("spec.resourceRefs", finalRefs)
}
// GetWriteConnectionSecretToReference returns the connection secret reference.
func (c *Composite) GetWriteConnectionSecretToReference() *v1alpha1.SecretReference {
out := &v1alpha1.SecretReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil
}
return out
}
// SetWriteConnectionSecretToReference sets the connection secret reference.
func (c *Composite) SetWriteConnectionSecretToReference(ref *v1alpha1.SecretReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.writeConnectionSecretToRef", ref)
}
// GetCondition of this Composite.
func (c *Composite) GetCondition(ct v1alpha1.ConditionType) v1alpha1.Condition {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil {
return v1alpha1.Condition{}
}
return conditioned.GetCondition(ct)
}
// SetConditions of this Composite.
func (c *Composite) SetConditions(conditions ...v1alpha1.Condition) {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
_ = fieldpath.Pave(c.Object).GetValueInto("status", &conditioned)
conditioned.SetConditions(conditions...)
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.Conditions)
}
// CompositeList contains a list of Composites.
type CompositeList struct {
unstructured.UnstructuredList
}
// GetUnstructuredList returns the underlying *unstructured.UnstructuredList.
func (c *CompositeList) GetUnstructuredList() *unstructured.UnstructuredList {
return &c.UnstructuredList
}

View File

@ -0,0 +1,165 @@
/*
Copyright 2020 The Crossplane 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.
*/
// Package composite contains an unstructured composite resource.
package composite
import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
)
// An Option modifies an unstructured composite resource.
type Option func(*Unstructured)
// WithGroupVersionKind sets the GroupVersionKind of the unstructured composite
// resource.
func WithGroupVersionKind(gvk schema.GroupVersionKind) Option {
return func(c *Unstructured) {
c.SetGroupVersionKind(gvk)
}
}
// New returns a new unstructured composed resource.
func New(opts ...Option) *Unstructured {
c := &Unstructured{}
for _, f := range opts {
f(c)
}
return c
}
// An Unstructured composed resource.
type Unstructured struct {
unstructured.Unstructured
}
// GetUnstructured returns the underlying *unstructured.Unstructured.
func (c *Unstructured) GetUnstructured() *unstructured.Unstructured {
return &c.Unstructured
}
// GetCompositionSelector of this Composite resource.
func (c *Unstructured) GetCompositionSelector() *v1.LabelSelector {
out := &v1.LabelSelector{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionSelector", out); err != nil {
return nil
}
return out
}
// SetCompositionSelector of this Composite resource.
func (c *Unstructured) SetCompositionSelector(sel *v1.LabelSelector) {
_ = fieldpath.Pave(c.Object).SetValue("spec.compositionSelector", sel)
}
// GetCompositionReference of this Composite resource.
func (c *Unstructured) GetCompositionReference() *corev1.ObjectReference {
out := &corev1.ObjectReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRef", out); err != nil {
return nil
}
return out
}
// SetCompositionReference of this Composite resource.
func (c *Unstructured) SetCompositionReference(ref *corev1.ObjectReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.compositionRef", ref)
}
// GetRequirementReference of this Composite resource.
func (c *Unstructured) GetRequirementReference() *corev1.ObjectReference {
out := &corev1.ObjectReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.requirementRef", out); err != nil {
return nil
}
return out
}
// SetRequirementReference of this Composite resource.
func (c *Unstructured) SetRequirementReference(ref *corev1.ObjectReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.requirementRef", ref)
}
// GetResourceReferences of this Composite resource.
func (c *Unstructured) GetResourceReferences() []corev1.ObjectReference {
out := &[]corev1.ObjectReference{}
_ = fieldpath.Pave(c.Object).GetValueInto("spec.resourceRefs", out)
return *out
}
// SetResourceReferences of this Composite resource.
func (c *Unstructured) SetResourceReferences(refs []corev1.ObjectReference) {
empty := corev1.ObjectReference{}
finalRefs := []corev1.ObjectReference{}
for _, ref := range refs {
// TODO(muvaf): temporary workaround.
if ref.String() == empty.String() {
continue
}
finalRefs = append(finalRefs, ref)
}
_ = fieldpath.Pave(c.Object).SetValue("spec.resourceRefs", finalRefs)
}
// GetWriteConnectionSecretToReference of this Composite resource.
func (c *Unstructured) GetWriteConnectionSecretToReference() *v1alpha1.SecretReference {
out := &v1alpha1.SecretReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil
}
return out
}
// SetWriteConnectionSecretToReference of this Composite resource.
func (c *Unstructured) SetWriteConnectionSecretToReference(ref *v1alpha1.SecretReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.writeConnectionSecretToRef", ref)
}
// GetReclaimPolicy of this Composite resource.
func (c *Unstructured) GetReclaimPolicy() v1alpha1.ReclaimPolicy {
s, _ := fieldpath.Pave(c.Object).GetString("spec.reclaimPolicy")
return v1alpha1.ReclaimPolicy(s)
}
// SetReclaimPolicy of this Composite resource.
func (c *Unstructured) SetReclaimPolicy(p v1alpha1.ReclaimPolicy) {
_ = fieldpath.Pave(c.Object).SetValue("spec.reclaimPolicy", p)
}
// GetCondition of this Composite resource.
func (c *Unstructured) GetCondition(ct v1alpha1.ConditionType) v1alpha1.Condition {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil {
return v1alpha1.Condition{}
}
return conditioned.GetCondition(ct)
}
// SetConditions of this Composite resource.
func (c *Unstructured) SetConditions(conditions ...v1alpha1.Condition) {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
_ = fieldpath.Pave(c.Object).GetValueInto("status", &conditioned)
conditioned.SetConditions(conditions...)
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.Conditions)
}

View File

@ -0,0 +1,133 @@
/*
Copyright 2020 The Crossplane 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.
*/
// Package requirement contains an unstructured resource requirement.
package requirement
import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
)
// An Option modifies an unstructured resource requirement.
type Option func(*Unstructured)
// WithGroupVersionKind sets the GroupVersionKind of the unstructured resource
// requirement.
func WithGroupVersionKind(gvk schema.GroupVersionKind) Option {
return func(c *Unstructured) {
c.SetGroupVersionKind(gvk)
}
}
// New returns a new unstructured resource requirement.
func New(opts ...Option) *Unstructured {
c := &Unstructured{}
for _, f := range opts {
f(c)
}
return c
}
// An Unstructured resource requirement.
type Unstructured struct {
unstructured.Unstructured
}
// GetUnstructured returns the underlying *unstructured.Unstructured.
func (c *Unstructured) GetUnstructured() *unstructured.Unstructured {
return &c.Unstructured
}
// GetCompositionSelector of this resource Requirement.
func (c *Unstructured) GetCompositionSelector() *v1.LabelSelector {
out := &v1.LabelSelector{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionSelector", out); err != nil {
return nil
}
return out
}
// SetCompositionSelector of this resource Requirement.
func (c *Unstructured) SetCompositionSelector(sel *v1.LabelSelector) {
_ = fieldpath.Pave(c.Object).SetValue("spec.compositionSelector", sel)
}
// GetCompositionReference of this resource Requirement.
func (c *Unstructured) GetCompositionReference() *corev1.ObjectReference {
out := &corev1.ObjectReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRef", out); err != nil {
return nil
}
return out
}
// SetCompositionReference of this resource Requirement.
func (c *Unstructured) SetCompositionReference(ref *corev1.ObjectReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.compositionRef", ref)
}
// GetResourceReference of this resource Requirement.
func (c *Unstructured) GetResourceReference() *corev1.ObjectReference {
out := &corev1.ObjectReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.resourceRef", out); err != nil {
return nil
}
return out
}
// SetResourceReference of this resource Requirement.
func (c *Unstructured) SetResourceReference(ref *corev1.ObjectReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.resourceRef", ref)
}
// GetWriteConnectionSecretToReference of this resource Requirement.
func (c *Unstructured) GetWriteConnectionSecretToReference() *v1alpha1.LocalSecretReference {
out := &v1alpha1.LocalSecretReference{}
if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil
}
return out
}
// SetWriteConnectionSecretToReference of this resource Requirement.
func (c *Unstructured) SetWriteConnectionSecretToReference(ref *v1alpha1.LocalSecretReference) {
_ = fieldpath.Pave(c.Object).SetValue("spec.writeConnectionSecretToRef", ref)
}
// GetCondition of this Requirement.
func (c *Unstructured) GetCondition(ct v1alpha1.ConditionType) v1alpha1.Condition {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil {
return v1alpha1.Condition{}
}
return conditioned.GetCondition(ct)
}
// SetConditions of this Requirement.
func (c *Unstructured) SetConditions(conditions ...v1alpha1.Condition) {
conditioned := v1alpha1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
_ = fieldpath.Pave(c.Object).GetValueInto("status", &conditioned)
conditioned.SetConditions(conditions...)
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.Conditions)
}