Skip to content

Commit 2d1b192

Browse files
committed
put CARMv2 map behind a feature flag and add service level isolation support
1 parent 96a54b3 commit 2d1b192

File tree

5 files changed

+100
-100
lines changed

5 files changed

+100
-100
lines changed

pkg/featuregate/features.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616
// optionally overridden.
1717
package featuregate
1818

19+
const (
20+
// CARMv2 is the name of the CARMv2 feature.
21+
CARMv2 = "CARMv2"
22+
)
23+
1924
// defaultACKFeatureGates is a map of feature names to Feature structs
2025
// representing the default feature gates for ACK controllers.
2126
var defaultACKFeatureGates = FeatureGates{
2227
// Set feature gates here
23-
// "feature1": {Stage: Alpha, Enabled: false},
28+
CARMv2: {Stage: Alpha, Enabled: false},
2429
}
2530

2631
// FeatureStage represents the development stage of a feature.

pkg/runtime/adoption_reconciler.go

+47-47
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
3434
ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config"
3535
ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors"
36+
"github.com/aws-controllers-k8s/runtime/pkg/featuregate"
3637
ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics"
3738
"github.com/aws-controllers-k8s/runtime/pkg/requeue"
3839
ackrtcache "github.com/aws-controllers-k8s/runtime/pkg/runtime/cache"
@@ -109,10 +110,6 @@ func (r *adoptionReconciler) reconcile(ctx context.Context, req ctrlrt.Request)
109110
return ackerr.NotAdoptable
110111
}
111112

112-
// If a user specified a namespace with role ARN annotation,
113-
// we need to get the role and set the accout ID to that role.
114-
teamID := r.getTeamID(res)
115-
116113
// If a user has specified a namespace that is annotated with the
117114
// an owner account ID, we need an appropriate role ARN to assume
118115
// in order to perform the reconciliation. The roles ARN are typically
@@ -123,31 +120,39 @@ func (r *adoptionReconciler) reconcile(ctx context.Context, req ctrlrt.Request)
123120
acctID, needCARMLookup := r.getOwnerAccountID(res)
124121

