Assume resources, classes, and providers are cluster scoped
Signed-off-by: Nic Cope <negz@rk0n.org>
This commit is contained in:
parent
a310ee6a4a
commit
9f5188e0cb
|
|
@ -78,13 +78,12 @@ type ResourceClaimStatus struct {
|
|||
|
||||
// A ResourceSpec defines the desired state of a managed resource.
|
||||
type ResourceSpec struct {
|
||||
// WriteConnectionSecretToReference specifies the name of a Secret, in the
|
||||
// same namespace as this managed resource, to which any connection details
|
||||
// for this managed resource should be written. Connection details
|
||||
// frequently include the endpoint, username, and password required to
|
||||
// connect to the managed resource.
|
||||
// WriteConnectionSecretToReference specifies the namespace and name of a
|
||||
// Secret to which any connection details for this managed resource should
|
||||
// be written. Connection details frequently include the endpoint, username,
|
||||
// and password required to connect to the managed resource.
|
||||
// +optional
|
||||
WriteConnectionSecretToReference corev1.LocalObjectReference `json:"writeConnectionSecretToRef,omitempty"`
|
||||
WriteConnectionSecretToReference *corev1.ObjectReference `json:"writeConnectionSecretToRef,omitempty"`
|
||||
|
||||
// ClaimReference specifies the resource claim to which this managed
|
||||
// resource will be bound. ClaimReference is set automatically during
|
||||
|
|
@ -124,6 +123,11 @@ type ResourceStatus struct {
|
|||
// specifications of managed resources dynamically provisioned using a resource
|
||||
// class.
|
||||
type ClassSpecTemplate struct {
|
||||
// WriteConnectionSecretsToNamespace specifies the namespace in which the
|
||||
// connection secrets of managed resources dynamically provisioned using
|
||||
// this claim will be created.
|
||||
WriteConnectionSecretsToNamespace string `json:"writeConnectionSecretsToNamespace"`
|
||||
|
||||
// ProviderReference specifies the provider that will be used to create,
|
||||
// observe, update, and delete managed resources that are dynamically
|
||||
// provisioned using this resource class.
|
||||
|
|
|
|||
|
|
@ -143,7 +143,11 @@ func (in *ResourceClaimStatus) DeepCopy() *ResourceClaimStatus {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) {
|
||||
*out = *in
|
||||
out.WriteConnectionSecretToReference = in.WriteConnectionSecretToReference
|
||||
if in.WriteConnectionSecretToReference != nil {
|
||||
in, out := &in.WriteConnectionSecretToReference, &out.WriteConnectionSecretToReference
|
||||
*out = new(v1.ObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.ClaimReference != nil {
|
||||
in, out := &in.ClaimReference, &out.ClaimReference
|
||||
*out = new(v1.ObjectReference)
|
||||
|
|
|
|||
|
|
@ -93,11 +93,14 @@ func NewAPIManagedConnectionPropagator(c client.Client, t runtime.ObjectTyper) *
|
|||
func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context, cm Claim, mg Managed) error {
|
||||
// Either this resource does not expose a connection secret, or this claim
|
||||
// does not want one.
|
||||
if mg.GetWriteConnectionSecretToReference().Name == "" || cm.GetWriteConnectionSecretToReference().Name == "" {
|
||||
if mg.GetWriteConnectionSecretToReference() == nil || cm.GetWriteConnectionSecretToReference().Name == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := types.NamespacedName{Namespace: mg.GetNamespace(), Name: mg.GetWriteConnectionSecretToReference().Name}
|
||||
n := types.NamespacedName{
|
||||
Namespace: mg.GetWriteConnectionSecretToReference().Namespace,
|
||||
Name: mg.GetWriteConnectionSecretToReference().Name,
|
||||
}
|
||||
mgcs := &corev1.Secret{}
|
||||
if err := a.client.Get(ctx, n, mgcs); err != nil {
|
||||
return errors.Wrap(err, errGetSecret)
|
||||
|
|
@ -111,7 +114,7 @@ func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context
|
|||
return errors.New(errSecretConflict)
|
||||
}
|
||||
|
||||
cmcs := ConnectionSecretFor(cm, MustGetKind(cm, a.typer))
|
||||
cmcs := LocalConnectionSecretFor(cm, MustGetKind(cm, a.typer))
|
||||
if _, err := util.CreateOrUpdate(ctx, a.client, cmcs, func() error {
|
||||
// Inside this anonymous function cmcs could either be unchanged (if
|
||||
// it does not exist in the API server) or updated to reflect its
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ func TestPropagateConnection(t *testing.T) {
|
|||
ctx: context.Background(),
|
||||
cm: &MockClaim{},
|
||||
mg: &MockManaged{
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
|
|
@ -196,7 +196,7 @@ func TestPropagateConnection(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockLocalConnectionSecretWriterTo: MockLocalConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
},
|
||||
mg: &MockManaged{},
|
||||
},
|
||||
|
|
@ -209,10 +209,10 @@ func TestPropagateConnection(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
MockLocalConnectionSecretWriterTo: MockLocalConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
},
|
||||
mg: &MockManaged{
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
},
|
||||
want: errors.Wrap(errBoom, errGetSecret),
|
||||
|
|
@ -248,12 +248,12 @@ func TestPropagateConnection(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: cmname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: cmname},
|
||||
MockLocalConnectionSecretWriterTo: MockLocalConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
},
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname, UID: uid},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
},
|
||||
want: errors.Wrap(errors.New(errSecretConflict), errCreateOrUpdateSecret),
|
||||
|
|
@ -285,12 +285,12 @@ func TestPropagateConnection(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: cmname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: cmname},
|
||||
MockLocalConnectionSecretWriterTo: MockLocalConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
},
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname, UID: uid},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
},
|
||||
want: errors.Wrap(errors.New(errSecretConflict), errCreateOrUpdateSecret),
|
||||
|
|
@ -331,12 +331,12 @@ func TestPropagateConnection(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: cmname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: cmname},
|
||||
MockLocalConnectionSecretWriterTo: MockLocalConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
},
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname, UID: uid},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
},
|
||||
want: errors.Wrap(errBoom, errUpdateSecret),
|
||||
|
|
@ -402,12 +402,12 @@ func TestPropagateConnection(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: cmname, UID: uid},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: cmname, UID: uid},
|
||||
MockLocalConnectionSecretWriterTo: MockLocalConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: cmcsname}},
|
||||
},
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname, UID: uid},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
|
|
|
|||
|
|
@ -52,16 +52,21 @@ func NewObjectMetaConfigurator(t runtime.ObjectTyper) *ObjectMetaConfigurator {
|
|||
}
|
||||
|
||||
// Configure the supplied Managed resource's object metadata.
|
||||
func (c *ObjectMetaConfigurator) Configure(_ context.Context, cm Claim, cs Class, mg Managed) error {
|
||||
mg.SetNamespace(cs.GetNamespace())
|
||||
func (c *ObjectMetaConfigurator) Configure(_ context.Context, cm Claim, _ Class, mg Managed) error {
|
||||
mg.SetGenerateName(fmt.Sprintf("%s-%s-", cm.GetNamespace(), cm.GetName()))
|
||||
if meta.GetExternalName(cm) != "" {
|
||||
meta.SetExternalName(mg, meta.GetExternalName(cm))
|
||||
}
|
||||
// TODO(negz): Don't set this potentially cross-namespace owner reference.
|
||||
// We probably want to use the resource's reclaim policy, not Kubernetes
|
||||
// garbage collection, to determine whether to delete a managed resource
|
||||
// when its claim is deleted per https://github.com/crossplaneio/crossplane/issues/550
|
||||
|
||||
// TODO(negz): Avoid setting this owner reference? Kubernetes specifies that
|
||||
// cluster scoped resources cannot have namespaced owners, by design, but
|
||||
// the owner reference appears to work for cascading deletes.
|
||||
// https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents
|
||||
|
||||
// TODO(negz): We probably want to use the resource's reclaim policy, not
|
||||
// Kubernetes garbage collection, to determine whether to delete a managed
|
||||
// resource when its claim is deleted per
|
||||
// https://github.com/crossplaneio/crossplane/issues/550
|
||||
mg.SetOwnerReferences([]v1.OwnerReference{meta.AsOwner(meta.ReferenceTo(cm, MustGetKind(cm, c.typer)))})
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ func TestConfiguratorChain(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestConfigureObjectMeta(t *testing.T) {
|
||||
ns := "namespace"
|
||||
claimName := "myclaim"
|
||||
claimNS := "myclaimns"
|
||||
uid := types.UID("definitely-a-uuid")
|
||||
|
|
@ -127,12 +126,10 @@ func TestConfigureObjectMeta(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &MockClaim{ObjectMeta: metav1.ObjectMeta{Name: claimName, Namespace: claimNS, UID: uid}},
|
||||
cs: &MockClass{ObjectMeta: metav1.ObjectMeta{Namespace: ns}},
|
||||
mg: &MockManaged{},
|
||||
},
|
||||
want: want{
|
||||
mg: &MockManaged{ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: ns,
|
||||
GenerateName: claimNS + "-" + claimName + "-",
|
||||
OwnerReferences: []metav1.OwnerReference{{
|
||||
APIVersion: MockGVK(&MockClaim{}).GroupVersion().String(),
|
||||
|
|
|
|||
|
|
@ -56,12 +56,20 @@ type ManagedResourceReferencer interface {
|
|||
GetResourceReference() *corev1.ObjectReference
|
||||
}
|
||||
|
||||
// A ConnectionSecretWriterTo may write a connection secret.
|
||||
type ConnectionSecretWriterTo interface {
|
||||
// A LocalConnectionSecretWriterTo may write a connection secret to its own
|
||||
// namespace.
|
||||
type LocalConnectionSecretWriterTo interface {
|
||||
SetWriteConnectionSecretToReference(r corev1.LocalObjectReference)
|
||||
GetWriteConnectionSecretToReference() corev1.LocalObjectReference
|
||||
}
|
||||
|
||||
// A ConnectionSecretWriterTo may write a connection secret to an arbitrary
|
||||
// namespace.
|
||||
type ConnectionSecretWriterTo interface {
|
||||
SetWriteConnectionSecretToReference(r *corev1.ObjectReference)
|
||||
GetWriteConnectionSecretToReference() *corev1.ObjectReference
|
||||
}
|
||||
|
||||
// A Reclaimer may specify a ReclaimPolicy.
|
||||
type Reclaimer interface {
|
||||
SetReclaimPolicy(p v1alpha1.ReclaimPolicy)
|
||||
|
|
@ -75,9 +83,10 @@ type Claim interface {
|
|||
runtime.Object
|
||||
metav1.Object
|
||||
|
||||
ClassSelector
|
||||
ClassReferencer
|
||||
ManagedResourceReferencer
|
||||
ConnectionSecretWriterTo
|
||||
LocalConnectionSecretWriterTo
|
||||
|
||||
Conditioned
|
||||
Bindable
|
||||
|
|
|
|||
|
|
@ -55,12 +55,21 @@ type MockManagedResourceReferencer struct{ Ref *corev1.ObjectReference }
|
|||
func (m *MockManagedResourceReferencer) SetResourceReference(r *corev1.ObjectReference) { m.Ref = r }
|
||||
func (m *MockManagedResourceReferencer) GetResourceReference() *corev1.ObjectReference { return m.Ref }
|
||||
|
||||
type MockConnectionSecretWriterTo struct{ Ref corev1.LocalObjectReference }
|
||||
type MockLocalConnectionSecretWriterTo struct{ Ref corev1.LocalObjectReference }
|
||||
|
||||
func (m *MockConnectionSecretWriterTo) SetWriteConnectionSecretToReference(r corev1.LocalObjectReference) {
|
||||
func (m *MockLocalConnectionSecretWriterTo) SetWriteConnectionSecretToReference(r corev1.LocalObjectReference) {
|
||||
m.Ref = r
|
||||
}
|
||||
func (m *MockConnectionSecretWriterTo) GetWriteConnectionSecretToReference() corev1.LocalObjectReference {
|
||||
func (m *MockLocalConnectionSecretWriterTo) GetWriteConnectionSecretToReference() corev1.LocalObjectReference {
|
||||
return m.Ref
|
||||
}
|
||||
|
||||
type MockConnectionSecretWriterTo struct{ Ref *corev1.ObjectReference }
|
||||
|
||||
func (m *MockConnectionSecretWriterTo) SetWriteConnectionSecretToReference(r *corev1.ObjectReference) {
|
||||
m.Ref = r
|
||||
}
|
||||
func (m *MockConnectionSecretWriterTo) GetWriteConnectionSecretToReference() *corev1.ObjectReference {
|
||||
return m.Ref
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +86,7 @@ type MockClaim struct {
|
|||
metav1.ObjectMeta
|
||||
MockClassReferencer
|
||||
MockManagedResourceReferencer
|
||||
MockConnectionSecretWriterTo
|
||||
MockLocalConnectionSecretWriterTo
|
||||
MockConditioned
|
||||
MockBindable
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func NewAPISecretPublisher(c client.Client, ot runtime.ObjectTyper) *APISecretPu
|
|||
// exists with the supplied ConnectionDetails.
|
||||
func (a *APISecretPublisher) PublishConnection(ctx context.Context, mg Managed, c ConnectionDetails) error {
|
||||
// This resource does not want to expose a connection secret.
|
||||
if mg.GetWriteConnectionSecretToReference().Name == "" {
|
||||
if mg.GetWriteConnectionSecretToReference() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
}
|
||||
|
||||
mgname := "coolmanaged"
|
||||
mgcsnamespace := "coolnamespace"
|
||||
mgcsname := "coolmanagedsecret"
|
||||
mgcsdata := map[string][]byte{
|
||||
"cool": []byte("data"),
|
||||
|
|
@ -163,7 +164,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &MockManaged{
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
c: ConnectionDetails{},
|
||||
},
|
||||
|
|
@ -183,7 +184,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &MockManaged{
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
c: ConnectionDetails{},
|
||||
},
|
||||
|
|
@ -195,6 +196,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
MockGet: test.NewMockGetFn(kerrors.NewNotFound(schema.GroupResource{}, "")),
|
||||
MockCreate: test.NewMockCreateFn(nil, func(got runtime.Object) error {
|
||||
want := &corev1.Secret{}
|
||||
want.SetNamespace(mgcsnamespace)
|
||||
want.SetName(mgcsname)
|
||||
want.SetOwnerReferences([]metav1.OwnerReference{{
|
||||
Name: mgname,
|
||||
|
|
@ -215,7 +217,40 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
ctx: context.Background(),
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Namespace: mgcsnamespace, Name: mgcsname}},
|
||||
},
|
||||
c: ConnectionDetails(cddata),
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
"SuccessfulCreateInDefaultNamespace": {
|
||||
fields: fields{
|
||||
client: &test.MockClient{
|
||||
MockGet: test.NewMockGetFn(kerrors.NewNotFound(schema.GroupResource{}, "")),
|
||||
MockCreate: test.NewMockCreateFn(nil, func(got runtime.Object) error {
|
||||
want := &corev1.Secret{}
|
||||
want.SetNamespace(corev1.NamespaceDefault)
|
||||
want.SetName(mgcsname)
|
||||
want.SetOwnerReferences([]metav1.OwnerReference{{
|
||||
Name: mgname,
|
||||
APIVersion: MockGVK(&MockManaged{}).GroupVersion().String(),
|
||||
Kind: MockGVK(&MockManaged{}).Kind,
|
||||
Controller: &controller,
|
||||
}})
|
||||
want.Data = cddata
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("-want, +got:\n%s", diff)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
typer: MockSchemeWith(&MockManaged{}),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
c: ConnectionDetails(cddata),
|
||||
},
|
||||
|
|
@ -226,6 +261,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
client: &test.MockClient{
|
||||
MockGet: func(_ context.Context, n types.NamespacedName, o runtime.Object) error {
|
||||
s := &corev1.Secret{}
|
||||
s.SetNamespace(corev1.NamespaceDefault)
|
||||
s.SetName(mgcsname)
|
||||
s.SetOwnerReferences([]metav1.OwnerReference{{
|
||||
Name: mgname,
|
||||
|
|
@ -238,6 +274,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
},
|
||||
MockUpdate: test.NewMockUpdateFn(nil, func(got runtime.Object) error {
|
||||
want := &corev1.Secret{}
|
||||
want.SetNamespace(corev1.NamespaceDefault)
|
||||
want.SetName(mgcsname)
|
||||
want.SetOwnerReferences([]metav1.OwnerReference{{
|
||||
Name: mgname,
|
||||
|
|
@ -258,7 +295,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
ctx: context.Background(),
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
c: ConnectionDetails(cddata),
|
||||
},
|
||||
|
|
@ -269,6 +306,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
client: &test.MockClient{
|
||||
MockGet: func(_ context.Context, n types.NamespacedName, o runtime.Object) error {
|
||||
s := &corev1.Secret{}
|
||||
s.SetNamespace(corev1.NamespaceDefault)
|
||||
s.SetName(mgcsname)
|
||||
s.SetOwnerReferences([]metav1.OwnerReference{{
|
||||
Name: mgname,
|
||||
|
|
@ -282,6 +320,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
},
|
||||
MockUpdate: test.NewMockUpdateFn(nil, func(got runtime.Object) error {
|
||||
want := &corev1.Secret{}
|
||||
want.SetNamespace(corev1.NamespaceDefault)
|
||||
want.SetName(mgcsname)
|
||||
want.SetOwnerReferences([]metav1.OwnerReference{{
|
||||
Name: mgname,
|
||||
|
|
@ -306,7 +345,7 @@ func TestAPISecretPublisher(t *testing.T) {
|
|||
ctx: context.Background(),
|
||||
mg: &MockManaged{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: mgname},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: corev1.LocalObjectReference{Name: mgcsname}},
|
||||
MockConnectionSecretWriterTo: MockConnectionSecretWriterTo{Ref: &corev1.ObjectReference{Name: mgcsname}},
|
||||
},
|
||||
c: ConnectionDetails(cddata),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,18 +28,46 @@ import (
|
|||
"github.com/crossplaneio/crossplane-runtime/pkg/meta"
|
||||
)
|
||||
|
||||
// A ConnectionSecretOwner may create and manage a connection secret.
|
||||
// A LocalConnectionSecretOwner may create and manage a connection secret in its
|
||||
// own namespace.
|
||||
type LocalConnectionSecretOwner interface {
|
||||
metav1.Object
|
||||
LocalConnectionSecretWriterTo
|
||||
}
|
||||
|
||||
// LocalConnectionSecretFor creates a connection secret in the namespace of the
|
||||
// supplied LocalConnectionSecretOwner, assumed to be of the supplied kind.
|
||||
func LocalConnectionSecretFor(o LocalConnectionSecretOwner, kind schema.GroupVersionKind) *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: o.GetNamespace(),
|
||||
Name: o.GetWriteConnectionSecretToReference().Name,
|
||||
OwnerReferences: []metav1.OwnerReference{meta.AsController(meta.ReferenceTo(o, kind))},
|
||||
},
|
||||
Data: make(map[string][]byte),
|
||||
}
|
||||
}
|
||||
|
||||
// A ConnectionSecretOwner may create and manage a connection secret in an
|
||||
// arbitrary namespace.
|
||||
type ConnectionSecretOwner interface {
|
||||
metav1.Object
|
||||
ConnectionSecretWriterTo
|
||||
}
|
||||
|
||||
// ConnectionSecretFor the supplied ConnectionSecretOwner, assumed to be of the
|
||||
// supplied kind.
|
||||
// ConnectionSecretFor creates a connection for the supplied
|
||||
// ConnectionSecretOwner, assumed to be of the supplied kind. The secret is
|
||||
// written to 'default' namespace if the ConnectionSecretOwner does not specify
|
||||
// a namespace.
|
||||
func ConnectionSecretFor(o ConnectionSecretOwner, kind schema.GroupVersionKind) *corev1.Secret {
|
||||
ns := o.GetWriteConnectionSecretToReference().Namespace
|
||||
if ns == "" {
|
||||
ns = corev1.NamespaceDefault
|
||||
}
|
||||
|
||||
return &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: o.GetNamespace(),
|
||||
Namespace: ns,
|
||||
Name: o.GetWriteConnectionSecretToReference().Name,
|
||||
OwnerReferences: []metav1.OwnerReference{meta.AsController(meta.ReferenceTo(o, kind))},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -32,10 +32,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
namespace = "coolns"
|
||||
name = "cool"
|
||||
secretName = "coolsecret"
|
||||
uid = types.UID("definitely-a-uuid")
|
||||
namespace = "coolns"
|
||||
name = "cool"
|
||||
uid = types.UID("definitely-a-uuid")
|
||||
)
|
||||
|
||||
var MockOwnerGVK = schema.GroupVersionKind{
|
||||
|
|
@ -44,19 +43,24 @@ var MockOwnerGVK = schema.GroupVersionKind{
|
|||
Kind: "MockOwner",
|
||||
}
|
||||
|
||||
type MockOwner struct {
|
||||
type MockLocalOwner struct {
|
||||
metav1.ObjectMeta
|
||||
Ref corev1.LocalObjectReference
|
||||
}
|
||||
|
||||
func (m *MockOwner) GetWriteConnectionSecretToReference() corev1.LocalObjectReference {
|
||||
return corev1.LocalObjectReference{Name: secretName}
|
||||
func (m *MockLocalOwner) GetWriteConnectionSecretToReference() corev1.LocalObjectReference {
|
||||
return m.Ref
|
||||
}
|
||||
|
||||
func (m *MockOwner) SetWriteConnectionSecretToReference(_ corev1.LocalObjectReference) {}
|
||||
func (m *MockLocalOwner) SetWriteConnectionSecretToReference(r corev1.LocalObjectReference) {
|
||||
m.Ref = r
|
||||
}
|
||||
|
||||
func TestLocalConnectionSecretFor(t *testing.T) {
|
||||
secretName := "coolsecret"
|
||||
|
||||
func TestConnectionSecretFor(t *testing.T) {
|
||||
type args struct {
|
||||
o ConnectionSecretOwner
|
||||
o LocalConnectionSecretOwner
|
||||
kind schema.GroupVersionKind
|
||||
}
|
||||
|
||||
|
|
@ -68,11 +72,14 @@ func TestConnectionSecretFor(t *testing.T) {
|
|||
}{
|
||||
"Success": {
|
||||
args: args{
|
||||
o: &MockOwner{ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
UID: uid,
|
||||
}},
|
||||
o: &MockLocalOwner{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
UID: uid,
|
||||
},
|
||||
Ref: corev1.LocalObjectReference{Name: secretName},
|
||||
},
|
||||
kind: MockOwnerGVK,
|
||||
},
|
||||
want: &corev1.Secret{
|
||||
|
|
@ -91,6 +98,98 @@ func TestConnectionSecretFor(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got := LocalConnectionSecretFor(tc.args.o, tc.args.kind)
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Errorf("LocalConnectionSecretFor(): -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type MockOwner struct {
|
||||
metav1.ObjectMeta
|
||||
Ref *corev1.ObjectReference
|
||||
}
|
||||
|
||||
func (m *MockOwner) GetWriteConnectionSecretToReference() *corev1.ObjectReference {
|
||||
return m.Ref
|
||||
}
|
||||
|
||||
func (m *MockOwner) SetWriteConnectionSecretToReference(r *corev1.ObjectReference) {
|
||||
m.Ref = r
|
||||
}
|
||||
|
||||
func TestConnectionSecretFor(t *testing.T) {
|
||||
secretName := "coolsecret"
|
||||
|
||||
type args struct {
|
||||
o ConnectionSecretOwner
|
||||
kind schema.GroupVersionKind
|
||||
}
|
||||
|
||||
controller := true
|
||||
|
||||
cases := map[string]struct {
|
||||
args args
|
||||
want *corev1.Secret
|
||||
}{
|
||||
"SpecifiedNamespace": {
|
||||
args: args{
|
||||
o: &MockOwner{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
UID: uid,
|
||||
},
|
||||
Ref: &corev1.ObjectReference{Namespace: namespace, Name: secretName},
|
||||
},
|
||||
kind: MockOwnerGVK,
|
||||
},
|
||||
want: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: secretName,
|
||||
OwnerReferences: []metav1.OwnerReference{{
|
||||
APIVersion: MockOwnerGVK.GroupVersion().String(),
|
||||
Kind: MockOwnerGVK.Kind,
|
||||
Name: name,
|
||||
UID: uid,
|
||||
Controller: &controller,
|
||||
}},
|
||||
},
|
||||
Data: map[string][]byte{},
|
||||
},
|
||||
},
|
||||
"DefaultNamespace": {
|
||||
args: args{
|
||||
o: &MockOwner{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
UID: uid,
|
||||
},
|
||||
Ref: &corev1.ObjectReference{Name: secretName},
|
||||
},
|
||||
kind: MockOwnerGVK,
|
||||
},
|
||||
want: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: corev1.NamespaceDefault,
|
||||
Name: secretName,
|
||||
OwnerReferences: []metav1.OwnerReference{{
|
||||
APIVersion: MockOwnerGVK.GroupVersion().String(),
|
||||
Kind: MockOwnerGVK.Kind,
|
||||
Name: name,
|
||||
UID: uid,
|
||||
Controller: &controller,
|
||||
}},
|
||||
},
|
||||
Data: map[string][]byte{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got := ConnectionSecretFor(tc.args.o, tc.args.kind)
|
||||
|
|
|
|||
Loading…
Reference in New Issue