Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initalize File Structure #1

Merged
merged 2 commits into from
Feb 27, 2024
Merged
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
43 changes: 43 additions & 0 deletions .github/workflows/deploy-pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Pulumi Deploy
on:
push:
branches:
- main
paths:
- '**/*'
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
GITHUB_TOKEN: ${{ secrets.DEPLOY_PAT }}

jobs:
preview:
runs-on: ubuntu-latest
strategy:
fail-fast: false
# This IAM Matrix should have a name with the stack name and an iamRole
# with access to deploy AWS resources in you account. The easiest method is attaching AdministratorAccess Policy to role.
# See https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services for details on implementing OIDC with Github Actions
matrix:
arrays: [
stack: {name: "hub", iamRole: "arn:aws:iam::753080021511:role/pulumi-github-actions"},
]
permissions:
id-token: write
contents: read
name: Deploy
steps:
- uses: actions/checkout@v2
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ matrix.arrays.stack.iamRole }}
aws-region: us-east-2
- run: |
cd ./pulumi
npm install
- uses: pulumi/actions@v3
with:
color: auto
command: up
work-dir: ./pulumi
stack-name: ${{ matrix.arrays.stack.name }}
39 changes: 39 additions & 0 deletions .github/workflows/pr-pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Pulumi Prototype Preview
on:
- pull_request
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
GITHUB_TOKEN: ${{ secrets.DEPLOY_PAT }}

