Merge pull request #161 from negz/outofcontrol
Expand support for unstructured types
This commit is contained in:
commit
10ecf0f09a
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
Loading…
Reference in New Issue