diff --git a/docs/addons/upbound-universal-crossplane.md b/docs/addons/upbound-universal-crossplane.md index d47ec5e6a..b59a37b7d 100644 --- a/docs/addons/upbound-universal-crossplane.md +++ b/docs/addons/upbound-universal-crossplane.md @@ -4,12 +4,6 @@ The `Upbound Universal Crossplane Amazon EKS Add-on` allows Amazon Elastic Kuber Upbound Universal Crossplane (UXP) is Upbound's official enterprise-grade Crossplane distribution. It's free, open source, and fully conformant with upstream Crossplane. UXP is hardened and tested by Upbound so customers can confidently deploy control plane architectures to production. Connect UXP to Upbound Cloud is enabled with a free Upbound account for simplified management. -For more information on the driver, please review the [aws marketplace](https://aws.amazon.com/marketplace/pp/prodview-uhc2iwi5xysoc?ref_=aws-mp-console-subscription-detail) and please make sure to subscribe this product in marketplace before using this addon. - -## Prerequisites - -- Subscription to Upbound Universal Crossplane (UXP) in AWS Marketplace. - ## Usage ```typescript @@ -18,7 +12,9 @@ import * as blueprints from '@aws-quickstart/eks-blueprints'; const app = new cdk.App(); -const addOn = new blueprints.addons.UpboundUniversalCrossplaneAddOn(), +new blueprints.UpboundCrossplaneAddOn({ + clusterAccessRole: blueprints.getNamedResource("AdminRole") +}); const blueprint = blueprints.EksBlueprint.builder() .version("auto") @@ -26,29 +22,16 @@ const blueprint = blueprints.EksBlueprint.builder() .build(app, 'my-stack-name'); ``` -## Configuration Options - -- `version`: Version of the Upbound Universal Crossplane add-on to be installed. - -```bash -# Command to show versions of the UXP add-on -aws eks describe-addon-versions - --addon-name upbound_universal-crossplane \ - --kubernetes-version 1.24 \ - --query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \ - --output text - -# Output -v1.9.1-eksbuild.0 +iguration Options -``` +- `createNamespace`: (boolean) If you want CDK to create the namespace for you. +- `values`: Arbitrary values to pass to the chart. Refer to the FluxCD [Helm Chart documentation](https://artifacthub.io/packages/helm/fluxcd-community/flux2) for additional details. It also supports all standard helm configuration options ( for Eg: https://github.com/aws-quickstart/cdk-eks-blueprints/blob/main/docs/addons/index.md#standard-helm-add-on-configuration-options). ## Validation -To validate that EBS CSI Driver add-on is installed properly, ensure that the ebs pods are running in the cluster - +To validate that Upbound Crossplane add-on is installed properly: ```bash -kubectl get all -n upbound-syste +kubectl get all -n upbound-system # Output NAME READY STATUS RESTARTS AGE @@ -71,20 +54,6 @@ replicaset.apps/upbound-bootstrapper-844f84fcf4 1 1 1 25 replicaset.apps/xgql-55d7475b48 1 1 1 25m ``` -Additionally, the `aws cli` can be used to determine which version of the UXP add-on is installed in the cluster - -```bash -# Assuming cluster-name is my-cluster, below command shows the version of coredns installed. Check if it is same as the version installed via EKS add-on -aws eks describe-addon \ - --cluster-name my-cluster \ - --addon-name upbound_universal-crossplane \ - --query "addon.addonVersion" \ - --output text - -# Output -v1.9.1-eksbuild.0 -``` - ## Functionality Applies the Upbound Universal Crossplane add-on to an Amazon EKS cluster. diff --git a/examples/blueprint-construct/index.ts b/examples/blueprint-construct/index.ts index b3e1c08d4..4bd1facb0 100644 --- a/examples/blueprint-construct/index.ts +++ b/examples/blueprint-construct/index.ts @@ -232,7 +232,11 @@ export default class BlueprintConstruct { new blueprints.ExternalsSecretsAddOn(), new blueprints.EksPodIdentityAgentAddOn(), new blueprints.NeuronDevicePluginAddOn(), - new blueprints.NeuronMonitorAddOn() + new blueprints.NeuronMonitorAddOn(), + new blueprints.UpboundCrossplaneAddOn({ + skipVersionValidation: true, + clusterAccessRole: blueprints.getNamedResource("node-role") + }) ]; // Instantiated to for helm version check. diff --git a/lib/addons/index.ts b/lib/addons/index.ts index e871349fa..2a99d7be3 100644 --- a/lib/addons/index.ts +++ b/lib/addons/index.ts @@ -2,9 +2,11 @@ export * from './ack'; export * from './adot'; export * from './amp'; +export * from './apache-airflow'; export * from './appmesh'; export * from './argocd'; export * from './argocd/argo-gitops-factory'; +export * from './aws-batch-on-eks'; export * from './aws-for-fluent-bit'; export * from './aws-loadbalancer-controller'; export * from './aws-node-termination-handler'; @@ -19,6 +21,10 @@ export * from './cert-manager'; export * from './cluster-autoscaler'; export * from './container-insights'; export * from './coredns'; +export * from './ebs-csi-driver'; +export * from './efs-csi-driver'; +export * from './eks-pod-identity-agent'; +export * from './emr-on-eks'; export * from './external-dns'; export * from './external-secrets'; export * from './falco'; @@ -26,12 +32,21 @@ export * from './fluxcd'; export * from './gpu-operator'; export * from './grafana-operator'; export * from './helm-addon'; +export * from './istio-addons/istio-base'; +export * from './istio-addons/istio-control-plane'; +export * from './istio-addons/istio-cni'; +export * from './istio-addons/istio-ingress-gateway'; +export * from './jupyterhub'; export * from './karpenter'; +export * from './keda'; +export * from './knative-operator'; export * from './kube-proxy'; export * from './kube-state-metrics'; export * from './kuberay'; +export * from './kubevious'; export * from './metrics-server'; export * from './nested-stack'; +export * from './neuron'; export * from './nginx'; export * from './opa-gatekeeper'; export * from './prometheus-node-exporter'; @@ -39,27 +54,11 @@ export * from './secrets-store'; export * from './secrets-store/csi-driver-provider-aws-secrets'; export * from './secrets-store/secret-provider'; export * from './ssm-agent'; +export * from './upbound-universal-crossplane'; export * from './velero'; export * from './vpc-cni'; export * from './xray'; export * from './xray-adot-addon'; -export * from './keda'; -export * from './kubevious'; -export * from './ebs-csi-driver'; -export * from './efs-csi-driver'; -export * from './istio-addons/istio-base'; -export * from './istio-addons/istio-control-plane'; -export * from './istio-addons/istio-cni'; -export * from './istio-addons/istio-ingress-gateway'; -export * from './knative-operator'; -export * from './jupyterhub'; -export * from './emr-on-eks'; -export * from './aws-batch-on-eks'; -export * from './upbound-universal-crossplane'; -export * from './apache-airflow'; -export * from './neuron'; -export * from './eks-pod-identity-agent'; -export * from './neuron'; export class Constants { public static readonly BLUEPRINTS_ADDON = "blueprints-addon"; diff --git a/lib/addons/upbound-universal-crossplane/index.ts b/lib/addons/upbound-universal-crossplane/index.ts index 0afd8485b..36cad3a9b 100644 --- a/lib/addons/upbound-universal-crossplane/index.ts +++ b/lib/addons/upbound-universal-crossplane/index.ts @@ -1,36 +1,97 @@ -import { CoreAddOn } from "../core-addon"; -import { supportsX86 } from "../../utils"; +import 'source-map-support/register'; +import { Construct } from 'constructs'; +import {ClusterInfo, Values} from "../../spi"; +import { merge } from "ts-deepmerge"; +import {createNamespace, supportsALL} from '../../utils'; +import {IRole, Policy, PolicyDocument} from 'aws-cdk-lib/aws-iam'; +import * as cdk from 'aws-cdk-lib'; +import {HelmAddOn, HelmAddOnUserProps} from "../helm-addon"; /** - * Interface for Upbound Universal Crossplane EKS add-on options + * User provided options for the Helm Chart. */ -interface UpboundUniversalCrossplaneAddOnProps { +export interface UpboundCrossplaneAddOnProps extends HelmAddOnUserProps { /** - * Version of the driver to deploy + * To Create Namespace using CDK */ - version?: string; + createNamespace?: boolean; + /* + * EKS Cluster Access Role. + * This is a role with right permissions that will be used by CrossPlane AWS provider + * to provision AWS resources. + */ + clusterAccessRole: IRole; } -/** - * Default values for the add-on - */ const defaultProps = { - addOnName: "upbound_universal-crossplane", - version: "v1.9.1-eksbuild.0" + 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: {} }; -/** - * Implementation of Upbound Crossplane EKS add-on - */ -@supportsX86 -export class UpboundUniversalCrossplaneAddOn extends CoreAddOn { - - constructor(readonly options?: UpboundUniversalCrossplaneAddOnProps) { - super({ - addOnName: defaultProps.addOnName, - version: options?.version ?? defaultProps.version, - saName: "" - }); +@supportsALL +export class UpboundCrossplaneAddOn extends HelmAddOn { + + readonly options: UpboundCrossplaneAddOnProps; + + constructor( props?: UpboundCrossplaneAddOnProps) { + super({...defaultProps, ...props}); + + this.options = this.props as UpboundCrossplaneAddOnProps; } -} + deploy(clusterInfo: ClusterInfo): void | Promise { + 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": `${this.options.clusterAccessRole.roleArn}` + }, + { + "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); + } +} \ No newline at end of file