Skip to content

Commit

Permalink
Merge pull request #173 from ajpaws/main
Browse files Browse the repository at this point in the history
Adding new pattern for Crossplane Argocd GitOps
  • Loading branch information
elamaran11 authored Sep 17, 2024
2 parents 1336bc1 + ffaac77 commit 8cd7f95
Show file tree
Hide file tree
Showing 16 changed files with 1,129 additions and 0 deletions.
10 changes: 10 additions & 0 deletions bin/crossplane-argocd-gitops.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { errorHandler } from '../lib/common/construct-utils';
import MultiClusterPipelineConstruct from "../lib/crossplane-argocd-gitops/multi-cluster-pipeline";

const app = new cdk.App();

new MultiClusterPipelineConstruct().buildAsync(app, "crossplane-argocd-gitops").catch((e) => {
errorHandler(app, "Pipeline construct failed because of error: ", e);
});
466 changes: 466 additions & 0 deletions docs/patterns/crossplane-argocd-gitops.md

Large diffs are not rendered by default.

Binary file added docs/patterns/images/amd-add-on.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/patterns/images/arm-add-on.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/patterns/images/aws_secret_codepipeline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/patterns/images/codepipeline1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/patterns/images/codepipeline2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import 'source-map-support/register';
import * as blueprints from '@aws-quickstart/eks-blueprints';
import * as eks from "aws-cdk-lib/aws-eks";
import { Construct } from 'constructs';
import { dependable } from '@aws-quickstart/eks-blueprints/dist/utils';
import { UpboundCrossplaneAddOn } from './upbound-crossplane-addon';