125122
var roleARN ackv1alpha1.AWSResourceName
126-
if teamID != "" {
127-
roleARN, err = r.getTeamRoleARN(teamID)
128-
if err != nil {
129-
ackrtlog.InfoAdoptedResource(r.log, res, fmt.Sprintf("Unable to start adoption reconcilliation %s: %v", acctID, err))
130-
// r.getRoleARN errors are not terminal, we should requeue.
131-
return requeue.NeededAfter(err, roleARNNotAvailableRequeueDelay)
132-
}
133-
parsedARN, err := arn.Parse(string(roleARN))
134-
if err != nil {
135-
return fmt.Errorf("failed to parsed role ARN %q from namespace annotation: %v", roleARN, err)
136-
}
137-
acctID = ackv1alpha1.AWSAccountID(parsedARN.AccountID)
138-
} else {
139-
if needCARMLookup {
140-
// This means that the user is specifying a namespace that is
141-
// annotated with an owner account ID or team ID. We need to retrieve the
142-
// roleARN from the ConfigMap and properly requeue if the roleARN
143-
// is not available.
144-
roleARN, err = r.getOwnerAccountRoleARN(acctID)
123+
if r.cfg.FeatureGates.IsEnabled(featuregate.CARMv2) {
124+
teamID := r.getTeamID(res)
125+
if teamID != "" {
126+
// The user is specifying a namespace that is annotated with a team ID.
127+
// Requeue if the corresponding roleARN is not available in the CARMv2 configmap.
128+
// Additionally, set the account ID to the role's account ID.
129+
roleARN, err = r.getRoleARNv2(string(teamID))
130+
if err != nil {
131+
ackrtlog.InfoAdoptedResource(r.log, res, fmt.Sprintf("Unable to start adoption reconcilliation %s: %v", acctID, err))
132+
return requeue.NeededAfter(err, roleARNNotAvailableRequeueDelay)
133+
}
134+
parsedARN, err := arn.Parse(string(roleARN))
135+
if err != nil {
136+
return fmt.Errorf("parsing role ARN %q from namespace annotation: %v", roleARN, err)
137+
}
138+
acctID = ackv1alpha1.AWSAccountID(parsedARN.AccountID)
139+
} else if needCARMLookup {
140+
// The user is specifying a namespace that is annotated with an owner account ID.
141+
// Requeue if the corresponding roleARN is not available in the CARMv2 configmap.
142+
roleARN, err = r.getRoleARNv2(string(acctID))
145143
if err != nil {
146144
ackrtlog.InfoAdoptedResource(r.log, res, fmt.Sprintf("Unable to start adoption reconcilliation %s: %v", acctID, err))
147-
// r.getRoleARN errors are not terminal, we should requeue.
148145
return requeue.NeededAfter(err, roleARNNotAvailableRequeueDelay)
149146
}
150147
}
148+
} else if needCARMLookup {
149+
// The user is specifying a namespace that is annotated with an owner account ID.
150+
// Requeue if the corresponding roleARN is not available in the Accounts (CARMv1) configmap.
151+
roleARN, err = r.getRoleARN(acctID)
152+
if err != nil {
153+
ackrtlog.InfoAdoptedResource(r.log, res, fmt.Sprintf("Unable to start adoption reconcilliation %s: %v", acctID, err))
154+
return requeue.NeededAfter(err, roleARNNotAvailableRequeueDelay)
155+
}
151156
}
152157

153158
region := r.getRegion(res)
@@ -512,34 +517,29 @@ func (r *adoptionReconciler) getEndpointURL(
512517
return r.cfg.EndpointURL
513518
}
514519

515-
// getRoleARN return the Role ARN that should be assumed for accoutn ID
516-
// in order to manage the resources.
517-
func (r *adoptionReconciler) getOwnerAccountRoleARN(
518-
acctID ackv1alpha1.AWSAccountID,
519-
) (ackv1alpha1.AWSResourceName, error) {
520-
roleARN, err := r.cache.CARMMaps.GetValue(ackrtcache.OwnerAccountIDPrefix + string(acctID))
521-
if err == ackrtcache.ErrCARMConfigMapNotFound || err == ackrtcache.ErrKeyNotFound {
522-
// CARM map v2 not defined. Check v1 map.
523-
roleARN, err = r.cache.Accounts.GetValue(string(acctID))
524-
if err != nil {
525-
return "", fmt.Errorf("unable to retrieve role ARN for account %s: %v", acctID, err)
526-
}
527-
} else if err != nil {
528-
return "", fmt.Errorf("unable to retrieve role ARN from CARM v2 for account %s: %v", acctID, err)
520+
// getRoleARNv2 returns the Role ARN that should be assumed for the given account/team ID,
521+
// from the CARMv2 configmap, in order to manage the resources.
522+
func (r *adoptionReconciler) getRoleARNv2(id string) (ackv1alpha1.AWSResourceName, error) {
523+
// use service level roleARN if present
524+
serviceID := r.sc.GetMetadata().ServiceAlias + "." + id
525+
if roleARN, err := r.cache.CARMMaps.GetValue(serviceID); err == nil {
526+
return ackv1alpha1.AWSResourceName(roleARN), nil
527+
}
528+
// otherwise use account/team level roleARN
529+
roleARN, err := r.cache.CARMMaps.GetValue(id)
530+
if err != nil {
531+
return "", fmt.Errorf("retrieving role ARN for account/team ID %q from %q configmap: %v", id, ackrtcache.ACKCARMMapV2, err)
529532
}
530533
return ackv1alpha1.AWSResourceName(roleARN), nil
531534
}
532535

533-
// getTeamRoleARN return the Role ARN that should be assumed for a team ID
534-
// in order to manage the resources.
535-
func (r *adoptionReconciler) getTeamRoleARN(
536-
teamID ackv1alpha1.TeamID,
537-
) (ackv1alpha1.AWSResourceName, error) {
538-
roleARN, err := r.cache.CARMMaps.GetValue(ackrtcache.TeamIDPrefix + string(teamID))
539-
if err == ackrtcache.ErrCARMConfigMapNotFound || err == ackrtcache.ErrKeyNotFound {
540-
return "", fmt.Errorf("unable to retrieve role ARN from CARM v2 for account %s: %v", teamID, err)
536+
// getRoleARN returns the Role ARN that should be assumed for the given account ID,
537+
// from the CARMv1 configmap, in order to manage the resources.
538+
func (r *adoptionReconciler) getRoleARN(acctID ackv1alpha1.AWSAccountID) (ackv1alpha1.AWSResourceName, error) {
539+
roleARN, err := r.cache.Accounts.GetValue(string(acctID))
540+
if err != nil {
541+
return "", fmt.Errorf("retrieving role ARN for account ID %q from %q configMap: %v", acctID, ackrtcache.ACKRoleAccountMap, err)
541542
}
542-
543543
return ackv1alpha1.AWSResourceName(roleARN), nil
544544
}
545545

pkg/runtime/cache/account.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ type CARMMap struct {
6060
// NewCARMMapCache instanciate a new CARMMap.
6161
func NewCARMMapCache(log logr.Logger) *CARMMap {
6262
return &CARMMap{
63-
log: log.WithName("cache.account"),
63+
log: log.WithName("cache.carm"),
6464
data: make(map[string]string),
6565
configMapCreated: false,
6666
}

pkg/runtime/cache/cache.go

-6
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ const (
4343
// caching system not to set up resyncs with an authoritative state source
4444
// (i.e. a Kubernetes API server) on a periodic basis.
4545
informerResyncPeriod = 0 * time.Second
46-
47-
// The prefix for owner account ID in the v2 CARM map.
48-
OwnerAccountIDPrefix = "owner-account-id/"
49-
50-
// The prefix for owner team ID in the v2 CARM map.
51-
TeamIDPrefix = "team-id/"
5246
)
5347

5448
// ackSystemNamespace is the namespace in which we look up ACK system

pkg/runtime/reconciler.go

+46-45
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
ackcondition "github.com/aws-controllers-k8s/runtime/pkg/condition"
4040
ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config"
4141
ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors"
42+
"github.com/aws-controllers-k8s/runtime/pkg/featuregate"
4243
ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics"
4344
"github.com/aws-controllers-k8s/runtime/pkg/requeue"
4445
ackrtcache "github.com/aws-controllers-k8s/runtime/pkg/runtime/cache"
@@ -226,10 +227,6 @@ func (r *resourceReconciler) Reconcile(ctx context.Context, req ctrlrt.Request)
226227
ctx = context.WithValue(ctx, ackrtlog.ContextKey, rlog)
227228
ctx = context.WithValue(ctx, "resourceNamespace", req.Namespace)
228229

229-
// If a user specified a namespace with team-id annotation,
230-
// we need to get the role and set the accout ID to that role.
231-
teamID := r.getTeamID(desired)
232-
233230
// If a user has specified a namespace that is annotated with the
234231
// an owner account ID, we need an appropriate role ARN to assume
235232
// in order to perform the reconciliation. The roles ARN are typically
@@ -240,28 +237,38 @@ func (r *resourceReconciler) Reconcile(ctx context.Context, req ctrlrt.Request)
240237
acctID, needCARMLookup := r.getOwnerAccountID(desired)
241238

242239
var roleARN ackv1alpha1.AWSResourceName
243-
if teamID != "" {
244-
roleARN, err = r.getTeamRoleARN(teamID)
245-
if err != nil {
246-
return r.handleCacheError(ctx, err, desired)
247-
}
248-
parsedARN, err := arn.Parse(string(roleARN))
249-
if err != nil {
250-
return ctrlrt.Result{}, fmt.Errorf("failed to parsed role ARN %q from namespace annotation: %v", roleARN, err)
251-
}
252-
acctID = ackv1alpha1.AWSAccountID(parsedARN.AccountID)
253-
} else {
254-
if needCARMLookup {
255-
// This means that the user is specifying a namespace that is
256-
// annotated with an owner account ID or team ID. We need to retrieve the
257-
// roleARN from the ConfigMap and properly requeue if the roleARN
258-
// is not available.
259-
roleARN, err = r.getOwnerAccountRoleARN(acctID)
240+
if r.cfg.FeatureGates.IsEnabled(featuregate.CARMv2) {
241+
teamID := r.getTeamID(desired)
242+
if teamID != "" {
243+
// The user is specifying a namespace that is annotated with a team ID.
244+
// Requeue if the corresponding roleARN is not available in the CARMv2 configmap.
245+
// Additionally, set the account ID to the role's account ID.
246+
roleARN, err = r.getRoleARNv2(string(teamID))
247+
if err != nil {
248+
return r.handleCacheError(ctx, err, desired)
249+
}
250+
parsedARN, err := arn.Parse(string(roleARN))
251+
if err != nil {
252+
return ctrlrt.Result{}, fmt.Errorf("parsing role ARN %q from namespace annotation: %v", roleARN, err)
253+
}
254+
acctID = ackv1alpha1.AWSAccountID(parsedARN.AccountID)
255+
} else if needCARMLookup {
256+
// The user is specifying a namespace that is annotated with an owner account ID.
257+
// Requeue if the corresponding roleARN is not available in the CARMv2 configmap.
258+
roleARN, err = r.getRoleARNv2(string(acctID))
260259
if err != nil {
261260
return r.handleCacheError(ctx, err, desired)
262261
}
263262
}
263+
} else if needCARMLookup {
264+
// The user is specifying a namespace that is annotated with an owner account ID.
265+
// Requeue if the corresponding roleARN is not available in the Accounts (CARMv1) configmap.
266+
roleARN, err = r.getRoleARN(acctID)
267+
if err != nil {
268+
return r.handleCacheError(ctx, err, desired)
269+
}
264270
}
271+
265272
region := r.getRegion(desired)
266273
endpointURL := r.getEndpointURL(desired)
267274
gvk := r.rd.GroupVersionKind()
@@ -1128,35 +1135,29 @@ func (r *resourceReconciler) getTeamID(
11281135
return ackv1alpha1.TeamID("")
11291136
}
11301137

1131-
// getRoleARN return the Role ARN that should be assumed for accoutn ID
1132-
// in order to manage the resources.
1133-
func (r *resourceReconciler) getOwnerAccountRoleARN(
1134-
acctID ackv1alpha1.AWSAccountID,
1135-
) (ackv1alpha1.AWSResourceName, error) {
1136-
roleARN, err := r.cache.CARMMaps.GetValue(ackrtcache.OwnerAccountIDPrefix + string(acctID))
1137-
if err == ackrtcache.ErrCARMConfigMapNotFound || err == ackrtcache.ErrKeyNotFound {
1138-
// CARM map v2 not defined. Check v1 map.
1139-
roleARN, err = r.cache.Accounts.GetValue(string(acctID))
1140-
if err != nil {
1141-
return "", fmt.Errorf("unable to retrieve role ARN for account %s: %v", acctID, err)
1142-
}
1143-
} else if err != nil {
1144-
return "", fmt.Errorf("unable to retrieve role ARN from CARM v2 for account %s: %v", acctID, err)
1138+
// getRoleARNv2 returns the Role ARN that should be assumed for the given account/team ID,
1139+
// from the CARMv2 configmap, in order to manage the resources.
1140+
func (r *resourceReconciler) getRoleARNv2(id string) (ackv1alpha1.AWSResourceName, error) {
1141+
// use service level roleARN if present
1142+
serviceID := r.sc.GetMetadata().ServiceAlias + "." + id
1143+
if roleARN, err := r.cache.CARMMaps.GetValue(serviceID); err == nil {
1144+
return ackv1alpha1.AWSResourceName(roleARN), nil
1145+
}
1146+
// otherwise use account/team level roleARN
1147+
roleARN, err := r.cache.CARMMaps.GetValue(id)
1148+
if err != nil {
1149+
return "", fmt.Errorf("retrieving role ARN for account/team ID %q from %q configmap: %v", id, ackrtcache.ACKCARMMapV2, err)
11451150
}
1146-
11471151
return ackv1alpha1.AWSResourceName(roleARN), nil
11481152
}
11491153

1150-
// getTeamRoleARN return the Role ARN that should be assumed for a team ID
1151-
// in order to manage the resources.
1152-
func (r *resourceReconciler) getTeamRoleARN(
1153-
teamID ackv1alpha1.TeamID,
1154-
) (ackv1alpha1.AWSResourceName, error) {
1155-
roleARN, err := r.cache.CARMMaps.GetValue(ackrtcache.TeamIDPrefix + string(teamID))
1156-
if err == ackrtcache.ErrCARMConfigMapNotFound || err == ackrtcache.ErrKeyNotFound {
1157-
return "", fmt.Errorf("unable to retrieve role ARN from CARM v2 for account %s: %v", teamID, err)
1154+
// getRoleARN returns the Role ARN that should be assumed for the given account ID,
1155+
// from the CARMv1 configmap, in order to manage the resources.
1156+
func (r *resourceReconciler) getRoleARN(acctID ackv1alpha1.AWSAccountID) (ackv1alpha1.AWSResourceName, error) {
1157+
roleARN, err := r.cache.Accounts.GetValue(string(acctID))
1158+
if err != nil {
1159+
return "", fmt.Errorf("retrieving role ARN for account ID %q from %q configMap: %v", acctID, ackrtcache.ACKRoleAccountMap, err)
11581160
}
1159-
11601161
return ackv1alpha1.AWSResourceName(roleARN), nil
11611162
}
11621163

0 commit comments

Comments
 (0)