Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions pkg/generate/code/resource_reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ func ReferenceFieldsValidation(
// are related to the given concrete field, determining whether its in a valid
// condition and updating the concrete field with the referenced value.
//
// The generated code calls ackrt.ResolveCrossNamespaceReference to validate
// the reference and, when the reference targets a different namespace and
// the cross-namespace flag is enabled, emit a deprecation warning and set
// the ACK.CrossNamespaceOptInRequired condition on the resource. When the
// flag is disabled, the helper returns a terminal error.
//
// Sample output (resolving a singular reference):
//
// if ko.Spec.APIRef != nil && ko.Spec.APIRef.From != nil {
Expand All @@ -130,6 +136,18 @@ func ReferenceFieldsValidation(
// if arr.Name == nil || *arr.Name == "" {
// return hasReferences, fmt.Errorf("provided resource reference is nil or empty: APIRef")
// }
// namespace, err := ackrt.ResolveCrossNamespaceReference(
// ctx,
// rm.cfg.EnableCrossNamespace,
// &ko.Status.Conditions,
// ackrt.CrossNamespaceRefKindResource,
// ko.ObjectMeta.GetNamespace(),
// arr.Namespace,
// *arr.Name,
// )
// if err != nil {
// return hasReferences, err
// }
// obj := &svcapitypes.API{}
// if err := getReferencedResourceState_API(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
// return hasReferences, err
Expand All @@ -146,6 +164,10 @@ func ReferenceFieldsValidation(
// if arr.Name == nil || *arr.Name == "" {
// return hasReferences, fmt.Errorf("provided resource reference is nil or empty: SecurityGroupRefs")
// }
// namespace, err := ackrt.ResolveCrossNamespaceReference( ... )
// if err != nil {
// return hasReferences, err
// }
// obj := &ec2apitypes.SecurityGroup{}
// if err := getReferencedResourceState_SecurityGroup(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
// return hasReferences, err
Expand All @@ -170,6 +192,10 @@ func ReferenceFieldsValidation(
// if arr.Name == nil || *arr.Name == "" {
// return hasReferences, fmt.Errorf("provided resource reference is nil or empty: Notification.LambdaFunctionConfigurations.Filter.Key.FilterRules.ValueRef")
// }
// namespace, err := ackrt.ResolveCrossNamespaceReference( ... )
// if err != nil {
// return hasReferences, err
// }
// obj := &svcapitypes.Bucket{}
// if err := getReferencedResourceState_Bucket(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
// return hasReferences, err
Expand Down Expand Up @@ -228,9 +254,17 @@ func ResolveReferencesForField(field *model.Field, sourceVarName string, indentL
outPrefix += fmt.Sprintf("%s\treturn hasReferences, fmt.Errorf(\"provided resource reference is nil or empty: %s\")\n", innerIndent, refFieldPath)
outPrefix += fmt.Sprintf("%s}\n", innerIndent)

outPrefix += fmt.Sprintf("%snamespace := ko.ObjectMeta.GetNamespace()\n", innerIndent)
outPrefix += fmt.Sprintf("%sif arr.Namespace != nil && *arr.Namespace != \"\" {\n", innerIndent)
outPrefix += fmt.Sprintf("%s\tnamespace = *arr.Namespace\n", innerIndent)
outPrefix += fmt.Sprintf("%snamespace, err := ackrt.ResolveCrossNamespaceReference(\n", innerIndent)
outPrefix += fmt.Sprintf("%s\tctx,\n", innerIndent)
outPrefix += fmt.Sprintf("%s\trm.cfg.EnableCrossNamespace,\n", innerIndent)
outPrefix += fmt.Sprintf("%s\t&ko.Status.Conditions,\n", innerIndent)
outPrefix += fmt.Sprintf("%s\tackrt.CrossNamespaceRefKindResource,\n", innerIndent)
outPrefix += fmt.Sprintf("%s\tko.ObjectMeta.GetNamespace(),\n", innerIndent)
outPrefix += fmt.Sprintf("%s\tarr.Namespace,\n", innerIndent)
outPrefix += fmt.Sprintf("%s\t*arr.Name,\n", innerIndent)
outPrefix += fmt.Sprintf("%s)\n", innerIndent)
outPrefix += fmt.Sprintf("%sif err != nil {\n", innerIndent)
outPrefix += fmt.Sprintf("%s\treturn hasReferences, err\n", innerIndent)
outPrefix += fmt.Sprintf("%s}\n", innerIndent)

outPrefix += getReferencedStateForField(field, innerIndentLevel)
Expand Down
98 changes: 77 additions & 21 deletions pkg/generate/code/resource_reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,17 @@ func Test_ResolveReferencesForField_SingleReference(t *testing.T) {
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: APIRef")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &svcapitypes.API{}
if err := getReferencedResourceState_API(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down Expand Up @@ -180,9 +188,17 @@ func Test_ResolveReferencesForField_ReferencingARN(t *testing.T) {
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: PermissionsBoundaryRef")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &svcapitypes.Policy{}
if err := getReferencedResourceState_Policy(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down Expand Up @@ -217,9 +233,17 @@ func Test_ResolveReferencesForField_SliceOfReferences(t *testing.T) {
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: SecurityGroupRefs")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &ec2apitypes.SecurityGroup{}
if err := getReferencedResourceState_SecurityGroup(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down Expand Up @@ -258,9 +282,17 @@ func Test_ResolveReferencesForField_NestedSingleReference(t *testing.T) {
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: JWTConfiguration.IssuerRef")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &svcapitypes.API{}
if err := getReferencedResourceState_API(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down Expand Up @@ -299,9 +331,17 @@ func Test_ResolveReferencesForField_SingleReference_DeeplyNested(t *testing.T) {
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: Logging.LoggingEnabled.TargetBucketRef")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &svcapitypes.Bucket{}
if err := getReferencedResourceState_Bucket(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down Expand Up @@ -340,9 +380,17 @@ func Test_ResolveReferencesForField_SingleReference_WithinSlice(t *testing.T) {
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: Routes.GatewayRef")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &svcapitypes.InternetGateway{}
if err := getReferencedResourceState_InternetGateway(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down Expand Up @@ -384,9 +432,17 @@ func Test_ResolveReferencesForField_SingleReference_WithinMultipleSlices(t *test
if arr.Name == nil || *arr.Name == "" {
return hasReferences, fmt.Errorf("provided resource reference is nil or empty: Notification.LambdaFunctionConfigurations.Filter.Key.FilterRules.ValueRef")
}
namespace := ko.ObjectMeta.GetNamespace()
if arr.Namespace != nil && *arr.Namespace != "" {
namespace = *arr.Namespace
namespace, err := ackrt.ResolveCrossNamespaceReference(
ctx,
rm.cfg.EnableCrossNamespace,
&ko.Status.Conditions,
ackrt.CrossNamespaceRefKindResource,
ko.ObjectMeta.GetNamespace(),
arr.Namespace,
*arr.Name,
)
if err != nil {
return hasReferences, err
}
obj := &svcapitypes.Bucket{}
if err := getReferencedResourceState_Bucket(ctx, apiReader, obj, *arr.Name, namespace); err != nil {
Expand Down
55 changes: 44 additions & 11 deletions pkg/generate/code/set_sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -1099,26 +1099,31 @@ func setSDKForContainer(

// setSDKForSecret returns a string of Go code that sets a target variable to
// the value of a Secret when the type of the source variable is a
// SecretKeyReference.
// SecretKeyReference. It first calls ResolveCrossNamespaceReferenceString to
// validate cross-namespace access (and emit a deprecation warning + condition
// when the reference is cross-namespace), then fetches the secret value.
//
// The Go code output from this function looks like this:
//
// tmpSecret, err := rm.rr.SecretValueFromReference(ctx, ko.Spec.MasterUserPassword)
// secretNamespace, err := ackrt.ResolveCrossNamespaceReferenceString(
// ctx,
// rm.cfg.EnableCrossNamespace,
// &r.ko.Status.Conditions,
// ackrt.CrossNamespaceRefKindSecret,
// r.ko.ObjectMeta.GetNamespace(),
// ko.Spec.MasterUserPassword.Namespace,
// ko.Spec.MasterUserPassword.Name,
// )
// if err != nil {
// return nil, ackrequeue.Needed(err)
// return nil, err
// }
// if tmpSecret != "" {
// res.SetMasterUserPassword(tmpSecret)
// }
//
// or:
//
// tmpSecret, err := rm.rr.SecretValueFromReference(ctx, f3iter)
// ko.Spec.MasterUserPassword.Namespace = secretNamespace
// tmpSecret, err := rm.rr.SecretValueFromReference(ctx, ko.Spec.MasterUserPassword)
// if err != nil {
// return nil, ackrequeue.Needed(err)
// }
// if tmpSecret != "" {
// f3elem = tmpSecret
// res.SetMasterUserPassword(tmpSecret)
// }
//
// The second case is used when the SecretKeyReference field
Expand All @@ -1140,6 +1145,34 @@ func setSDKForSecret(
indent := strings.Repeat("\t", indentLevel)
secVar := "tmpSecret"

// Resolve cross-namespace access before fetching the secret
// secretNamespace, err := ackrt.ResolveCrossNamespaceReferenceString(
// ctx,
// rm.cfg.EnableCrossNamespace,
// &r.ko.Status.Conditions,
// ackrt.CrossNamespaceRefKindSecret,
// r.ko.ObjectMeta.GetNamespace(),
// sourceVarName.Namespace,
// sourceVarName.Name,
// )
out += fmt.Sprintf(
"%s\tsecretNamespace, err := ackrt.ResolveCrossNamespaceReferenceString(\n",
indent,
)
out += fmt.Sprintf("%s\t\tctx,\n", indent)
out += fmt.Sprintf("%s\t\trm.cfg.EnableCrossNamespace,\n", indent)
out += fmt.Sprintf("%s\t\t&r.ko.Status.Conditions,\n", indent)
out += fmt.Sprintf("%s\t\tackrt.CrossNamespaceRefKindSecret,\n", indent)
out += fmt.Sprintf("%s\t\tr.ko.ObjectMeta.GetNamespace(),\n", indent)
out += fmt.Sprintf("%s\t\t%s.Namespace,\n", indent, sourceVarName)
out += fmt.Sprintf("%s\t\t%s.Name,\n", indent, sourceVarName)
out += fmt.Sprintf("%s\t)\n", indent)
out += fmt.Sprintf("%s\tif err != nil {\n", indent)
out += fmt.Sprintf("%s\t\treturn nil, err\n", indent)
out += fmt.Sprintf("%s\t}\n", indent)
// Override the secret reference namespace with the resolved namespace
out += fmt.Sprintf("%s\t%s.Namespace = secretNamespace\n", indent, sourceVarName)

// tmpSecret, err := rm.rr.SecretValueFromReference(ctx, ko.Spec.MasterUserPassword)
out += fmt.Sprintf(
"%s\t%s, err := rm.rr.SecretValueFromReference(ctx, %s)\n",
Expand Down
Loading