mirror of https://github.com/codevalet/codevalet
Merge pull request #62 from rtyler/migration-to-cb
Migrate off rtyler's and onto CloudBees' infrastructure
This commit is contained in:
commit
b2b165cd92
|
@ -39,3 +39,10 @@ given administrative access to the Jenkins master.
|
|||
Groovy scripting will set up some VM templates which will provide dynamically
|
||||
provisioned agents in a cloud provider such as Azure, with a fixed quota, i.e.
|
||||
2 active machines per.
|
||||
|
||||
|
||||
== Operating
|
||||
|
||||
Presently, after moving into a CloudBees-owned Azure subscription, instances
|
||||
come up with scoped (`Contributor`) permissions to provision resources only
|
||||
within the `azureagents-for-codevalet` resource group.
|
||||
|
|
32
Makefile
32
Makefile
|
@ -1,21 +1,21 @@
|
|||
IMAGE_PREFIX="rtyler/codevalet"
|
||||
TF_VARFILE=.terraform.cb.json
|
||||
TERRAFORM=./scripts/terraform
|
||||
|
||||
check: generate validate
|
||||
$(MAKE) -C webapp check
|
||||
$(MAKE) -C proxy check
|
||||
|
||||
all: plugins master proxy
|
||||
all: plugins master
|
||||
|
||||
generate: generate-tfs generate-k8s
|
||||
generate: generate-k8s agent-templates
|
||||
|
||||
run: webapp proxy
|
||||
run: webapp
|
||||
docker-compose up
|
||||
|
||||
clean:
|
||||
rm -f build/git-refs.txt k8/generated
|
||||
docker-compose down || true
|
||||
$(MAKE) -C webapp clean
|
||||
$(MAKE) -C proxy clean
|
||||
|
||||
|
||||
## Build the Jenkins master image
|
||||
|
@ -48,9 +48,6 @@ build/agent-templates:
|
|||
|
||||
## Handle sub-projects
|
||||
###############################################################
|
||||
proxy:
|
||||
$(MAKE) -C proxy
|
||||
|
||||
webapp:
|
||||
$(MAKE) -C webapp
|
||||
###############################################################
|
||||
|
@ -58,14 +55,17 @@ webapp:
|
|||
|
||||
## Terraform
|
||||
###############################################################
|
||||
validate: plans/*.tf
|
||||
./scripts/terraform validate plans
|
||||
validate: plans/*.tf tfinit
|
||||
$(TERRAFORM) validate --var-file=$(TF_VARFILE) plans
|
||||
|
||||
plan: validate
|
||||
./scripts/terraform plan --var-file=.terraform.json plans
|
||||
plan: validate tfinit
|
||||
$(TERRAFORM) plan --var-file=$(TF_VARFILE) plans
|
||||
|
||||
deploy: plan
|
||||
./scripts/terraform apply --var-file=.terraform.json plans
|
||||
deploy: plan tfinit
|
||||
$(TERRAFORM) apply --var-file=$(TF_VARFILE) plans
|
||||
|
||||
tfinit: $(TF_VARFILE) ./scripts/tf-init
|
||||
./scripts/tf-init $(TF_VARFILE)
|
||||
###############################################################
|
||||
|
||||
|
||||
|
@ -100,5 +100,5 @@ k8s/generated:
|
|||
|
||||
|
||||
.PHONY: clean all plugins master builder plan validate \
|
||||
deploy generate-k8s deploy-k8s webapp check generate-tfs generate \
|
||||
agent-templates proxy run
|
||||
deploy generate-k8s deploy-k8s webapp check generate \
|
||||
agent-templates run tfinit
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
---
|
||||
version: '3'
|
||||
services:
|
||||
proxy:
|
||||
image: 'rtyler/codevalet-proxy:latest'
|
||||
ports:
|
||||
- 8000:80
|
||||
- 8443:443
|
||||
environment:
|
||||
- WEBAPP_SERVICE_PORT=9292
|
||||
- WEBAPP_SERVICE_HOST=webapp
|
||||
# Example version of these variables for scripting/testing
|
||||
- JENKINS_CODEVALET_SERVICE_HOST=127.0.1.1
|
||||
- JENKINS_CODEVALET_SERVICE_PORT=80
|
||||
links:
|
||||
- webapp
|
||||
|
||||
webapp:
|
||||
image: 'rtyler/codevalet-webapp:latest'
|
||||
ports:
|
||||
|
|
|
@ -44,17 +44,8 @@ if (principle.isBlank()) {
|
|||
'Azure credentials for provisioning agent', /* description */
|
||||
subscriptionId, /* subscriptionId */
|
||||
clientId, /* clientId */
|
||||
clientSecret , /* clientSecret */
|
||||
/* oauth2 Token endpoint */
|
||||
"https://login.windows.net/${tenantId}",
|
||||
/* service management url */
|
||||
AzureCredentials.Constants.DEFAULT_MANAGEMENT_URL,
|
||||
/* authentication endpoint */
|
||||
AzureCredentials.Constants.DEFAULT_AUTHENTICATION_ENDPOINT,
|
||||
/* resource manager endpoint */
|
||||
AzureCredentials.Constants.DEFAULT_RESOURCE_MANAGER_ENDPOINT,
|
||||
/* graph endpoint */
|
||||
AzureCredentials.Constants.DEFAULT_GRAPH_ENDPOINT)
|
||||
clientSecret) /* clientSecret */
|
||||
credential.tenant = tenantId
|
||||
|
||||
SystemCredentialsProvider.instance.store.addCredentials(Domain.global(), credential)
|
||||
}
|
||||
|
@ -66,8 +57,6 @@ def cloud = Jenkins.instance.clouds.find { it.name == cloudName }
|
|||
/* Avoid adding the AzureVMCloud over and over and over again */
|
||||
if (cloud == null) {
|
||||
cloud = new AzureVMCloud(cloudName, /* Cloud Name */
|
||||
/* Azure Credentials Id */
|
||||
AzureCredentials.getServicePrincipal(credentialsId),
|
||||
credentialsId, /* credentials id */
|
||||
maxAgents, /* Max Agents */
|
||||
'1200', /* Deployment Timeout (s) */
|
||||
|
@ -96,12 +85,12 @@ def vhd = null
|
|||
vmTemplate = new AzureVMAgentTemplate('<%= name %>',
|
||||
'<%= d['description'] %>', /* description */
|
||||
'<%= d['labels'].join(' ') %>', /* labels */
|
||||
'East US 2', /* location */
|
||||
'West US', /* location */
|
||||
'<%= d['size'] %>', /* VM Size */
|
||||
'existing', /* Storage account Name reference type */
|
||||
'Standard_LRS', /* Storage account type */
|
||||
'', /* new storage account name */
|
||||
'codevaletvhds', /* existing storage account name */
|
||||
'codevaletimages', /* existing storage account name */
|
||||
'unmanaged', /* disk type */
|
||||
'<%= d['executors'] %>', /* number of executors */
|
||||
'NORMAL', /* Usage mode */
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: aci-connector
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: aci-connector
|
||||
spec:
|
||||
containers:
|
||||
- name: aci-connector
|
||||
image: microsoft/aci-connector-k8s:latest
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: AZURE_CLIENT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: jenkins-masters
|
||||
key: azure_client_secret
|
||||
- name: AZURE_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: jenkins-masters
|
||||
key: azure_client
|
||||
- name: AZURE_TENANT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: jenkins-masters
|
||||
key: azure_tenant
|
||||
- name: AZURE_SUBSCRIPTION_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: jenkins-masters
|
||||
key: azure_subscription
|
||||
- name: ACI_RESOURCE_GROUP
|
||||
value: 'azureagents-for-codevalet'
|
||||
- name: ACI_REGION
|
||||
value: 'westus'
|
|
@ -1,35 +1,42 @@
|
|||
---
|
||||
apiVersion: "v1"
|
||||
kind: "List"
|
||||
apiVersion: 'v1'
|
||||
kind: 'List'
|
||||
items:
|
||||
- apiVersion: "v1"
|
||||
kind: "Service"
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: 'canary'
|
||||
spec:
|
||||
type: 'LoadBalancer'
|
||||
selector:
|
||||
name: 'canary'
|
||||
ports:
|
||||
-
|
||||
name: "http"
|
||||
port: 80
|
||||
targetPort: 9292
|
||||
protocol: "TCP"
|
||||
|
||||
- apiVersion: "v1"
|
||||
kind: "ReplicationController"
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: 'canary'
|
||||
namespace: 'canary'
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 9292
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: 'canary'
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: 'canary'
|
||||
namespace: 'canary'
|
||||
labels:
|
||||
name: 'canary'
|
||||
spec:
|
||||
replicas: 3
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
template:
|
||||
metadata:
|
||||
name: 'canary'
|
||||
labels:
|
||||
name: 'canary'
|
||||
app: 'canary'
|
||||
annotations:
|
||||
spec:
|
||||
containers:
|
||||
- name: 'canary'
|
||||
|
@ -37,6 +44,12 @@ items:
|
|||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 9292
|
||||
name: http
|
||||
resources:
|
||||
requests:
|
||||
memory: 64M
|
||||
limits:
|
||||
memory: 256M
|
||||
env:
|
||||
- name: RACK_ENV
|
||||
value: 'production'
|
||||
|
@ -59,4 +72,26 @@ items:
|
|||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 10
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: 'http-ingress'
|
||||
namespace: 'canary'
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- codevalet.io
|
||||
secretName: ingress-tls
|
||||
rules:
|
||||
- host: codevalet.io
|
||||
http:
|
||||
paths:
|
||||
- path: /canary/
|
||||
backend:
|
||||
serviceName: canary
|
||||
servicePort: 80
|
||||
# vim: ft=yaml
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: List
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: 'nginx-ingress'
|
||||
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: 'nginx'
|
||||
namespace: 'nginx-ingress'
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 80
|
||||
name: http
|
||||
- port: 443
|
||||
name: https
|
||||
sessionAffinity: 'ClientIP'
|
||||
selector:
|
||||
app: 'nginx'
|
||||
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
namespace: 'nginx-ingress'
|
||||
name: 'nginx'
|
||||
data:
|
||||
proxy-connect-timeout: "15"
|
||||
proxy-read-timeout: "600"
|
||||
proxy-send-timeout: "600"
|
||||
hsts-include-subdomains: "false"
|
||||
body-size: "64m"
|
||||
server-name-hash-bucket-size: "256"
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: 'nginx'
|
||||
namespace: 'nginx-ingress'
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: 'nginx'
|
||||
spec:
|
||||
containers:
|
||||
- image: 'gcr.io/google_containers/nginx-ingress-controller:0.8.3'
|
||||
name: 'nginx'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10254
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 5
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- containerPort: 443
|
||||
args:
|
||||
- /nginx-ingress-controller
|
||||
- --default-backend-service=webapp/webapp
|
||||
- --nginx-configmap=nginx-ingress/nginx
|
|
@ -1,29 +1,20 @@
|
|||
---
|
||||
# Based on
|
||||
# https://radu-matei.github.io/blog/kubernetes-jenkins-azure/#configuring-jenkins-to-dinamically-spawn-agents-docker-containers-for-builds
|
||||
# https://github.com/kubernetes/charts/blob/master/stable/jenkins/templates/jenkins-master-deployment.yaml
|
||||
#
|
||||
# Thanks Radu!
|
||||
apiVersion: "v1"
|
||||
apiVersion: v1
|
||||
kind: "List"
|
||||
items:
|
||||
# jenkins
|
||||
- apiVersion: "v1"
|
||||
kind: "PersistentVolume"
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "jenkins-@@USER@@"
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
capacity:
|
||||
storage: 5Gi
|
||||
gcePersistentDisk:
|
||||
pdName: 'jenkins-@@USER@@'
|
||||
fsType: ext4
|
||||
|
||||
- apiVersion: "v1"
|
||||
kind: "PersistentVolumeClaim"
|
||||
- apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: "jenkins-@@USER@@"
|
||||
namespace: "jenkins-@@USER@@"
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
|
@ -31,31 +22,85 @@ items:
|
|||
requests:
|
||||
storage: 5Gi
|
||||
|
||||
- apiVersion: "v1"
|
||||
kind: "ReplicationController"
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: 'jenkins-@@USER@@'
|
||||
namespace: 'jenkins-@@USER@@'
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
- port: 50000
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: 'jenkins-@@USER@@'
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: 'http-ingress'
|
||||
namespace: 'jenkins-@@USER@@'
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- codevalet.io
|
||||
secretName: ingress-tls
|
||||
rules:
|
||||
- host: codevalet.io
|
||||
http:
|
||||
paths:
|
||||
- path: '/u/@@USER@@'
|
||||
backend:
|
||||
serviceName: 'jenkins-@@USER@@'
|
||||
servicePort: 80
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: "jenkins-@@USER@@"
|
||||
namespace: "jenkins-@@USER@@"
|
||||
labels:
|
||||
name: "jenkins-@@USER@@"
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
template:
|
||||
metadata:
|
||||
name: "jenkins-@@USER@@"
|
||||
labels:
|
||||
name: "jenkins-@@USER@@"
|
||||
app: "jenkins-@@USER@@"
|
||||
annotations:
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
runAsUser: 1000
|
||||
volumes:
|
||||
- name: "jenkins-@@USER@@"
|
||||
persistentVolumeClaim:
|
||||
claimName: "jenkins-@@USER@@"
|
||||
containers:
|
||||
- name: "jenkins-@@USER@@"
|
||||
image: 'rtyler/codevalet-master:latest'
|
||||
image: "rtyler/codevalet-master:latest"
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
- containerPort: 50000
|
||||
name: jnlp
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
requests:
|
||||
memory: 384M
|
||||
limits:
|
||||
memory: 1G
|
||||
volumeMounts:
|
||||
- name: "jenkins-@@USER@@"
|
||||
mountPath: "/var/jenkins_home"
|
||||
env:
|
||||
- name: CPU_REQUEST
|
||||
valueFrom:
|
||||
|
@ -120,35 +165,4 @@ items:
|
|||
secretKeyRef:
|
||||
name: jenkins-masters
|
||||
key: azure_subscription
|
||||
volumeMounts:
|
||||
- name: "jenkins-@@USER@@"
|
||||
mountPath: "/var/jenkins_home"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: '/u/@@USER@@/login'
|
||||
port: 8080
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
volumes:
|
||||
- name: "jenkins-@@USER@@"
|
||||
persistentVolumeClaim:
|
||||
claimName: "jenkins-@@USER@@"
|
||||
|
||||
- apiVersion: "v1"
|
||||
kind: "Service"
|
||||
metadata:
|
||||
name: "jenkins-@@USER@@"
|
||||
spec:
|
||||
type: 'LoadBalancer'
|
||||
selector:
|
||||
name: "jenkins-@@USER@@"
|
||||
ports:
|
||||
-
|
||||
name: "http"
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
protocol: "TCP"
|
||||
|
||||
# vim: ft=yaml
|
||||
|
|
|
@ -2,19 +2,41 @@
|
|||
apiVersion: "v1"
|
||||
kind: "List"
|
||||
items:
|
||||
- apiVersion: "v1"
|
||||
kind: "ReplicationController"
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: 'webapp'
|
||||
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: 'webapp'
|
||||
namespace: 'webapp'
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 9292
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: 'webapp'
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: 'webapp'
|
||||
namespace: 'webapp'
|
||||
labels:
|
||||
name: 'webapp'
|
||||
spec:
|
||||
replicas: 3
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
template:
|
||||
metadata:
|
||||
name: 'webapp'
|
||||
labels:
|
||||
name: 'webapp'
|
||||
app: 'webapp'
|
||||
annotations:
|
||||
spec:
|
||||
containers:
|
||||
- name: 'webapp'
|
||||
|
@ -22,6 +44,12 @@ items:
|
|||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 9292
|
||||
name: http
|
||||
resources:
|
||||
requests:
|
||||
memory: 64M
|
||||
limits:
|
||||
memory: 256M
|
||||
env:
|
||||
- name: RACK_ENV
|
||||
value: 'production'
|
||||
|
@ -45,7 +73,30 @@ items:
|
|||
httpGet:
|
||||
path: /
|
||||
port: 9292
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 3
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 10
|
||||
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: 'http-ingress'
|
||||
namespace: 'webapp'
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
nginx.ingress.kubernetes.io/affinity: 'cookie'
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- codevalet.io
|
||||
secretName: ingress-tls
|
||||
rules:
|
||||
- host: codevalet.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: webapp
|
||||
servicePort: 80
|
||||
|
||||
# vim: ft=yaml
|
||||
|
|
|
@ -5,41 +5,22 @@
|
|||
# considered "trusted" resources and not those running user-generated code.
|
||||
|
||||
resource "azurerm_resource_group" "controlplane" {
|
||||
name = "${var.prefix}-controlplane"
|
||||
location = "${var.region}"
|
||||
name = "codevalet"
|
||||
location = "${var.region}"
|
||||
}
|
||||
|
||||
resource "azurerm_container_service" "controlplane" {
|
||||
name = "${var.prefix}-controlplane"
|
||||
location = "${azurerm_resource_group.controlplane.location}"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
orchestration_platform = "Kubernetes"
|
||||
|
||||
master_profile {
|
||||
count = 1
|
||||
dns_prefix = "${var.k8s_master_name}"
|
||||
}
|
||||
|
||||
linux_profile {
|
||||
admin_username = "tyler"
|
||||
ssh_key {
|
||||
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAueiy12T5bvFhsc9YjfLc3aVIxgySd3gDxQWy/bletIoZL8omKmzocBYJ7F58U1asoyfWsy2ToTOY8jJp1eToXmbD6L5+xvHba0A7djYh9aQRrFam7doKQ0zp0ZSUF6+R1v0OM4nnWqK4n2ECIYd+Bdzrp+xA5+XlW3ZSNzlnW2BeWznzmgRMcp6wI+zQ9GMHWviR1cxpml5Z6wrxTZ0aX91btvnNPqoOGva976B6e6403FOEkkIFTk6CC1TFKwc/VjbqxYBg4kU0JhiTP+iEZibcQrYjWdYUgAotYbFVe5/DneHMLNsMPdeihba4PUwt62rXyNegenuCRmCntLcaFQ== tyler@kiwi"
|
||||
}
|
||||
}
|
||||
|
||||
agent_pool_profile {
|
||||
name = "k8s-agents"
|
||||
count = "${var.k8s_agents}"
|
||||
dns_prefix = "${var.prefix}-k8s-agent"
|
||||
vm_size = "Standard_DS2_v2"
|
||||
}
|
||||
|
||||
service_principal {
|
||||
client_id = "${var.client_id}"
|
||||
client_secret = "${var.client_secret}"
|
||||
}
|
||||
|
||||
diagnostics_profile {
|
||||
enabled = false
|
||||
}
|
||||
resource "azurerm_container_registry" "registry" {
|
||||
name = "codevalet"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
location = "${azurerm_resource_group.controlplane.location}"
|
||||
admin_enabled = true
|
||||
sku = "Standard"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_account" "storage" {
|
||||
name = "codevaletstorage"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
location = "${azurerm_resource_group.controlplane.location}"
|
||||
account_tier = "Standard"
|
||||
account_replication_type = "GRS"
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
# resources between production and staging, but we'll give it a try.
|
||||
|
||||
resource "azurerm_dns_zone" "root" {
|
||||
name = "${var.dnsprefix}codevalet.io"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
name = "${var.dnsprefix}codevalet.io"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ resource "azurerm_resource_group" "images" {
|
|||
}
|
||||
|
||||
resource "azurerm_storage_account" "images" {
|
||||
name = "codevaletvhds"
|
||||
resource_group_name = "${azurerm_resource_group.images.name}"
|
||||
|
||||
location = "${var.region}"
|
||||
account_type = "Standard_LRS"
|
||||
name = "codevaletimages"
|
||||
resource_group_name = "${azurerm_resource_group.images.name}"
|
||||
location = "${var.region}"
|
||||
account_tier = "Standard"
|
||||
account_replication_type = "LRS"
|
||||
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#
|
||||
# Terraform plan for the in-bound nginx proxy
|
||||
#
|
||||
|
||||
resource "azurerm_dns_a_record" "nginx" {
|
||||
name = "@"
|
||||
zone_name = "${azurerm_dns_zone.root.name}"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
ttl = "300"
|
||||
records = ["${azurerm_public_ip.nginx.ip_address}"]
|
||||
}
|
||||
|
||||
resource "azurerm_public_ip" "nginx" {
|
||||
name = "nginx"
|
||||
location = "${var.region}"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
public_ip_address_allocation = "static"
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "nginx" {
|
||||
depends_on = [
|
||||
"azurerm_container_service.controlplane",
|
||||
]
|
||||
|
||||
metadata {
|
||||
name = "nginx"
|
||||
}
|
||||
spec {
|
||||
load_balancer_ip = "${azurerm_public_ip.nginx.ip_address}"
|
||||
|
||||
type = "LoadBalancer"
|
||||
selector {
|
||||
name = "nginx"
|
||||
}
|
||||
session_affinity = "ClientIP"
|
||||
port {
|
||||
name = "http"
|
||||
target_port = 80
|
||||
port = 80
|
||||
}
|
||||
port {
|
||||
name = "http-tls"
|
||||
target_port = 443
|
||||
port = 443
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +1,8 @@
|
|||
# Configure the terraform Azure provider
|
||||
|
||||
variable "subscription_id" {}
|
||||
variable "client_id" {}
|
||||
variable "client_secret" {}
|
||||
variable "tenant_id" {}
|
||||
|
||||
variable "prefix" {
|
||||
type = "string"
|
||||
default = "codevaletdev"
|
||||
}
|
||||
|
||||
variable "dnsprefix" {
|
||||
type = "string"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "env" {
|
||||
type = "string"
|
||||
default = "dev"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = "string"
|
||||
default = "East US 2"
|
||||
}
|
||||
|
||||
variable "k8s_master_name" {
|
||||
type = "string"
|
||||
# Cannot contain interpolations? wompwomp
|
||||
default = "codevaletdev-k8s-master"
|
||||
}
|
||||
|
||||
variable "k8s_agents" {
|
||||
type = "string"
|
||||
default = "1"
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
subscription_id = "${var.subscription_id}"
|
||||
client_id = "${var.client_id}"
|
||||
client_secret = "${var.client_secret}"
|
||||
tenant_id = "${var.tenant_id}"
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_context_auth_info = "${var.k8s_master_name}-admin"
|
||||
config_context_cluster = "${var.k8s_master_name}"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Variables for plugging in various environment specific settings
|
||||
#
|
||||
|
||||
variable "env" {
|
||||
type = "string"
|
||||
default = "dev"
|
||||
}
|
||||
|
||||
variable "dnsprefix" {
|
||||
type = "string"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = "string"
|
||||
default = "West US"
|
||||
}
|
||||
|
||||
#
|
||||
# Variables which should be kept secret
|
||||
# and provided by a --var-file
|
||||
#######################################
|
||||
variable "subscription_id" {}
|
||||
variable "client_id" {}
|
||||
variable "client_secret" {}
|
||||
variable "tenant_id" {}
|
||||
#######################################
|
|
@ -1,34 +0,0 @@
|
|||
#
|
||||
# Terraform plan for managing some of the resources for the webapp
|
||||
#
|
||||
|
||||
resource "azurerm_public_ip" "webapp" {
|
||||
name = "webapp"
|
||||
location = "${var.region}"
|
||||
resource_group_name = "${azurerm_resource_group.controlplane.name}"
|
||||
public_ip_address_allocation = "static"
|
||||
}
|
||||
|
||||
|
||||
resource "kubernetes_service" "webapp" {
|
||||
depends_on = [
|
||||
"azurerm_container_service.controlplane",
|
||||
]
|
||||
|
||||
metadata {
|
||||
name = "webapp"
|
||||
}
|
||||
spec {
|
||||
load_balancer_ip = "${azurerm_public_ip.webapp.ip_address}"
|
||||
|
||||
type = "LoadBalancer"
|
||||
selector {
|
||||
name = "webapp"
|
||||
}
|
||||
session_affinity = "ClientIP"
|
||||
port {
|
||||
target_port = 9292
|
||||
port = 80
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ workflow-aggregator-plugin
|
|||
blueocean-plugin
|
||||
github-oauth-plugin
|
||||
azure-vm-agents-plugin
|
||||
kubernetes-plugin
|
||||
matrix-auth-plugin
|
||||
embeddable-build-status-plugin
|
||||
sentry-plugin
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
FROM ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -qy software-properties-common
|
||||
RUN add-apt-repository ppa:certbot/certbot && \
|
||||
apt-get update && \
|
||||
apt-get install -qy python-certbot-nginx nginx ruby dnsmasq supervisor
|
||||
|
||||
ADD nginx.conf /etc/nginx/
|
||||
RUN touch /etc/nginx/vars.conf /etc/nginx/monkeys.conf
|
||||
ADD conf.d/*.conf /etc/nginx/conf.d/
|
||||
|
||||
COPY run-nginx /usr/bin/
|
||||
COPY generate-nginx-locations /usr/bin/
|
||||
COPY manage-certificates /usr/bin/
|
||||
COPY supervisor.conf /etc/supervisor/conf.d/supervisor.conf
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
STOPSIGNAL SIGTERM
|
||||
|
||||
CMD /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisor.conf
|
|
@ -1,14 +0,0 @@
|
|||
IMAGE=rtyler/codevalet-proxy
|
||||
|
||||
check: container
|
||||
docker run --rm \
|
||||
-e JENKINS_CODEVALET_SERVICE_HOST=127.0.1.1 \
|
||||
-e JENKINS_CODEVALET_SERVICE_PORT=80 \
|
||||
-e JENKINS_FOOBAR_SERVICE_HOST=127.0.2.1 \
|
||||
-e JENKINS_FOOBAR_SERVICE_PORT=80 \
|
||||
$(IMAGE):latest /usr/bin/run-nginx test
|
||||
|
||||
container: Dockerfile
|
||||
docker build -t $(IMAGE) .
|
||||
|
||||
.PHONY: clean check container
|
|
@ -1,54 +0,0 @@
|
|||
# Basic configuration for the reverse proxy in front of "everything"
|
||||
#
|
||||
# This should manage the default proxying
|
||||
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name codevalet.io;
|
||||
|
||||
location ^~ /.well-known/acme-challenge {
|
||||
root /var/www/letsencrypt;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name codevalet.io;
|
||||
|
||||
include /etc/nginx/vars.conf;
|
||||
|
||||
# Grab all the dynamically generated routes, blech.
|
||||
# Need to do this before the catch-all location below
|
||||
include /etc/nginx/monkeys.conf;
|
||||
|
||||
location /canary {
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
rewrite ^/canary/(.*) /$1 break;
|
||||
|
||||
proxy_pass http://$canary:$canary_port;
|
||||
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://$webapp:$webapp_port;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# vim: sw=2 ts=2 et
|
|
@ -1,39 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'erb'
|
||||
|
||||
locations = {}
|
||||
|
||||
ENV.each_pair do |key, val|
|
||||
next unless key.match /JENKINS_(\w+)_SERVICE_(\w+)/
|
||||
user = $1.downcase.to_sym
|
||||
env_type = $2
|
||||
|
||||
locations[user] ||= {}
|
||||
|
||||
if env_type == 'HOST'
|
||||
locations[user][:host] = val
|
||||
elsif env_type == 'PORT'
|
||||
locations[user][:port] = val
|
||||
end
|
||||
end
|
||||
|
||||
File.open('/etc/nginx/monkeys.conf', 'w+') do |f|
|
||||
f.write(ERB.new(DATA.read).result)
|
||||
end
|
||||
|
||||
__END__
|
||||
|
||||
## THIS FILE IS AUTOGENERATED BY generate-nginx-locations
|
||||
# DO NOT EDIT
|
||||
#
|
||||
<% locations.each_pair do |name, data| %>
|
||||
|
||||
location = /u/<%= name %>/ {
|
||||
return 301 $scheme://$server_name/u/<%= name %>/blue/pipelines;
|
||||
}
|
||||
location /u/<%= name %> {
|
||||
proxy_set_header Host $host;
|
||||
proxy_pass http://<%= data[:host] %>:<%= data[:port] %>;
|
||||
}
|
||||
<% end %>
|
|
@ -1,36 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
DOMAIN=codevalet.io
|
||||
EMAIL=tyler--codevalet@monkeypox.org
|
||||
|
||||
sleep 10
|
||||
|
||||
printenv
|
||||
|
||||
while true; do
|
||||
|
||||
ls -lah /etc/letsencrypt
|
||||
cat /etc/letsencrypt/options-ssl-nginx.conf
|
||||
|
||||
echo ">> Beep boop.."
|
||||
|
||||
if [ ! "${LETSENCRYPT+x}" = "x" ]; then
|
||||
if [ -d /etc/letsencrypt/live ]; then
|
||||
echo ">> Let's Encrypt files appear to be on the filesystem";
|
||||
echo ">> .. attempting a renew";
|
||||
if [ $? -ne 0 ]; then
|
||||
certbot renew -n -d ${DOMAIN} -m ${EMAIL};
|
||||
fi;
|
||||
fi;
|
||||
else
|
||||
echo ">> Let's Encrypt files do not appear to exist, registering"
|
||||
certbot register -m ${EMAIL} --agree-tos;
|
||||
certbot certonly --webroot -w /usr/share/nginx/html -d ${DOMAIN} -m ${EMAIL} ;
|
||||
fi;
|
||||
|
||||
echo ">> Snoozing for a while.."
|
||||
|
||||
tail -n 500 /var/log/letsencrypt/*log
|
||||
# Let's nap for a whole day!
|
||||
sleep 3000
|
||||
done;
|
|
@ -1,30 +0,0 @@
|
|||
#user nginx;
|
||||
worker_processes 1;
|
||||
|
||||
error_log /dev/stdout warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
include /etc/nginx/modules/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 4096;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
gzip on;
|
||||
resolver 127.0.0.1;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
|
||||
# vim: ft=conf sw=2 ts=2 et
|
|
@ -1,35 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# This is a wrapper script to lay down some environment specific configuartion
|
||||
# before the daemon starts. This can be useful for pulling environment
|
||||
# variables into the application without requiring anything too terribly goofy
|
||||
# in the nginx runtime
|
||||
|
||||
cat > /etc/nginx/vars.conf << EOF
|
||||
# THIS FILE IS AUTOGENERATED BY run-nginx
|
||||
# DO NOT EDIT
|
||||
|
||||
set \$webapp ${WEBAPP_SERVICE_HOST:-dummy-host};
|
||||
set \$webapp_port ${WEBAPP_SERVICE_PORT:-80};
|
||||
|
||||
set \$canary ${CANARY_SERVICE_HOST:-dummy-host};
|
||||
set \$canary_port ${CANARY_SERVICE_PORT:-80};
|
||||
EOF
|
||||
|
||||
|
||||
if [ -f /etc/letsencrypt/live/codevalet.io/cert.pem ]; then
|
||||
cat >> /etc/nginx/vars.conf << EOF
|
||||
ssl_certificate_key /etc/letsencrypt/live/codevalet.io/privkey.pem;
|
||||
ssl_certificate /etc/letsencrypt/live/codevalet.io/fullchain.pem;
|
||||
EOF
|
||||
fi;
|
||||
|
||||
/usr/bin/generate-nginx-locations
|
||||
|
||||
cat /etc/nginx/monkeys.conf
|
||||
|
||||
if [ "$1" = "test" ]; then
|
||||
exec /usr/sbin/nginx -t;
|
||||
else
|
||||
exec /usr/sbin/nginx -g "daemon off;";
|
||||
fi;
|
|
@ -1,26 +0,0 @@
|
|||
[supervisord]
|
||||
nodaemon=true
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/bin/run-nginx
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
|
||||
[program:dnsmasq]
|
||||
command=/usr/sbin/dnsmasq --user=root --no-daemon
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
|
||||
[program:certs]
|
||||
command=/usr/bin/manage-certificates
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
|
@ -3,7 +3,7 @@
|
|||
# This script is meant to be added to the PATH so the latest terraform
|
||||
# container is always in use
|
||||
|
||||
CONTAINER_NAME=hashicorp/terraform:0.9.9
|
||||
CONTAINER_NAME=hashicorp/terraform:latest
|
||||
|
||||
# Pull down the container if we don't already have it
|
||||
docker inspect -f . ${CONTAINER_NAME} 2>&1 > /dev/null
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
TERRAFORM=$(dirname $0)/terraform
|
||||
TF_VARFILE=$1
|
||||
|
||||
# Pull everything from our var-file into shell variables
|
||||
# How's that for some python code golf?
|
||||
eval $(python -c "import json; print '\n'.join(['{}={}'.format(k.upper(),v) for k,v in json.load(file('${TF_VARFILE}')).iteritems()]);")
|
||||
|
||||
${TERRAFORM} init \
|
||||
-backend=true \
|
||||
-backend-config="storage_account_name=${ENV}codevalettf" \
|
||||
-backend-config="container_name=tfstate" \
|
||||
-backend-config="key=codevalet.tfstate" \
|
||||
-backend-config="resource-group-name=${ENV}codevalet" \
|
||||
-backend-config="arm_subscription_id=${SUBCRIPTION_ID}" \
|
||||
-backend-config="arm_client_id=${CLIENT_ID}" \
|
||||
-backend-config="arm_client_secret=${CLIENT_SECRET}" \
|
||||
-backend-config="arm_tenant_id=${TENANT_ID}" \
|
||||
plans
|
|
@ -52,8 +52,8 @@
|
|||
.col-md-6
|
||||
%p
|
||||
© 2017
|
||||
%a{:href => 'https://github.com/rtyler'}
|
||||
R. Tyler Croy.
|
||||
%a{:href => 'https://github.com/cloudbees'}
|
||||
CloudBees Labs.
|
||||
.col-md-6
|
||||
%p.text-right
|
||||
%a{:href => 'https://twitter.com/codevalet'}
|
||||
|
|
Loading…
Reference in New Issue