Skip to content

Commit

Permalink
Ctor for authconfigmap from K8s ClientSet
Browse files Browse the repository at this point in the history
  • Loading branch information
rndstr committed Mar 13, 2019
1 parent d87c13a commit 065837d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 73 deletions.
59 changes: 32 additions & 27 deletions pkg/authconfigmap/authconfigmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package authconfigmap
import (
"fmt"

"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/kris-nova/logger"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -40,7 +41,7 @@ const (

// RoleNodeGroupUsername is the default username for a nodegroup
// role mapping.
RoleNodeGroupUsername = "system:node:{{EC2PrivateDNSName}}"
RoleNodeGroupUsername = "system:node:{{EC2PrivateDNSName}}"
)

// RoleNodeGroupGroups are the groups to allow roles to interact
Expand All @@ -49,20 +50,34 @@ var RoleNodeGroupGroups = []string{"system:bootstrappers", "system:nodes"}

// AuthConfigMap allows modifying the auth ConfigMap.
type AuthConfigMap struct {
cm *corev1.ConfigMap
client v1.ConfigMapInterface
cm *corev1.ConfigMap
}

// New creates an AuthConfigMap instance that manipulates
// a ConfigMap. If it is nil, one is created.
func New(cm *corev1.ConfigMap) *AuthConfigMap {
a := &AuthConfigMap{cm: cm}
if a.cm == nil {
a.cm = &corev1.ConfigMap{
func New(client v1.ConfigMapInterface, cm *corev1.ConfigMap) *AuthConfigMap {
if cm == nil {
cm = &corev1.ConfigMap{
ObjectMeta: ObjectMeta(),
Data: map[string]string{},
}
}
return a
return &AuthConfigMap{client: client, cm: cm}
}

// NewFromClientSet fetches the auth ConfigMap.
func NewFromClientSet(clientSet kubernetes.Interface) (*AuthConfigMap, error) {
client := clientSet.CoreV1().ConfigMaps(ObjectNamespace)

// check if object exists
cm, err := client.Get(ObjectName, metav1.GetOptions{})
// It is fine for the configmap not to exist. Any other error is fatal.
if err != nil && !kerr.IsNotFound(err) {
return nil, errors.Wrapf(err, "getting auth ConfigMap")
}
logger.Debug("aws-auth = %s", awsutil.Prettify(cm))
return New(client, cm), nil
}

// AddAccount appends an IAM account to the `mapAccounts` entry
Expand Down Expand Up @@ -177,13 +192,13 @@ func (a *AuthConfigMap) setRoles(r mapRoles) error {

// Save persists the ConfigMap to the cluster. It determines
// whether to create or update by looking at the ConfigMap's UID.
func (a *AuthConfigMap) Save(client v1.ConfigMapInterface) (err error) {
func (a *AuthConfigMap) Save() (err error) {
if a.cm.UID == "" {
a.cm, err = client.Create(a.cm)
a.cm, err = a.client.Create(a.cm)
return err
}

a.cm, err = client.Update(a.cm)
a.cm, err = a.client.Update(a.cm)
return err
}

Expand All @@ -198,20 +213,14 @@ func ObjectMeta() metav1.ObjectMeta {
// AddNodeGroup creates or adds a nodegroup IAM role in the auth
// ConfigMap for the given nodegroup.
func AddNodeGroup(clientSet kubernetes.Interface, ng *api.NodeGroup) error {
client := clientSet.CoreV1().ConfigMaps(ObjectNamespace)

// check if object exists
cm, err := client.Get(ObjectName, metav1.GetOptions{})
if err != nil && !kerr.IsNotFound(err) {
// something must have gone terribly wrong
return errors.Wrapf(err, "getting auth ConfigMap")
acm, err := NewFromClientSet(clientSet)
if err != nil {
return err
}

acm := New(cm)
if err := acm.AddRole(ng.IAM.InstanceRoleARN, RoleNodeGroupUsername, RoleNodeGroupGroups); err != nil {
return errors.Wrap(err, "adding nodegroup to auth ConfigMap")
}
if err := acm.Save(client); err != nil {
if err := acm.Save(); err != nil {
return errors.Wrap(err, "saving auth ConfigMap")
}
logger.Debug("saved auth ConfigMap for %q", ng.Name)
Expand All @@ -221,18 +230,14 @@ func AddNodeGroup(clientSet kubernetes.Interface, ng *api.NodeGroup) error {
// RemoveNodeGroup removes a nodegroup from the ConfigMap and
// does a client update.
func RemoveNodeGroup(clientSet kubernetes.Interface, ng *api.NodeGroup) error {
client := clientSet.CoreV1().ConfigMaps(ObjectNamespace)

cm, err := client.Get(ObjectName, metav1.GetOptions{})
acm, err := NewFromClientSet(clientSet)
if err != nil {
return errors.Wrapf(err, "getting auth ConfigMap")
return err
}

acm := New(cm)
if err := acm.RemoveRole(ng.IAM.InstanceRoleARN); err != nil {
return errors.Wrap(err, "removing nodegroup from auth ConfigMap")
}
if err := acm.Save(client); err != nil {
if err := acm.Save(); err != nil {
return errors.Wrap(err, "updating auth ConfigMap after removing role")
}
logger.Debug("updated auth ConfigMap for %s", ng.Name)
Expand Down
76 changes: 43 additions & 33 deletions pkg/authconfigmap/authconfigmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ var (
expectedB = makeExpectedRole(roleB, []string{groupB})
)

// mockClient implements v1.ConfigMapInterface
type mockClient struct {
v1.ConfigMapInterface
created *corev1.ConfigMap
updated *corev1.ConfigMap
}

func (c *mockClient) Create(cm *corev1.ConfigMap) (*corev1.ConfigMap, error) {
cm.ObjectMeta.UID = "18b9e60c-2057-11e7-8868-0eba8ef9df1a"
c.created = cm
return cm, nil
}

func (c *mockClient) Update(cm *corev1.ConfigMap) (*corev1.ConfigMap, error) {
c.updated = cm
return cm, nil
}

func (c *mockClient) reset() {
c.updated = nil
c.created = nil
}

func makeExpectedRole(arn string, groups []string) string {
return fmt.Sprintf(`- rolearn: %s
username: system:node:{{EC2PrivateDNSName}}
Expand All @@ -45,30 +68,13 @@ func makeExpectedAccounts(accounts ...string) string {
return y
}

// mockClient implements v1.ConfigMapInterface
type mockClient struct {
v1.ConfigMapInterface
created *corev1.ConfigMap
updated *corev1.ConfigMap
}

func (c *mockClient) Create(cm *corev1.ConfigMap) (*corev1.ConfigMap, error) {
cm.ObjectMeta.UID = "18b9e60c-2057-11e7-8868-0eba8ef9df1a"
c.created = cm
return cm, nil
}

func (c *mockClient) Update(cm *corev1.ConfigMap) (*corev1.ConfigMap, error) {
c.updated = cm
return cm, nil
}

var _ = Describe("AuthConfigMap{}", func() {
Describe("New()", func() {
It("should create an empty configmap", func() {
acm := New(nil)
client := &mockClient{}
err := acm.Save(client)
acm := New(client, nil)
err := acm.Save()
Expect(err).NotTo(HaveOccurred())
Expect(client.updated).To(BeNil())

Expand All @@ -86,9 +92,9 @@ var _ = Describe("AuthConfigMap{}", func() {
}
cm.ObjectMeta.UID = "123456"

acm := New(cm)
client := &mockClient{}
err := acm.Save(client)
acm := New(client, cm)
err := acm.Save()
Expect(err).NotTo(HaveOccurred())
Expect(client.created).To(BeNil())

Expand All @@ -103,14 +109,15 @@ var _ = Describe("AuthConfigMap{}", func() {
Data: map[string]string{},
}
cm.UID = "123456"
acm := New(cm)
client := &mockClient{}
acm := New(client, cm)

addAndSave := func(arn string, groups []string) *corev1.ConfigMap {
client.reset()
err := acm.AddRole(arn, RoleNodeGroupUsername, groups)
Expect(err).NotTo(HaveOccurred())

client := &mockClient{}
err = acm.Save(client)
err = acm.Save()
Expect(err).NotTo(HaveOccurred())
Expect(client.created).To(BeNil())
Expect(client.updated).NotTo(BeNil())
Expand Down Expand Up @@ -138,14 +145,15 @@ var _ = Describe("AuthConfigMap{}", func() {
Data: map[string]string{"mapRoles": expectedA + expectedA + expectedB},
}
cm.UID = "123456"
acm := New(cm)
client := &mockClient{}
acm := New(client, cm)

removeAndSave := func(arn string) *corev1.ConfigMap {
client.reset()
err := acm.RemoveRole(arn)
Expect(err).NotTo(HaveOccurred())

client := &mockClient{}
err = acm.Save(client)
err = acm.Save()
Expect(err).NotTo(HaveOccurred())

return client.updated
Expand Down Expand Up @@ -174,14 +182,15 @@ var _ = Describe("AuthConfigMap{}", func() {
Data: map[string]string{},
}
cm.UID = "123456"
acm := New(cm)
client := &mockClient{}
acm := New(client, cm)

addAndSave := func(account string) *corev1.ConfigMap {
client.reset()
err := acm.AddAccount(account)
Expect(err).NotTo(HaveOccurred())

client := &mockClient{}
err = acm.Save(client)
err = acm.Save()
Expect(err).NotTo(HaveOccurred())
Expect(client.created).To(BeNil())
Expect(client.updated).NotTo(BeNil())
Expand All @@ -208,14 +217,15 @@ var _ = Describe("AuthConfigMap{}", func() {
Data: map[string]string{"mapAccounts": makeExpectedAccounts(accountA) + makeExpectedAccounts(accountB)},
}
cm.UID = "123456"
acm := New(cm)
client := &mockClient{}
acm := New(client, cm)

removeAndSave := func(account string) *corev1.ConfigMap {
client.reset()
err := acm.RemoveAccount(account)
Expect(err).NotTo(HaveOccurred())

client := &mockClient{}
err = acm.Save(client)
err = acm.Save()
Expect(err).NotTo(HaveOccurred())
Expect(client.created).To(BeNil())
Expect(client.updated).NotTo(BeNil())
Expand Down
18 changes: 5 additions & 13 deletions pkg/ctl/utils/aws_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ package utils

import (
"fmt"
"github.com/aws/aws-sdk-go/aws/awsutil"
"os"

"github.com/kris-nova/logger"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
kerr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha4"
"github.com/weaveworks/eksctl/pkg/authconfigmap"
Expand Down Expand Up @@ -77,26 +74,21 @@ func doAWSAuth(p *api.ProviderConfig, cfg *api.ClusterConfig, nameArg string) er
}

clientSet, err := ctl.NewStdClientSet(cfg)
client := clientSet.CoreV1().ConfigMaps(authconfigmap.ObjectNamespace)

obj, err := client.Get(authconfigmap.ObjectName, metav1.GetOptions{})
// It is fine for the configmap not to exist. Any other error is fatal.
if err != nil && !kerr.IsNotFound(err) {
return errors.Wrapf(err, "getting auth ConfigMap")
if err != nil {
return err
}
acm, err := authconfigmap.NewFromClientSet(clientSet)

logger.Debug("aws-auth = %s", awsutil.Prettify(obj))

if len(awsAuthAddAdminRoles) == 0 && len(awsAuthRemoveRoles) == 0 &&
len(awsAuthAddAccounts) == 0 && len(awsAuthRemoveAccounts) == 0 {
logger.Info("no actions given, use --{add,remove}-{role-account}")
return nil
}

acm := authconfigmap.New(obj)
// Roles.
for _, r := range awsAuthAddAdminRoles {
if err := acm.AddRole(r, []string{authconfigmap.GroupMasters}); err != nil {
if err := acm.AddRole(r, authconfigmap.RoleNodeGroupUsername, []string{authconfigmap.GroupMasters}); err != nil {
return errors.Wrap(err, "adding role to auth ConfigMap")
}
}
Expand All @@ -118,7 +110,7 @@ func doAWSAuth(p *api.ProviderConfig, cfg *api.ClusterConfig, nameArg string) er
}
}

if err := acm.Save(client); err != nil {
if err := acm.Save(); err != nil {
return errors.Wrap(err, "updating auth ConfigMap")
}
logger.Success("saved auth ConfigMap")
Expand Down

0 comments on commit 065837d

Please sign in to comment.