export class CrossplaneHelmProviderAddon implements blueprints.ClusterAddOn {
id?: string | undefined;
readonly helmProviderVersion: string;
constructor(helmProviderVersion: string) {
this.helmProviderVersion = helmProviderVersion;
}

@dependable(UpboundCrossplaneAddOn.name)
deploy(clusterInfo: blueprints.ClusterInfo): void | Promise<Construct> {
const cluster = clusterInfo.cluster;

const roleBinding = {
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "ClusterRoleBinding",
metadata: {
name: "helm-provider"
},
subjects: [
{
kind: "ServiceAccount",
name: "helm-provider",
namespace: "upbound-system"
}
],
roleRef: {
kind: "ClusterRole",
name: "cluster-admin",
apiGroup: "rbac.authorization.k8s.io"
}
};

const runtimeConfig = {
apiVersion: "pkg.crossplane.io/v1beta1",
kind: "DeploymentRuntimeConfig",
metadata: {
name: "helm-runtime-config"
},
spec: {
deploymentTemplate: {
spec: {
replicas: 1,
selector: {},
template: {}
}
},
serviceAccountTemplate: {
metadata: { name: "helm-provider" }
}
}
};

const provider = {
apiVersion: "pkg.crossplane.io/v1",
kind: "Provider",
metadata: { name: "helm-provider" },
spec: {
package: 'xpkg.upbound.io/crossplane-contrib/provider-helm:'+this.helmProviderVersion,
runtimeConfigRef: {
name: "helm-runtime-config"
}
}
};

const runtimeHelmConfig = new eks.KubernetesManifest(clusterInfo.cluster.stack, "runtimeHelmConfig", {
cluster: cluster,
manifest: [roleBinding, runtimeConfig]
});

const awsHelmProvider = new eks.KubernetesManifest(clusterInfo.cluster.stack, "providerHelmResource", {
cluster: cluster,
manifest: [provider]
});

awsHelmProvider.node.addDependency(runtimeHelmConfig);
return Promise.resolve(runtimeHelmConfig);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import 'source-map-support/register';
import * as blueprints from '@aws-quickstart/eks-blueprints';
import * as eks from "aws-cdk-lib/aws-eks";
import { Construct } from 'constructs';
import { dependable } from '@aws-quickstart/eks-blueprints/dist/utils';
import { UpboundCrossplaneAddOn } from './upbound-crossplane-addon';

export class CrossplaneK8sProviderAddon implements blueprints.ClusterAddOn {
id?: string | undefined;
readonly k8sProviderVersion: string;
constructor(k8sProviderVersion: string) {
this.k8sProviderVersion = k8sProviderVersion;
}

@dependable(UpboundCrossplaneAddOn.name)
deploy(clusterInfo: blueprints.ClusterInfo): void | Promise<Construct> {
const cluster = clusterInfo.cluster;

const roleBinding = {
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "ClusterRoleBinding",
metadata: { name: "kubernetes-provider" },
subjects: [
{
kind: "ServiceAccount",
name: "kubernetes-provider",
namespace: "upbound-system"
}
],
roleRef: {
kind: "ClusterRole",
name: "cluster-admin",
apiGroup: "rbac.authorization.k8s.io"
}
};

const runtimeConfig = {
apiVersion: "pkg.crossplane.io/v1beta1",
kind: "DeploymentRuntimeConfig",
metadata: {
name: "kubernetes-runtime-config"
},
spec: {
deploymentTemplate: {
spec: {
replicas: 1,
selector: {},
template: {}
}
},
serviceAccountTemplate: {
metadata: { name: "kubernetes-provider" }
}
}
};

const providerK8sResource = {
apiVersion: "pkg.crossplane.io/v1",
kind: "Provider",
metadata: { name: "kubernetes-provider" },
spec: {
package: 'xpkg.upbound.io/crossplane-contrib/provider-kubernetes:'+this.k8sProviderVersion,
runtimeConfigRef: {
name: "kubernetes-runtime-config"
}
}
};

const runtimeK8sConfig = new eks.KubernetesManifest(clusterInfo.cluster.stack, "runtimeK8sConfig", {
cluster: cluster,
manifest: [roleBinding, runtimeConfig]
});

const awsK8sProvider = new eks.KubernetesManifest(clusterInfo.cluster.stack, "awsK8sProvider", {
cluster: cluster,
manifest: [providerK8sResource]
});

awsK8sProvider.node.addDependency(runtimeK8sConfig);

return Promise.resolve(runtimeK8sConfig);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

import * as iam from 'aws-cdk-lib/aws-iam';
import { IManagedPolicy } from 'aws-cdk-lib/aws-iam';

import * as blueprints from '@aws-quickstart/eks-blueprints';

export class CreateNamedRoleProvider implements blueprints.ResourceProvider<iam.Role> {

/**
* Constructor to create role provider.
* @param roleId role id
* @param assumedBy @example new iam.ServicePrincipal('ec2.amazonaws.com')
* @param policies
*/
constructor(private roleId: string, private roleName: string, private assumedBy: iam.IPrincipal, private policies?: IManagedPolicy[]){}

provide(context: blueprints.ResourceContext): iam.Role {
return new iam.Role(context.scope, this.roleId, {
assumedBy: this.assumedBy,
managedPolicies: this.policies,
roleName: this.roleName
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import 'source-map-support/register';
import * as blueprints from '@aws-quickstart/eks-blueprints';
import { Construct } from 'constructs';
import { Values } from "@aws-quickstart/eks-blueprints/dist/spi";
import { merge } from "ts-deepmerge";
import { createNamespace } from '@aws-quickstart/eks-blueprints/dist/utils';
import { Policy, PolicyDocument} from 'aws-cdk-lib/aws-iam';
import * as cdk from 'aws-cdk-lib';

/**
* User provided options for the Helm Chart
*/
export interface UpboundCrossplaneAddOnProps extends blueprints.HelmAddOnUserProps {
/**
* To Create Namespace using CDK
*/
createNamespace?: boolean;
}

const defaultProps: blueprints.HelmAddOnProps = {
name: 'uxp',
release: 'blueprints-addon-uxp',
namespace: 'upbound-system',
chart: 'universal-crossplane',
version: '1.14.5-up.1',
repository: 'https://charts.upbound.io/stable',
values: {},
};

export class UpboundCrossplaneAddOn extends blueprints.HelmAddOn {

readonly options: UpboundCrossplaneAddOnProps;

constructor( props?: UpboundCrossplaneAddOnProps) {
super({...defaultProps, ...props});

this.options = this.props as UpboundCrossplaneAddOnProps;
}

deploy(clusterInfo: blueprints.ClusterInfo): void | Promise<Construct> {
const cluster = clusterInfo.cluster;

// Create the `upbound-system` namespace.
const ns = createNamespace(this.options.namespace!, cluster, true);

// Create the CrossPlane AWS Provider IRSA.
const serviceAccountName = "provider-aws";
const sa = cluster.addServiceAccount(serviceAccountName, {
name: serviceAccountName,
namespace: this.options.namespace!,
});
sa.node.addDependency(ns);
sa.role.attachInlinePolicy(new Policy(cluster.stack, 'eks-connect-policy', {
document: PolicyDocument.fromJson({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["sts:AssumeRole"],
"Resource": `arn:aws:iam::${cluster.stack.account}:role/eks-workload-connector-role`
},
{
"Effect": "Allow",
"Action": ["eks:*"],
"Resource": `*`
}
]
})}));

clusterInfo.addAddOnContext(UpboundCrossplaneAddOn.name, {
arn: sa.role.roleArn
});

new cdk.CfnOutput(cluster.stack, 'providerawssaiamrole',
{
value: sa.role.roleArn,
description: 'provider AWS IAM role',
exportName : 'providerawssaiamrole'
});

let values: Values = this.options.values ?? {};
values = merge(values, values);

const chart = this.addHelmChart(clusterInfo, values, false, true);
chart.node.addDependency(sa);
return Promise.resolve(chart);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import 'source-map-support/register';
import * as blueprints from '@aws-quickstart/eks-blueprints';
import * as eks from "aws-cdk-lib/aws-eks";
import { Construct } from 'constructs';
import { dependable } from '@aws-quickstart/eks-blueprints/dist/utils';
import { UpboundCrossplaneAddOn } from './upbound-crossplane-addon';
import { Policy, PolicyDocument} from 'aws-cdk-lib/aws-iam';

export class UpboundCrossplaneEKSProviderAddOn implements blueprints.ClusterAddOn {
id?: string | undefined;
readonly UpboundEKSProviderVersion: string;
constructor(UpboundEKSProviderVersion: string) {
this.UpboundEKSProviderVersion = UpboundEKSProviderVersion;
}
@dependable(UpboundCrossplaneAddOn.name)
deploy(clusterInfo: blueprints.ClusterInfo): void | Promise<Construct> {
const cluster = clusterInfo.cluster;

// Create the CrossPlane EKS Provider IRSA.
const serviceAccountName = "provider-aws-eks";
const upboundNamespace = "upbound-system";
const sa = cluster.addServiceAccount(serviceAccountName, {
name: serviceAccountName,
namespace: upboundNamespace,
});
sa.role.attachInlinePolicy(new Policy(cluster.stack, 'eks-workload-connector-policy', {
document: PolicyDocument.fromJson({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["sts:AssumeRole"],
"Resource": `arn:aws:iam::${cluster.stack.account}:role/eks-workload-connector-role`
},
{
"Effect": "Allow",
"Action": ["eks:*"],
"Resource": `*`
}
]
})}));

// clusterInfo.addAddOnContext(UpboundCrossplaneEKSProviderAddOn.name, {
// arn: sa.role.roleArn
// });

const runtimeConfig = new eks.KubernetesManifest(clusterInfo.cluster.stack, "runtimeConfig", {
cluster: cluster,
manifest: [
{
apiVersion: "pkg.crossplane.io/v1beta1",
kind: "DeploymentRuntimeConfig",
metadata: {
name: "aws-eks-runtime-config"
},
spec: {
deploymentTemplate: {
spec: {
replicas: 1,
selector: {},
template: {}
}
},
serviceAccountTemplate: {
metadata: { name: "provider-aws-eks" }
}
}
},
],
});

const awsEksProvider = new eks.KubernetesManifest(clusterInfo.cluster.stack, "EKSProvider", {
cluster: cluster,
manifest: [
{
apiVersion: "pkg.crossplane.io/v1",
kind: "Provider",
metadata: {
name: "provider-aws-eks",
},
spec: {
package: 'xpkg.upbound.io/upbound/provider-aws-eks:'+this.UpboundEKSProviderVersion,
runtimeConfigRef: {
name: "aws-eks-runtime-config"
}
},
},
],
});

// runtimeConfig.node.addDependency(sa);
awsEksProvider.node.addDependency(runtimeConfig);
return Promise.resolve(runtimeConfig);
}
}
Loading

0 comments on commit 8cd7f95

Please sign in to comment.