jobs:
preview:
runs-on: ubuntu-latest
strategy:
fail-fast: false
# This IAM Matrix should have a name with the stack name and an iamRole
# with access to deploy AWS resources in you account. The easiest method is attaching AdministratorAccess Policy to role
# See https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services for details on implementing OIDC with Github Actions
matrix:
arrays: [
stack: {name: "hub", iamRole: "arn:aws:iam::753080021511:role/pulumi-github-actions"},
]
permissions:
id-token: write
contents: read
name: Deploy
steps:
- uses: actions/checkout@v2
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ matrix.arrays.stack.iamRole }}
aws-region: us-east-2
- run: |
cd ./pulumi
npm install
- uses: pulumi/actions@v3
with:
color: auto
command: preview
work-dir: ./pulumi
stack-name: ${{ matrix.arrays.stack.name }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
***node_modules/
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
# gitopscon-2024-na-demo
# gitopscon-2024-na-demo

![Architecture Diagram of GitOps Flow with Gitops Bridge and Pulumi](assets/gitopscon-na24.png)

### File Structure

```
root/
.github/ # Contains Github Actions to deploy and preview Pulumi IaC
gitops/ # Contains Gitops Configuration
addons/ # Contains the Application Set Files and Addons we want
platform/ # Contains the platform level addons we want
team/ # Contains the Application Team addons we want
bootstrap/ # Contains the bootstrap application to deploy cluster secrets and applicationsets
charts/ # Contains Helm Charts and default values for configuration
platform/ # Contains Platform Helm Charts and default values
team/ # Contains Application Team Helm Charts and default values
clusters/ # Contains the cluster secret files
overrides/ # Contains Values file overrides
clusters/ # Contains Values file overrides for specific cluster
environments/ # Contains Values file overrides for specific cluster environments
pulumi/ # Contains the Pulumi code for the repository
bootstrap.sh # The bootstrap command to run to setup the hub cluster
Pulumi.hub.yaml # Contains configuration for the Pulumi Stack "hub"
Pulumi.dev.yaml # Contains configuration for the Pulumi Stack "dev"
```
Binary file added assets/gitopscon-na24.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added gitops/addons/.keep
Empty file.
22 changes: 22 additions & 0 deletions gitops/bootstrap/bootstrap-app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argo-bootstrap
spec:
project: default
syncPolicy:
automated:
prune: false
destination:
namespace: argocd
server: https://kubernetes.default.svc
sources:
- repoURL: https://github.com/gitops-bridge-dev/gitopscon-2024-na-demo
path: gitops/bootstrap
targetRevision: HEAD
- repoURL: https://github.com/ImagineLearning/otk-platform
path: gitops/clusters
targetRevision: HEAD
- repoURL: https://github.com/ImagineLearning/otk-platform
path: gitops/addons
targetRevision: HEAD
Empty file added gitops/charts/.keep
Empty file.
Empty file added gitops/clusters/.keep
Empty file.
13 changes: 13 additions & 0 deletions pulumi/Pulumi.dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
config:
aws:region: us-east-1
cidrBlock: 10.0.0.0/16
awsAccountId: "753080021511"
clusterType: "spoke"
hubStackName: "hub"
githubOrg: "gitops-bridge"
githubRepo: "gitopscon-2024-na-demo"
secretPath: "gitops/clusters/dev-cluster.yaml"
implementationType: "github"
clusterComponents: {}
adminClusterIamRole: "INSERT Iam Role ARN here"
adminClusterUser: "arn:aws:iam::753080021511:user/BlakeRomano"
12 changes: 12 additions & 0 deletions pulumi/Pulumi.hub.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
config:
aws:region: us-east-1
awsAccountId: "753080021511"
cidrBlock: 10.0.0.0/16
githubOrg: "gitops-bridge-dev"
githubRepo: "gitopscon-2024-na-demo"
secretPath: "gitops/clusters/hub-cluster.yaml"
clusterType: "hub"
implementationType: "github"
clusterComponents: {}
adminClusterIamRole: "INSERT Iam Role ARN here"
adminClusterUser: "arn:aws:iam::753080021511:user/BlakeRomano"
3 changes: 3 additions & 0 deletions pulumi/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: gitopscon-2024-na-demo
runtime: nodejs
description: GitOpsCon 2024 North America Demo Project
28 changes: 28 additions & 0 deletions pulumi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Pulumi Typescript GitOps Bridge

### How to Start Your Hub Cluster:

1. Create applicable stack files you need - The `Pulumi.dev.yaml` and `Pulumi.hub.yaml` each correspond to one stack for your hub cluster and one stack for a development environment spoke cluster
2. Create a GitOps Repo - Add a README.md and stub out the files you will be adding the ArgoCD Cluster secrets to.
3. Update configuration values as you need - You will want to update Stack Files with configuration for Github Repo/Org, as well as AWS Account ID, CIDRs, etc;
4. Add any extra resources you may need in your given environment
5. Add an Environment Variable for `GITHUB_TOKEN` in your deployment env (local, Github Actions, AWS Code Pipeline, etc;)
6. `pulumi up --stack hub`
7. Wait for the Resources to create like VPC, EKS Cluster, and IAM permissions
8. Run `./bootstrap.sh`


### How to Add Spoke Clusters:

1. Add any extra resources you may need in your given environment
2. Add an Environment Variable for `GITHUB_TOKEN` in your deployment env (local, Github Actions, AWS Code Pipeline, etc;)
3. Run Pulumi Up for the Spoke Cluster's Stack `pulumi up --stack dev`
4. Wait for the Resources to create like VPC, EKS Cluster, and IAM permissions
5. Apply the Secret resource that was added to the GitOps Repository

### Productionizing your Implementation

* Add Authentication for ArgoCD to be able to grab from your Organization's private repository
* Add ApplicationSets to your configuration by looking at the GitOps Bridge Control Plane Template for resources you need
* Create an ArgoCD Application that manages deployment of your Cluster Secret
* Move your EKS Cluster to be a private access endpoint
17 changes: 17 additions & 0 deletions pulumi/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

export AWS_PROFILE=default

# Add EKS cluster to kubeconfig
aws eks --region us-east-1 update-kubeconfig --name hub-cluster --alias hub-cluster

# Install ArgoCD
kubectl create namespace argocd --context hub-cluster
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml --context hub-cluster

kubectl apply -f "../gitops/bootstrap/hub-cluster.yaml"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file hub-cluster.yaml doesn't exist

kubectl apply -f "../gitops/bootstrap/bootstrap-app.yaml"

# Echo command to port forward ArgoCD and get admin password
echo "To port forward ArgoCD run: kubectl -n argocd port-forward svc/argocd-server 8080:443 &"
echo "Password can be retrieved by running: kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d"
98 changes: 98 additions & 0 deletions pulumi/github.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import * as pulumi from "@pulumi/pulumi";
import * as github from "@pulumi/github";
import * as yaml from 'js-yaml';
import { getValue } from "./utils"
import { env } from "process";

export class GitOpsClusterConfig {
private config: pulumi.Config;
private outputs: {[key: string]: pulumi.Output<any>};

constructor(outputs: {[key: string]: pulumi.Output<any>}, config: pulumi.Config, clusterAuthority: pulumi.Output<string>) {
this.config = config
this.outputs = outputs
const annotations = this.generateAnnotations(pulumi.getStack())
const serverConfig = this.generateConfig(clusterAuthority)
getValue(pulumi.all([annotations, serverConfig]).apply(([annotations, serverConfig]) => {
return {
apiVersion: "v1",
kind: "Secret",
metadata: {
labels: this.generateLabels(),
annotations: annotations,
name: `${pulumi.getStack()}-cluster-secret`,
namespace: "argocd",
},
type: "Opaque",
stringData: {
name: pulumi.getStack(),
server: config.require("clusterType") === "hub" ? "https://kubernetes.default.svc" : `https://${annotations.k8s_service_host}`
},
data: {
config: Buffer.from(serverConfig).toString("base64"),
},
}
})).then(fileContents => {
const provider = new github.Provider("github", {
token: env.GITHUB_TOKEN,
owner: config.require("githubOrg"),
})
new github.RepositoryFile("argo-cluster-secret.yaml", {
repository: config.require("githubRepo"),
file: config.require("secretPath"),
content: yaml.dump(fileContents),
branch: "main",
commitMessage: `Update Argo Config Secret for ${pulumi.getStack()}`,
overwriteOnCreate: true,
}, {provider: provider});
})
.catch(err => console.log(err))
}

private generateConfig(clusterAuthority: pulumi.Output<string>) {
if (this.config.require("clusterType") !== "hub") {
return pulumi.all([this.outputs.argoRoleArn, clusterAuthority]).apply(([argoRoleArn, clusterAuthority]) => `{
"awsAuthConfig": {
"clusterName": "${this.config.require("name")}-cluster",
"roleARN": "${argoRoleArn}"
},
"tlsClientConfig": {
"insecure": false,
"caData": "${clusterAuthority}"
}
}
`)
}
return `{
"tlsClientConfig": {
"insecure": false
}
}
`
}

private generateAnnotations(name: string) {
// Add More Outputs as needed to output to cluster secret
const outputs = pulumi.all([
this.outputs.clusterName,
this.outputs.clusterApiEndpoint,
])
const annotations = outputs.apply(([
clusterName,
clusterApiEndpoint,
]) => {
return {
"aws_cluster_name": clusterName,
"k8s_service_host": clusterApiEndpoint.split("://")[1],
}
})
return annotations
}

private generateLabels() {
return {
"argocd.argoproj.io/secret-type": "cluster",
...this.config.requireObject<Object>("clusterComponents"),
}
}
}
Loading
Loading