diff --git a/packages/@aws-cdk/aws-eks/lib/k8s-patch.ts b/packages/@aws-cdk/aws-eks/lib/k8s-patch.ts index 812a4f73b043c..7a755cc1d3a02 100644 --- a/packages/@aws-cdk/aws-eks/lib/k8s-patch.ts +++ b/packages/@aws-cdk/aws-eks/lib/k8s-patch.ts @@ -3,7 +3,8 @@ import { Construct, Stack } from "@aws-cdk/core"; import { Cluster } from "./cluster"; import { KubectlProvider } from "./kubectl-provider"; -export interface CoreDnsComputeTypeProps { +export interface CoreDnsComputeTypeProps extends KubernetesPatchProps {} +export interface KubernetesPatchProps { /** * The cluster to apply the patch to. */ @@ -30,6 +31,20 @@ export interface CoreDnsComputeTypeProps { * @default "default" */ readonly resourceNamespace?: string; + + /** + * The patch type to pass to `kubectl patch`. + * The default type used by `kubectl patch` is "strategic". + * + * @default "strategic" + */ + readonly patchType?: PatchType; +} + +export enum PatchType { + JSON = "json", + MERGE = "merge", + STRATEGIC = "strategic" } /** @@ -37,7 +52,7 @@ export interface CoreDnsComputeTypeProps { * Kubernetes resource. */ export class KubernetesPatch extends Construct { - constructor(scope: Construct, id: string, props: CoreDnsComputeTypeProps) { + constructor(scope: Construct, id: string, props: KubernetesPatchProps) { super(scope, id); const stack = Stack.of(this); @@ -52,8 +67,9 @@ export class KubernetesPatch extends Construct { ApplyPatchJson: stack.toJsonString(props.applyPatch), RestorePatchJson: stack.toJsonString(props.restorePatch), ClusterName: props.cluster.clusterName, - RoleArn: props.cluster._getKubectlCreationRoleArn(provider.role) + RoleArn: props.cluster._getKubectlCreationRoleArn(provider.role), + PatchType: props.patchType ?? PatchType.STRATEGIC } }); } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py index b427b71f6342b..d6211b9348e1e 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py @@ -33,6 +33,7 @@ def patch_handler(event, context): resource_namespace = props['ResourceNamespace'] apply_patch_json = props['ApplyPatchJson'] restore_patch_json = props['RestorePatchJson'] + patch_type = props['PatchType'] patch_json = None if request_type == 'Create' or request_type == 'Update': @@ -42,7 +43,7 @@ def patch_handler(event, context): else: raise Exception("invalid request type %s" % request_type) - kubectl([ 'patch', resource_name, '-n', resource_namespace, '-p', patch_json ]) + kubectl([ 'patch', resource_name, '-n', resource_namespace, '-p', patch_json, '--type', patch_type ]) def kubectl(args): diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json index 4e0fd0d7605a5..de1aa505baf0b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json @@ -1756,7 +1756,7 @@ }, "/", { - "Ref": "AssetParameters6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859S3BucketBA51B749" + "Ref": "AssetParametersb2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87S3BucketB4483E96" }, "/", { @@ -1766,7 +1766,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859S3VersionKey723A87EA" + "Ref": "AssetParametersb2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87S3VersionKey0402E731" } ] } @@ -1779,7 +1779,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859S3VersionKey723A87EA" + "Ref": "AssetParametersb2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87S3VersionKey0402E731" } ] } @@ -1789,11 +1789,11 @@ ] }, "Parameters": { - "referencetoawscdkeksclustertestAssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2S3Bucket5C1311C2Ref": { - "Ref": "AssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2S3Bucket8A1A4BE8" + "referencetoawscdkeksclustertestAssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbS3Bucket6A8A7186Ref": { + "Ref": "AssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbS3Bucket0C3A00C2" }, - "referencetoawscdkeksclustertestAssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2S3VersionKey33922910Ref": { - "Ref": "AssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2S3VersionKeyB580A234" + "referencetoawscdkeksclustertestAssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbS3VersionKeyA18C5C39Ref": { + "Ref": "AssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbS3VersionKeyBED95764" }, "referencetoawscdkeksclustertestAssetParameters6c3e21f76e4ba0bc4b901f71bfa9c1eaf7929edcfd9a1591690d12b024100044S3Bucket24E1CF9DRef": { "Ref": "AssetParameters6c3e21f76e4ba0bc4b901f71bfa9c1eaf7929edcfd9a1591690d12b024100044S3Bucket75CDEB48" @@ -1901,29 +1901,29 @@ "Type": "String", "Description": "Artifact hash for asset \"6c3e21f76e4ba0bc4b901f71bfa9c1eaf7929edcfd9a1591690d12b024100044\"" }, - "AssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2S3Bucket8A1A4BE8": { + "AssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbS3Bucket0C3A00C2": { "Type": "String", - "Description": "S3 bucket for asset \"809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2\"" + "Description": "S3 bucket for asset \"a6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afb\"" }, - "AssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2S3VersionKeyB580A234": { + "AssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbS3VersionKeyBED95764": { "Type": "String", - "Description": "S3 key for asset version \"809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2\"" + "Description": "S3 key for asset version \"a6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afb\"" }, - "AssetParameters809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2ArtifactHash5CE7C76A": { + "AssetParametersa6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afbArtifactHashBF08C2D7": { "Type": "String", - "Description": "Artifact hash for asset \"809b8ac7e88704d37fac32bbd5cfa56be7ea4d3e9ddb682d216c4b6868cd8fa2\"" + "Description": "Artifact hash for asset \"a6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afb\"" }, - "AssetParameters6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859S3BucketBA51B749": { + "AssetParametersb2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87S3BucketB4483E96": { "Type": "String", - "Description": "S3 bucket for asset \"6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859\"" + "Description": "S3 bucket for asset \"b2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87\"" }, - "AssetParameters6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859S3VersionKey723A87EA": { + "AssetParametersb2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87S3VersionKey0402E731": { "Type": "String", - "Description": "S3 key for asset version \"6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859\"" + "Description": "S3 key for asset version \"b2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87\"" }, - "AssetParameters6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859ArtifactHash22D2ECF0": { + "AssetParametersb2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87ArtifactHash1FD4BC6F": { "Type": "String", - "Description": "Artifact hash for asset \"6a008e167065eeab066c7f96e7f3c21c2636476b93c075681fba2953ae54a859\"" + "Description": "Artifact hash for asset \"b2a83bc01824acea756ffd355b4f53ae58aacffc1525dc8c75796ebb74cd8f87\"" }, "AssetParameters6348c4414dfcbc19ed407c51ecc75d12faf4ee3219e972437d4ceed53e5b79a0S3BucketEF51ACE0": { "Type": "String", diff --git a/packages/@aws-cdk/aws-eks/test/test.k8s-patch.ts b/packages/@aws-cdk/aws-eks/test/test.k8s-patch.ts index 9aa05c2f94c0d..4a22aa4b72b6c 100644 --- a/packages/@aws-cdk/aws-eks/test/test.k8s-patch.ts +++ b/packages/@aws-cdk/aws-eks/test/test.k8s-patch.ts @@ -2,7 +2,7 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { Stack } from '@aws-cdk/core'; import { Test } from 'nodeunit'; import * as eks from '../lib'; -import { KubernetesPatch } from '../lib/k8s-patch'; +import { KubernetesPatch, PatchType } from '../lib/k8s-patch'; export = { 'applies a patch to k8s'(test: Test) { @@ -41,5 +41,64 @@ export = { } })); test.done(); + }, + 'defaults to "strategic" patch type if no patchType is specified'(test: Test) { + // GIVEN + const stack = new Stack(); + const cluster = new eks.Cluster(stack, 'MyCluster'); + + // WHEN + new KubernetesPatch(stack, 'MyPatch', { + cluster, + applyPatch: { patch: { to: 'apply' } }, + restorePatch: { restore: { patch: 123 }}, + resourceName: 'myResourceName', + }); + expect(stack).to(haveResource('Custom::AWSCDK-EKS-KubernetesPatch', { + PatchType: "strategic" + })); + test.done(); + }, + 'uses specified to patch type if specified'(test: Test) { + // GIVEN + const stack = new Stack(); + const cluster = new eks.Cluster(stack, 'MyCluster'); + + // WHEN + new KubernetesPatch(stack, 'jsonPatch', { + cluster, + applyPatch: { patch: { to: 'apply' } }, + restorePatch: { restore: { patch: 123 }}, + resourceName: 'jsonPatchResource', + patchType: PatchType.JSON + }); + new KubernetesPatch(stack, 'mergePatch', { + cluster, + applyPatch: { patch: { to: 'apply' } }, + restorePatch: { restore: { patch: 123 }}, + resourceName: 'mergePatchResource', + patchType: PatchType.MERGE + }); + new KubernetesPatch(stack, 'strategicPatch', { + cluster, + applyPatch: { patch: { to: 'apply' } }, + restorePatch: { restore: { patch: 123 }}, + resourceName: 'strategicPatchResource', + patchType: PatchType.STRATEGIC + }); + + expect(stack).to(haveResource('Custom::AWSCDK-EKS-KubernetesPatch', { + ResourceName: "jsonPatchResource", + PatchType: "json" + })); + expect(stack).to(haveResource('Custom::AWSCDK-EKS-KubernetesPatch', { + ResourceName: "mergePatchResource", + PatchType: "merge" + })); + expect(stack).to(haveResource('Custom::AWSCDK-EKS-KubernetesPatch', { + ResourceName: "strategicPatchResource", + PatchType: "strategic" + })); + test.done(); } }; \ No newline at end of file