Skip to content

Commit

Permalink
feat: add isSynced to Status and patch Status
Browse files Browse the repository at this point in the history
  • Loading branch information
henninge committed Jan 31, 2022
1 parent 7760c52 commit 1921de8
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 18 deletions.
1 change: 1 addition & 0 deletions api/v1beta1/awsauthmapsnippet_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type AwsAuthMapSnippetStatus struct {

RoleArns []string `json:"roleArns,omitempty"`
UserArns []string `json:"userArns,omitempty"`
IsSynced bool `json:"isSynced,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
2 changes: 2 additions & 0 deletions config/crd/bases/crd.awsauth.io_awsauthmapsnippets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ spec:
status:
description: AwsAuthMapSnippetStatus defines the observed state of AwsAuthMapSnippet.
properties:
isSynced:
type: boolean
roleArns:
items:
type: string
Expand Down
34 changes: 21 additions & 13 deletions controllers/awsauthmapsnippet_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,37 +98,45 @@ func (r *AwsAuthMapSnippetReconciler) Reconcile(ctx context.Context, req ctrl.Re
return ctrl.Result{}, nil
}

// Prepare patch, remember original resource content
original := snippet.DeepCopy()
defer func() {
if err := r.UpdateSnippetStatus(ctx, snippet, original); err != nil {
logger.Error(err, "Failed to update status")
}
}()

snippet.Status.IsSynced = false

logger.Info("Updating ConfigMap")
if err := r.UpdateConfigMap(ctx, snippet, awsauthmap); err != nil {
logger.Error(err, "Failed to update ConfigMap")
return ctrl.Result{}, err
}

if err := r.UpdateSnippetStatus(ctx, snippet); err != nil {
logger.Error(err, "Failed to update status")
return ctrl.Result{}, err
}

logger.Info("Reconciliation completed")
snippet.Status.IsSynced = true

return ctrl.Result{}, nil
}

/*
UpdateSnippetStatus stores the ARNS that are being managed in the status
sub-object und updates the status.
*/
func (r *AwsAuthMapSnippetReconciler) UpdateSnippetStatus(ctx context.Context, snippet *crdv1beta1.AwsAuthMapSnippet) error {
func (r *AwsAuthMapSnippetReconciler) UpdateSnippetStatus(ctx context.Context, current, original *crdv1beta1.AwsAuthMapSnippet) error {

snippet.Status.RoleArns = []string{}
snippet.Status.UserArns = []string{}
// Overwrite lists with current
current.Status.RoleArns = []string{}
current.Status.UserArns = []string{}

for _, mr := range snippet.Spec.MapRoles {
snippet.Status.RoleArns = append(snippet.Status.RoleArns, mr.RoleArn)
for _, mr := range current.Spec.MapRoles {
current.Status.RoleArns = append(current.Status.RoleArns, mr.RoleArn)
}
for _, mu := range snippet.Spec.MapUsers {
snippet.Status.UserArns = append(snippet.Status.UserArns, mu.UserArn)
for _, mu := range current.Spec.MapUsers {
current.Status.UserArns = append(current.Status.UserArns, mu.UserArn)
}
return r.Status().Update(ctx, snippet)
return r.Status().Patch(ctx, current, client.MergeFrom(original))
}

/*
Expand Down
48 changes: 46 additions & 2 deletions controllers/awsauthmapsnippet_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
)

var _ = Describe("snippet controller", func() {

It("should update status", func() {
const USER_ARN = "arn:aws:iam::123456789012:user/foobar"
snip := &crdv1beta1.AwsAuthMapSnippet{
Expand All @@ -31,6 +30,7 @@ var _ = Describe("snippet controller", func() {
},
},
},
Status: crdv1beta1.AwsAuthMapSnippetStatus{IsSynced: false},
}
err := k8sClient.Create(context.Background(), snip)
Expect(err).ToNot(HaveOccurred())
Expand All @@ -44,14 +44,18 @@ var _ = Describe("snippet controller", func() {
if err != nil {
return false
}
if !snip.Status.IsSynced {
return false
}
if len(snip.Status.UserArns) != 1 {
return false
}
return snip.Status.UserArns[0] == USER_ARN
}, time.Second*10, time.Second).Should(BeTrue())

})
It("should create the ConfigMap", func() {

It("should set isSync to false on failure", func() {
const USER_ARN = "arn:aws:iam::123456789012:user/foobar"
snip := &crdv1beta1.AwsAuthMapSnippet{
ObjectMeta: v1.ObjectMeta{
Expand All @@ -67,6 +71,46 @@ var _ = Describe("snippet controller", func() {
},
},
},
Status: crdv1beta1.AwsAuthMapSnippetStatus{IsSynced: false},
}
k8sClient.FailUpdateName = "aws-auth"
defer func() {
k8sClient.FailUpdateName = ""
}()

err := k8sClient.Create(context.Background(), snip)
Expect(err).ToNot(HaveOccurred())

Consistently(func() bool {
// check if status exists
err = k8sClient.Get(context.Background(), types.NamespacedName{
Name: snip.Name,
Namespace: snip.Namespace,
}, snip)
if err != nil {
return true
}
return snip.Status.IsSynced
}, time.Second*10, time.Second).Should(BeFalse())

})
It("should create the ConfigMap", func() {
const USER_ARN = "arn:aws:iam::123456789012:user/foobar"
snip := &crdv1beta1.AwsAuthMapSnippet{
ObjectMeta: v1.ObjectMeta{
Name: "testsnip3",
Namespace: "default",
},
Spec: crdv1beta1.AwsAuthMapSnippetSpec{
MapUsers: []crdv1beta1.MapUsersSpec{
{
UserArn: USER_ARN,
UserName: "foobar-name",
Groups: []string{"foobar-group"},
},
},
},
Status: crdv1beta1.AwsAuthMapSnippetStatus{IsSynced: false},
}
err := k8sClient.Create(context.Background(), snip)
Expect(err).ToNot(HaveOccurred())
Expand Down
25 changes: 22 additions & 3 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package controllers

import (
"context"
"errors"
"path/filepath"
"testing"

Expand All @@ -40,7 +42,7 @@ import (
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.

var cfg *rest.Config
var k8sClient client.Client
var k8sClient *FakeApiClient
var testEnv *envtest.Environment

func TestAPIs(t *testing.T) {
Expand All @@ -51,6 +53,20 @@ func TestAPIs(t *testing.T) {
[]Reporter{printer.NewlineReporter{}})
}

type FakeApiClient struct {
client.Client

FailUpdateName string
}

func (f *FakeApiClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
if obj.GetName() == f.FailUpdateName {
return errors.New("Conflict")
}

return f.Client.Update(ctx, obj, opts...)
}

var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))

Expand All @@ -69,9 +85,12 @@ var _ = BeforeSuite(func() {

//+kubebuilder:scaffold:scheme

k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
realClient, err := client.New(cfg, client.Options{Scheme: scheme.Scheme})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())
Expect(realClient).NotTo(BeNil())

k8sClient = &FakeApiClient{}
k8sClient.Client = realClient

k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme.Scheme,
Expand Down

0 comments on commit 1921de8

Please sign in to comment.