├── .DS_Store
├── .gitignore
├── README.md
├── code-analysis
├── .DS_Store
├── README.md
├── delivery
│ ├── delivery.yml
│ └── source
│ │ └── gitops-source-template.yml
├── supply-chain
│ ├── build
│ │ └── kpack
│ │ │ ├── cluster-builder.yml
│ │ │ ├── cluster-stack.yml
│ │ │ ├── cluster-store.yml
│ │ │ └── image-template.yml
│ ├── code-analysis
│ │ └── sonar
│ │ │ ├── run-template.yml
│ │ │ ├── source-template.yml
│ │ │ └── task.yml
│ ├── config
│ │ └── config-template.yml
│ ├── deliverable
│ │ └── template.yml
│ ├── source
│ │ └── git-source-template.yml
│ ├── supply-chain.yml
│ └── writer
│ │ └── git
│ │ ├── run-template.yml
│ │ ├── secret.yml
│ │ └── source-template.yml
└── workload.yml
├── github-pr
├── README.md
└── supply-chain
│ ├── config-writer
│ ├── run-template.yml
│ └── source-template.yml
│ ├── pull-request
│ ├── run-template.yml
│ ├── task.yml
│ └── template.yml
│ └── source-test-scan-to-url.yml
├── image-prebuilt
├── .DS_Store
├── README.md
├── delivery
│ ├── delivery.yml
│ └── source
│ │ └── image
│ │ └── source-template.yml
├── supply-chain
│ ├── config
│ │ └── config-template.yml
│ ├── deliverable
│ │ └── template.yml
│ ├── scan
│ │ └── image
│ │ │ ├── image-template.yml
│ │ │ ├── scan-policy.yml
│ │ │ └── scan-template.yml
│ ├── source
│ │ └── image-repo-template.yml
│ ├── supply-chain.yml
│ └── writer
│ │ ├── run-template.yml
│ │ ├── task.yml
│ │ └── template.yml
└── workload-imageprebuilt.yml
├── multi-cluster
├── README.md
├── deliverable-to-run-cluster-reconciler.yml
├── rbac
│ ├── deliverable-cluster-role-binding.yml
│ └── deliverable-cluster-role.yml
└── supply-chain
│ ├── deliverable-config-writer
│ └── cluster-template.yml
│ ├── deliverable-config
│ └── config-template.yml
│ └── source-to-url.yml
├── multi-language-support-with-sonar
├── README.md
├── clusterdelivery
│ ├── deliverable-config-writer
│ │ ├── commit-and-pr-task.yaml
│ │ ├── commit-and-pr-taskrun-runtemplate.yaml
│ │ └── config-writer-and-pull-requester-template.yaml
│ ├── deliverable-config
│ │ └── config-template.yml
│ └── delivery.yml
└── supplychain
│ ├── deliverable-config-writer
│ └── cluster-template.yml
│ ├── deliverable-config
│ └── config-template.yml
│ ├── source-analyzer
│ ├── run-template.yml
│ ├── source-template.yml
│ ├── task-dotnet.yml
│ └── task.yml
│ ├── source-test-analyze-scan-to-url.yml
│ └── source-tester
│ ├── run-template.yml
│ └── source-template.yml
└── shared
├── .DS_Store
├── delivery
└── deploy
│ └── deployment.yml
├── git-secret.yml
├── registry-secret.yml
├── secret.yml
├── service-account.yml
└── supply-chain
└── deploy
└── k8s
└── app-deploy.yml
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x95castle1/custom-cartographer-supply-chain-examples/6f0778ce94efc310684215e82308c34d8cb2e127/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | values.yml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # custom-cartographer-supply-chain-examples
2 |
3 | ## Prerequisites
4 |
5 | 1. Kubernetes v1.19+
6 |
7 | ```bash
8 | kind create cluster --image kindest/node:v1.21.1
9 | ```
10 |
11 | 2. [Carvel] tools for templating and groups of Kubernetes objects to the api
12 | server
13 |
14 | - [ytt]: templating the credentials
15 | - [kapp]: submitting objects to Kubernetes
16 |
17 | 3. Cartographer, and dependencies used in the example
18 |
19 | To install `cartographer`, refer to [README.md](../../README.md).
20 |
21 | All that `cartographer` does is choreograph the passing of results from a
22 | Kubernetes object to another, following the graph described in the
23 | [ClusterSupplyChain] object.
24 |
25 | This means that `cartographer` by itself is not very useful - its powers arise
26 | from integrating other Kubernetes resources that when tied together with a
27 | supplychain, forms something powerful.
28 |
29 | Install the following utilities as well as Cartographer!
30 |
31 | - [kpack](https://github.com/pivotal/kpack/blob/main/docs/install.md),
32 | for providing an opinionated way of continuously building container
33 | images using buildpacks
34 |
35 |
36 | - [kapp-controller](https://carvel.dev/kapp-controller/docs/latest/install/),
37 | for providing us with the ability of deploying multiple
38 | Kubernetes objects as a single unit
39 |
40 | 4. A container image registry in which you have authorization to push images. The
41 | credentials will be passed to kpack in the configuration steps below.
42 |
43 | 5. [Tree](https://github.com/ahmetb/kubectl-tree), a tool that we will use to observe the objects created.
44 |
45 | 6. Install [tekton]
46 |
47 | ```bash
48 | export TEKTON_VERSION=0.30.0
49 | kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/previous/v$TEKTON_VERSION/release.yaml
50 | ```
51 |
52 | 7. Additional setup instructions to run the examples here are in the readme doc per usecase subfolder.
53 |
54 |
--------------------------------------------------------------------------------
/code-analysis/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x95castle1/custom-cartographer-supply-chain-examples/6f0778ce94efc310684215e82308c34d8cb2e127/code-analysis/.DS_Store
--------------------------------------------------------------------------------
/code-analysis/README.md:
--------------------------------------------------------------------------------
1 | ## Run the code-analysis use case
2 |
3 | > For non-java workloads looking to use sonar for code quality analysis, consider using the [tekton sonarqube scanner task](https://hub.tekton.dev/tekton/task/sonarqube-scanner). This [repo](https://gitlab.com/drawsmcgraw/cartographer-sonar) is an example custom supply chain to take advantage of this reusable task.
4 |
5 | ## Prerequisites
6 |
7 | 1. Install flux [source-controller](https://fluxcd.io/docs/gitops-toolkit/source-watcher/#install-flux) for providing the ability to find new commits to a git
8 | repository and making it internally available to other resources.
9 |
10 | 2. Install the [git-cli task](https://github.com/tektoncd/catalog/tree/main/task/git-cli/0.2) from the
11 | [tekton catalog](https://github.com/tektoncd/catalog). This is used to write to the git repo.
12 |
13 | ```bash
14 | kapp deploy --yes -a tekton-git-cli -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-cli/0.2/git-cli.yaml
15 | ```
16 |
17 | 3. Install [sonarqube](https://docs.sonarqube.org/latest/setup/sonarqube-on-kubernetes/) (skip if you already have a sonarqube instance running in a cluster)
18 |
19 | ## Run
20 |
21 | > assumes current working directory is `repo-root/code-analysis`
22 |
23 | Submit a workload to run through a supply chain with the following steps:
24 |
25 | **get source** → **run test and sonar code quality analysis** → **build image** → **deploy** → **write config** → **stamp out a deliverable** and
26 |
27 | Deploy the deliverable produced from the supply chain through cluster delivery with the following steps:
28 |
29 | **get source from the 'write config' (last step) in the supply chain** → **deploy**
30 | ```
31 | kapp deploy --yes -a code-analysis-demo -c \
32 | -f <(ytt --ignore-unknown-comments -f . -f ../values.yml) \
33 | -f <(ytt --ignore-unknown-comments -f ../shared -f ../values.yml)
34 | ```
35 |
--------------------------------------------------------------------------------
/code-analysis/delivery/delivery.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterDelivery
3 | metadata:
4 | name: deliver
5 | spec:
6 | selector:
7 | workload-type: deliver
8 | workload-intent: code-analysis
9 | resources:
10 | - name: source-provider
11 | templateRef:
12 | kind: ClusterSourceTemplate
13 | name: gitops-source
14 |
15 | - name: deployer
16 | templateRef:
17 | kind: ClusterDeploymentTemplate
18 | name: app-deploy
19 | # in a supply chain, the output of a source template is only available as a `source`
20 | # in a delivery, a source template's output can be consumed as a `deployment`
21 | # every ClusterDeploymentTemplate must be passed exactly one deployment. the deployment
22 | # is not named (as other inputs can be)
23 | deployment:
24 | resource: source-provider
--------------------------------------------------------------------------------
/code-analysis/delivery/source/gitops-source-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSourceTemplate
3 | metadata:
4 | name: gitops-source
5 | spec:
6 | urlPath: .status.artifact.url
7 | revisionPath: .status.artifact.revision
8 |
9 | template:
10 | apiVersion: source.toolkit.fluxcd.io/v1beta1
11 | kind: GitRepository
12 | metadata:
13 | name: $(deliverable.metadata.name)$-app
14 | spec:
15 | interval: 1m0s
16 | url: $(deliverable.spec.source.git.url)$
17 | ref: $(deliverable.spec.source.git.ref)$
18 | secretRef:
19 | name: gitops-ssh-secret
--------------------------------------------------------------------------------
/code-analysis/supply-chain/build/kpack/cluster-builder.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: kpack.io/v1alpha2
4 | kind: ClusterBuilder
5 | metadata:
6 | name: java-builder
7 | spec:
8 | serviceAccountRef:
9 | name: #@ data.values.service_account_name
10 | namespace: default
11 | tag: #@ data.values.image_prefix + "java-builder"
12 | stack:
13 | name: stack
14 | kind: ClusterStack
15 | store:
16 | name: java-store
17 | kind: ClusterStore
18 | order:
19 | - group:
20 | - id: paketo-buildpacks/java
--------------------------------------------------------------------------------
/code-analysis/supply-chain/build/kpack/cluster-stack.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kpack.io/v1alpha2
3 | kind: ClusterStack
4 | metadata:
5 | name: stack
6 | spec:
7 | id: "io.buildpacks.stacks.bionic"
8 | buildImage:
9 | image: "paketobuildpacks/build:base-cnb"
10 | runImage:
11 | image: "paketobuildpacks/run:base-cnb"
--------------------------------------------------------------------------------
/code-analysis/supply-chain/build/kpack/cluster-store.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kpack.io/v1alpha2
3 | kind: ClusterStore
4 | metadata:
5 | name: java-store
6 | spec:
7 | sources:
8 | - image: gcr.io/paketo-buildpacks/java
--------------------------------------------------------------------------------
/code-analysis/supply-chain/build/kpack/image-template.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: carto.run/v1alpha1
3 | kind: ClusterImageTemplate
4 | metadata:
5 | name: image
6 | spec:
7 | params:
8 | - name: image_prefix
9 | default: some-default-prefix-
10 |
11 | imagePath: .status.latestImage
12 |
13 | template:
14 | apiVersion: kpack.io/v1alpha2
15 | kind: Image
16 | metadata:
17 | name: $(workload.metadata.name)$
18 | spec:
19 | tag: $(params.image_prefix)$$(workload.metadata.name)$
20 | serviceAccountName: $(workload.spec.serviceAccountName)$
21 | builder:
22 | kind: ClusterBuilder
23 | name: java-builder
24 | source:
25 | blob:
26 | url: $(sources.tested-source.url)$
27 | build:
28 | env: $(workload.spec.build.env)$
--------------------------------------------------------------------------------
/code-analysis/supply-chain/code-analysis/sonar/run-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterRunTemplate
3 | metadata:
4 | name: tekton-sonar-taskrun
5 | spec:
6 | outputs:
7 | url: spec.params[?(@.name=="source-url")].value
8 | revision: spec.params[?(@.name=="source-revision")].value
9 | template:
10 | apiVersion: tekton.dev/v1beta1
11 | kind: TaskRun
12 | metadata:
13 | generateName: $(runnable.metadata.name)$-
14 | labels: $(runnable.metadata.labels)$
15 | spec:
16 | params:
17 | - name: source-url
18 | value: $(runnable.spec.inputs.source-url)$
19 | - name: source-revision
20 | value: $(runnable.spec.inputs.source-revision)$
21 | taskRef: {name: $(selected.metadata.name)$}
--------------------------------------------------------------------------------
/code-analysis/supply-chain/code-analysis/sonar/source-template.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: carto.run/v1alpha1
3 | kind: ClusterSourceTemplate
4 | metadata:
5 | name: tested-source
6 | spec:
7 | urlPath: .status.outputs.url
8 | revisionPath: .status.outputs.revision
9 |
10 | template:
11 | apiVersion: carto.run/v1alpha1
12 | kind: Runnable
13 | metadata:
14 | name: $(workload.metadata.name)$
15 | spec:
16 | serviceAccountName: $(workload.spec.serviceAccountName)$
17 | runTemplateRef:
18 | name: tekton-sonar-taskrun
19 |
20 | selector:
21 | resource:
22 | apiVersion: tekton.dev/v1beta1
23 | kind: Task
24 | matchingLabels:
25 | task: code-analysis
26 |
27 | inputs:
28 | source-url: $(sources.source.url)$
29 | source-revision: $(sources.source.revision)$
30 |
--------------------------------------------------------------------------------
/code-analysis/supply-chain/code-analysis/sonar/task.yml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | labels:
5 | task: code-analysis
6 | name: sonar
7 | namespace: default
8 | spec:
9 | params:
10 | - name: source-url
11 | - name: source-revision
12 | steps:
13 | - image: harbor-repo.vmware.com/dockerhub-proxy-cache/library/gradle
14 | name: code-analysis
15 | resources: {}
16 | script: |-
17 | cd `mktemp -d`
18 |
19 | wget -qO- $(params.source-url) | tar xvz
20 | chmod +x mvnw
21 | ./mvnw verify sonar:sonar
--------------------------------------------------------------------------------
/code-analysis/supply-chain/config/config-template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterConfigTemplate
5 | metadata:
6 | name: app-config
7 | spec:
8 | configPath: .data.manifest
9 |
10 | ytt: |
11 | #@ load("@ytt:data", "data")
12 | apiVersion: v1
13 | kind: ConfigMap
14 | metadata:
15 | name: #@ data.values.workload.metadata.name
16 | data:
17 | #@yaml/text-templated-strings
18 | manifest: |
19 | apiVersion: apps/v1
20 | kind: Deployment
21 | metadata:
22 | name: (@= data.values.workload.metadata.name @)-app
23 | spec:
24 | serviceAccountName: (@= data.values.workload.spec.serviceAccountName @)
25 | selector:
26 | matchLabels:
27 | app: (@= data.values.workload.metadata.name @)
28 | template:
29 | metadata:
30 | labels:
31 | app: (@= data.values.workload.metadata.name @)
32 | spec:
33 | containers:
34 | - name: main
35 | image: (@= data.values.image @)
--------------------------------------------------------------------------------
/code-analysis/supply-chain/deliverable/template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterTemplate
5 | metadata:
6 | name: deliverable-template
7 | spec:
8 | params:
9 | - name: gitops_server
10 | default: ""
11 | - name: gitops_repository
12 | default: ""
13 | - name: gitops_branch
14 | default: "main"
15 |
16 | ytt: |
17 | #@ load("@ytt:data", "data")
18 |
19 | #@ def giturl():
20 | #@ return "ssh://git@" + "/".join([
21 | #@ data.values.params.gitops_server,
22 | #@ data.values.params.gitops_repository
23 | #@ ])
24 | #@ end
25 |
26 | apiVersion: carto.run/v1alpha1
27 | kind: Deliverable
28 | metadata:
29 | name: #@ data.values.workload.metadata.name
30 | labels:
31 | workload-type: deliver
32 | workload-intent: code-analysis
33 | spec:
34 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
35 | source:
36 | git:
37 | url: #@ giturl()
38 | ref:
39 | branch: #@ data.values.params.gitops_branch
40 | commit: #@ data.values.source.revision
--------------------------------------------------------------------------------
/code-analysis/supply-chain/source/git-source-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSourceTemplate
3 | metadata:
4 | name: source
5 | spec:
6 | urlPath: .status.artifact.url
7 | revisionPath: .status.artifact.revision
8 |
9 | template:
10 | apiVersion: source.toolkit.fluxcd.io/v1beta1
11 | kind: GitRepository
12 | metadata:
13 | name: $(workload.metadata.name)$
14 | spec:
15 | interval: 1m0s
16 | url: $(workload.spec.source.git.url)$
17 | ref: $(workload.spec.source.git.ref)$
18 | secretRef:
19 | name: gitops-ssh-secret
--------------------------------------------------------------------------------
/code-analysis/supply-chain/supply-chain.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 VMware
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | ---
15 | #@ load("@ytt:data", "data")
16 | ---
17 | apiVersion: carto.run/v1alpha1
18 | kind: ClusterSupplyChain
19 | metadata:
20 | name: code-analysis-supply-chain
21 | spec:
22 | selector:
23 | workload-intent: code-analysis
24 | resources:
25 | - name: source-provider
26 | templateRef:
27 | kind: ClusterSourceTemplate
28 | name: source
29 |
30 | - name: source-tester-analyzer
31 | templateRef:
32 | kind: ClusterSourceTemplate
33 | name: tested-source
34 | sources:
35 | - resource: source-provider
36 | name: source
37 |
38 | - name: image-builder
39 | templateRef:
40 | kind: ClusterImageTemplate
41 | name: image
42 | params:
43 | - name: image_prefix
44 | value: #@ data.values.image_prefix
45 | sources:
46 | - resource: source-tester-analyzer
47 | name: tested-source
48 |
49 | - name: deployer
50 | templateRef:
51 | kind: ClusterTemplate
52 | name: app-deploy
53 | images:
54 | - resource: image-builder
55 | name: image
56 |
57 | - name: config-provider
58 | templateRef:
59 | kind: ClusterConfigTemplate
60 | name: app-config
61 | images:
62 | - resource: image-builder
63 | name: image
64 |
65 | - name: git-writer
66 | templateRef:
67 | kind: ClusterSourceTemplate
68 | name: git-writer-source # returns the commit sha of what was pushed to git
69 | configs:
70 | - resource: config-provider
71 | name: app-config
72 |
73 | - name: deliverable
74 | templateRef:
75 | kind: ClusterTemplate
76 | name: deliverable-template
77 | sources:
78 | - resource: git-writer
79 | name: git-writer-source # commit sha of what git-writter wrote is included in the deliverable
--------------------------------------------------------------------------------
/code-analysis/supply-chain/writer/git/run-template.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: carto.run/v1alpha1
3 | kind: ClusterRunTemplate
4 | metadata:
5 | name: git-writer
6 | spec:
7 | outputs:
8 | revision: '.status.taskResults[?(@.name=="commit")].value'
9 | template:
10 | apiVersion: tekton.dev/v1beta1
11 | kind: TaskRun
12 | metadata:
13 | generateName: $(runnable.metadata.name)$-
14 | spec:
15 | taskRef:
16 | name: git-cli
17 | workspaces:
18 | - name: source
19 | emptyDir: { }
20 | - name: input
21 | emptyDir: { }
22 | - name: ssh-directory
23 | secret:
24 | secretName: git-ssh-secret
25 | params:
26 | - name: GIT_USER_NAME
27 | value: $(runnable.spec.inputs.git_username)$
28 | - name: GIT_USER_EMAIL
29 | value: $(runnable.spec.inputs.git_user_email)$
30 | - name: USER_HOME
31 | value: /root
32 | - name: GIT_SCRIPT
33 | value: |
34 | export COMMIT_MESSAGE="$(runnable.spec.inputs.commit_message)$"
35 | export BRANCH="$(runnable.spec.inputs.branch)$"
36 | if [[ -n "$(runnable.spec.inputs.skip_host_checking)$" && "$(runnable.spec.inputs.skip_host_checking)$" = true ]]
37 | then
38 | export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
39 | fi
40 | if [[ -n "$(runnable.spec.inputs.git_ssh_variant)$" ]]
41 | then
42 | export GIT_SSH_VARIANT="$(runnable.spec.inputs.git_ssh_variant)$"
43 | fi
44 | git init
45 | if [[ -n "$(runnable.spec.inputs.git_server_port)$" ]]; then
46 | git remote add origin $(runnable.spec.inputs.git_ssh_user)$@$(runnable.spec.inputs.git_server)$:$(runnable.spec.inputs.git_server_port)$/$(runnable.spec.inputs.git_repository)$
47 | else
48 | git remote add origin $(runnable.spec.inputs.git_ssh_user)$@$(runnable.spec.inputs.git_server)$:$(runnable.spec.inputs.git_repository)$
49 | fi
50 | # TODO remove the fetch and branch
51 | git fetch
52 | git branch
53 | git pull origin "`git remote show origin | grep "HEAD branch" | sed 's/.*: //'`"
54 | git pull origin "$BRANCH" || git branch "$BRANCH"
55 | git checkout "$BRANCH"
56 | export CONFIG_MAP_FIELD=$(runnable.spec.inputs.input_config_map_field)$
57 | export DATA="$(runnable.spec.inputs.data)$"
58 | echo "$DATA" | tee "$CONFIG_MAP_FIELD"
59 | git add .
60 | git commit --allow-empty -m "$COMMIT_MESSAGE"
61 | git push --set-upstream origin "$BRANCH"
--------------------------------------------------------------------------------
/code-analysis/supply-chain/writer/git/secret.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | ---
4 | apiVersion: v1
5 | kind: Secret
6 | metadata:
7 | name: git-ssh-secret
8 | data:
9 | id_rsa: #@ data.values.git_writer.base64_encoded_ssh_key
10 | known_hosts: #@ data.values.git_writer.base64_encoded_known_hosts
--------------------------------------------------------------------------------
/code-analysis/supply-chain/writer/git/source-template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterSourceTemplate
5 | metadata:
6 | name: git-writer-source
7 | spec:
8 | urlPath: .status.outputs.revision # this is unused, yet needs to be valued to be deemed a valid ClusterSourceTemplate output
9 | revisionPath: .status.outputs.revision
10 | params:
11 | - name: git_writer_username
12 | default: #@ data.values.git_writer.username
13 | - name: git_writer_user_email
14 | default: #@ data.values.git_writer.user_email
15 | - name: git_writer_commit_message
16 | default: #@ data.values.git_writer.message
17 | - name: git_writer_ssh_user
18 | default: #@ data.values.git_writer.ssh_user
19 | - name: git_writer_server
20 | default: #@ data.values.git_writer.server
21 | - name: git_writer_port
22 | default: #@ data.values.git_writer.port
23 | - name: git_writer_repository
24 | default: #@ data.values.git_writer.repository
25 | - name: git_writer_branch
26 | default: #@ data.values.git_writer.branch
27 | - name: git_writer_skip_host_checking
28 | default: false
29 | - name: git_writer_ssh_variant
30 | default: ssh
31 | template:
32 | apiVersion: carto.run/v1alpha1
33 | kind: Runnable
34 | metadata:
35 | name: $(workload.metadata.name)$-git-writer
36 | spec:
37 | serviceAccountName: $(workload.spec.serviceAccountName)$
38 | runTemplateRef:
39 | name: git-writer
40 |
41 | inputs:
42 | input_config_map_name: $(workload.metadata.name)$
43 | input_config_map_field: manifest.yaml
44 |
45 | git_username: $(params.git_writer_username)$
46 | git_user_email: $(params.git_writer_user_email)$
47 | commit_message: $(params.git_writer_commit_message)$
48 | git_ssh_user: $(params.git_writer_ssh_user)$
49 | git_server: $(params.git_writer_server)$
50 | git_server_port: $(params.git_writer_port)$
51 | git_repository: $(params.git_writer_repository)$
52 | branch: $(params.git_writer_branch)$
53 | skip_host_checking: $(params.git_writer_skip_host_checking)$
54 | git_ssh_variant: $(params.git_writer_ssh_variant)$
55 | data: $(config)$
--------------------------------------------------------------------------------
/code-analysis/workload.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: Workload
5 | metadata:
6 | name: code-analysis
7 | namespace: default
8 | labels:
9 | app.kubernetes.io/part-of: code-analysis
10 | workload-intent: code-analysis
11 | spec:
12 | serviceAccountName: #@ data.values.service_account_name
13 | params:
14 | - name: gitops_server
15 | value: github.com
16 | - name: gitops_repository
17 | value: Mpluya/code-analysis-config
18 | - name: gitops_branch
19 | value: main
20 | source:
21 | git:
22 | ref:
23 | branch: main
24 | url: ssh://git@github.com/Mpluya/code-analysis
25 |
--------------------------------------------------------------------------------
/github-pr/README.md:
--------------------------------------------------------------------------------
1 | ## Run the github pull request use case
2 |
3 | This is an enhancement on top of the out of the box supply chain templates provided with TAP such that the config produced from a supply chain gets put in a pull request. Adding a pull request in the workflow provides an opportunity for a review before 'change' is realized in a target environment. This is especially important in highly regulated organizations where change management is enforced where every change affecting production has to be reviewed.
4 |
5 | ## Assumption
6 | TAP is installed including any of the out of the box supply chains.
7 |
8 | ## Installation
9 | 1. Follow the instructions for making [Live modification of supply chains and templates](https://docs.vmware.com/en/Tanzu-Application-Platform/1.1/tap/GUID-scc-authoring-supply-chains.html#live-modification-of-supply-chains-and-templates-6).
10 |
11 | Below are the actual steps taken:
12 | - pause reconciliation of tap meta package
13 | ```
14 | kubectl patch packageinstall/tap -n tap-install -p '{"spec":{"paused":true}}' --type=merge
15 | ```
16 | - pause reconciliation of the supply chain applied in your cluster (this example uses testing-scanning)
17 | ```
18 | kubectl patch packageinstall/ootb-supply-chain-testing-scanning -n tap-install -p '{"spec":{"paused":true}}' --type=merge
19 | ```
20 |
21 | 2. Add `tekton-taskrun` (ClusterRunTemplate used by config-writer) to the template exclusion list in tap values.
22 | ```
23 | ootb_templates:
24 | excluded_templates:
25 | - 'tekton-taskrun'
26 | ```
27 |
28 | Update tap - `tanzu package installed update tap -p tap.tanzu.vmware.com -v $TAP_VERSION --values-file tap-values.yml -n tap-install`
29 |
30 |
31 | > assumes current working directory is `repo-root/github-pr`
32 |
33 | 3. Apply the templates (`kubectl apply -f .`) under supply-chain/config-writer and supply-chain/pull-request. If you prefer to use kapp run `kapp deploy -a custom-templates -f .`
34 |
35 | 4. Update the ClusterSupplyChain. This example uses the testing scanning implementation.
36 | ```
37 | kubectl replace -f source-test-scan-to-url.yml --replace
38 | ```
39 |
40 | If you're using either basic or testing supply chain, you can still pick up the enhancements from the full sample (source-test-scan-to-url.yml) provided in this repo and apply the following:
41 | - replace the config-writer with the content between comments `# updated config writer template` and `# end updated config writer template`.
42 |
43 | > Note: the sources section will need to be adjusted, for basic - source-provider, for testing - source-tester.
44 |
45 | - add github-pull-request template section
46 |
47 | Cluster supply chain snippet :
48 | ```
49 | - name: config-writer
50 | templateRef:
51 | kind: ClusterSourceTemplate
52 | name: config-writer-source-template
53 | configs:
54 | - resource: app-config
55 | name: config
56 | sources:
57 | - resource: [source-provider | source-tester]
58 | name: source
59 | params:
60 | - name: serviceAccount
61 | value: default
62 | - name: registry
63 | value:
64 | repository: [ootb supply chain registry repository provided in tap values]
65 | server: [ootb supply chain registry server provided in tap values]
66 |
67 | - name: github-pull-request
68 | templateRef:
69 | kind: ClusterTemplate
70 | name: pull-request
71 | sources:
72 | - resource: config-writer
73 | name: config-writer-source-template
74 | ```
--------------------------------------------------------------------------------
/github-pr/supply-chain/config-writer/run-template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | #@ if/end "tekton-taskrun" not in data.values.excluded_templates:
4 | ---
5 | apiVersion: carto.run/v1alpha1
6 | kind: ClusterRunTemplate
7 | metadata:
8 | name: tekton-taskrun
9 | spec:
10 | outputs:
11 | url: spec.params[?(@.name=="git_repository")].value
12 | revision: spec.params[?(@.name=="git_branch")].value
13 | template:
14 | apiVersion: tekton.dev/v1beta1
15 | kind: TaskRun
16 | metadata:
17 | generateName: $(runnable.metadata.name)$-
18 | labels: $(runnable.metadata.labels)$
19 | spec:
20 | serviceAccountName: $(runnable.spec.inputs.serviceAccount)$
21 | taskRef: $(runnable.spec.inputs.taskRef)$
22 | params: $(runnable.spec.inputs.params)$
23 |
--------------------------------------------------------------------------------
/github-pr/supply-chain/config-writer/source-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSourceTemplate
3 | metadata:
4 | name: config-writer-source-template
5 | spec:
6 | urlPath: .status.outputs.url
7 | revisionPath: .status.outputs.revision
8 | params:
9 | - default: default
10 | name: serviceAccount
11 | - default: {}
12 | name: registry
13 | ytt: |
14 | #@ load("@ytt:data", "data")
15 | #@ load("@ytt:json", "json")
16 | #@ load("@ytt:base64", "base64")
17 |
18 | #@ def has_git_params():
19 | #@ if 'gitops_repository_prefix' in data.values.params:
20 | #@ return True
21 | #@ end
22 | #@
23 | #@ if 'gitops_repository' in data.values.params:
24 | #@ return True
25 | #@ end
26 | #@
27 | #@ return False
28 | #@ end
29 |
30 | #@ def is_gitops():
31 | #@ return has_git_params()
32 | #@ end
33 |
34 | #@ def param(key):
35 | #@ if not key in data.values.params:
36 | #@ return None
37 | #@ end
38 | #@ return data.values.params[key]
39 | #@ end
40 |
41 | #@ def git_repository():
42 | #@ if 'gitops_repository' in data.values.params:
43 | #@ return param("gitops_repository")
44 | #@ end
45 | #@
46 | #@ prefix = param("gitops_repository_prefix")
47 | #@ return prefix + data.values.workload.metadata.name + ".git"
48 | #@ end
49 |
50 | #@ def git_revision():
51 | #@ return (data.values.source.revision.split("/")[1])[0:7]
52 | #@ end
53 |
54 | #@ def image():
55 | #@ return "/".join([
56 | #@ data.values.params.registry.server,
57 | #@ data.values.params.registry.repository,
58 | #@ "-".join([
59 | #@ data.values.workload.metadata.name,
60 | #@ data.values.workload.metadata.namespace,
61 | #@ "bundle",
62 | #@ ])
63 | #@ ]) + ":" + data.values.workload.metadata.uid
64 | #@ end
65 |
66 |
67 | ---
68 | apiVersion: carto.run/v1alpha1
69 | kind: Runnable
70 | metadata:
71 | name: #@ data.values.workload.metadata.name + "-config-writer"
72 | labels:
73 | app.kubernetes.io/component: config-writer
74 | #@ if/end hasattr(data.values.workload.metadata, "labels") and hasattr(data.values.workload.metadata.labels, "app.kubernetes.io/part-of"):
75 | app.kubernetes.io/part-of: #@ data.values.workload.metadata.labels["app.kubernetes.io/part-of"]
76 | spec:
77 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
78 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
79 |
80 | runTemplateRef:
81 | name: tekton-taskrun
82 |
83 | inputs:
84 | serviceAccount: #@ data.values.params.serviceAccount
85 | taskRef:
86 | kind: ClusterTask
87 | name: #@ "git-writer" if is_gitops() else "image-writer"
88 | params:
89 | #@ if is_gitops():
90 | - name: git_repository
91 | value: #@ git_repository()
92 | - name: git_branch
93 | value: #@ git_revision()
94 | - name: git_user_name
95 | value: #@ param("gitops_user_name")
96 | - name: git_user_email
97 | value: #@ param("gitops_user_email")
98 | - name: git_commit_message
99 | value: #@ param("gitops_commit_message")
100 | - name: git_files
101 | value: #@ base64.encode(json.encode(data.values.config))
102 | #@ else:
103 | - name: files
104 | value: #@ base64.encode(json.encode(data.values.config))
105 | - name: bundle
106 | value: #@ image()
107 | #@ end
--------------------------------------------------------------------------------
/github-pr/supply-chain/pull-request/run-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterRunTemplate
3 | metadata:
4 | name: github-open-pr-taskrun
5 | spec:
6 | template:
7 | apiVersion: tekton.dev/v1beta1
8 | kind: TaskRun
9 | metadata:
10 | generateName: $(runnable.metadata.name)$-
11 | labels:
12 | $(runnable.metadata.labels)$
13 | spec:
14 | serviceAccountName: $(runnable.spec.inputs.serviceAccount)$
15 | taskRef: {name: $(selected.metadata.name)$}
16 | params:
17 | - name: REPO_FULL_NAME
18 | value: $(runnable.spec.inputs.repo)$
19 | - name: HEAD
20 | value: $(runnable.spec.inputs.fromBranch)$
21 | - name: BASE
22 | value: $(runnable.spec.inputs.toBranch)$
23 | - name: TITLE
24 | value: $(runnable.spec.inputs.title)$
25 | - name: BODY
26 | value: $(runnable.spec.inputs.body)$
--------------------------------------------------------------------------------
/github-pr/supply-chain/pull-request/task.yml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: github-open-pr-task
5 | labels:
6 | task: open-github-pr
7 | annotations:
8 | tekton.dev/categories: Git
9 | tekton.dev/pipelines.minVersion: "0.12.1"
10 | tekton.dev/tags: github
11 | tekton.dev/displayName: "open github pull request"
12 | tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le"
13 | spec:
14 | description: >-
15 | This task will open a PR on Github based on several parameters.
16 | This could be useful in GitOps repositories for example.
17 |
18 | params:
19 | - name: GITHUB_HOST_URL
20 | description: |
21 | The GitHub host, adjust this if you run a GitHub enteprise.
22 | default: "api.github.com"
23 | type: string
24 |
25 | - name: API_PATH_PREFIX
26 | description: |
27 | The API path prefix, GitHub Enterprise has a prefix e.g. /api/v3
28 | default: ""
29 | type: string
30 |
31 | - name: REPO_FULL_NAME
32 | description: |
33 | The GitHub repository full name, e.g.: tektoncd/catalog
34 | type: string
35 |
36 | - name: GITHUB_TOKEN_SECRET_NAME
37 | description: |
38 | The name of the kubernetes secret that contains the GitHub token, default: github
39 | type: string
40 | default: github
41 |
42 | - name: GITHUB_TOKEN_SECRET_KEY
43 | description: |
44 | The key within the kubernetes secret that contains the GitHub token, default: token
45 | type: string
46 | default: token
47 |
48 | - name: AUTH_TYPE
49 | description: |
50 | The type of authentication to use. You could use the less secure "Basic" for example
51 | type: string
52 | default: Bearer
53 |
54 | - name: HEAD
55 | description: |
56 | The name of the branch where your changes are implemented.
57 | type: string
58 |
59 | - name: BASE
60 | description: |
61 | The name of the branch you want the changes pulled into.
62 | type: string
63 |
64 | - name: BODY
65 | description: |
66 | The body description of the pull request.
67 | type: string
68 |
69 | - name: TITLE
70 | description: |
71 | The title of the pull request.
72 | type: string
73 |
74 | results:
75 | - name: NUMBER
76 | description: Number of the created pull request.
77 |
78 | - name: URL
79 | description: URL of the created pull request.
80 |
81 | volumes:
82 | - name: githubtoken
83 | secret:
84 | secretName: $(params.GITHUB_TOKEN_SECRET_NAME)
85 |
86 | steps:
87 | - name: open-pr
88 | volumeMounts:
89 | - name: githubtoken
90 | readOnly: true
91 | mountPath: /etc/github-open-pr
92 | env:
93 | - name: PULLREQUEST_NUMBER_PATH
94 | value: $(results.NUMBER.path)
95 | - name: PULLREQUEST_URL_PATH
96 | value: $(results.URL.path)
97 |
98 | image: registry.access.redhat.com/ubi8/python-38:1-34.1599745032
99 | script: |
100 | #!/usr/libexec/platform-python
101 |
102 | """This script will open a PR on Github"""
103 |
104 | import json
105 | import os
106 | import sys
107 | import http.client
108 |
109 | github_token = open("/etc/github-open-pr/$(params.GITHUB_TOKEN_SECRET_KEY)", "r").read()
110 |
111 | open_pr_url = "$(params.API_PATH_PREFIX)" + "/repos/$(params.REPO_FULL_NAME)/pulls"
112 |
113 | data = {
114 | "head": "$(params.HEAD)",
115 | "base": "$(params.BASE)",
116 | "title": "$(params.TITLE)",
117 | "body": """$(params.BODY)"""
118 | }
119 | print("Sending this data to GitHub: ")
120 | print(data)
121 |
122 | authHeader = "$(params.AUTH_TYPE) " + github_token
123 |
124 | # This is for our fake github server
125 | if "$(params.GITHUB_HOST_URL)".startswith("http://"):
126 | conn = http.client.HTTPConnection("$(params.GITHUB_HOST_URL)"
127 | .replace("http://", ""))
128 | else:
129 | conn = http.client.HTTPSConnection("$(params.GITHUB_HOST_URL)")
130 |
131 | conn.request(
132 | "POST",
133 | open_pr_url,
134 | body=json.dumps(data),
135 | headers={
136 | "User-Agent": "TektonCD, the peaceful cat",
137 | "Authorization": authHeader,
138 | "Accept": "application/vnd.github.v3+json ",
139 | })
140 | resp = conn.getresponse()
141 | if not str(resp.status).startswith("2"):
142 | print("Error: %d" % (resp.status))
143 | print(resp.read())
144 | sys.exit(1)
145 | else:
146 | # https://docs.github.com/en/rest/reference/pulls#create-a-pull-request
147 | body = json.loads(resp.read().decode())
148 |
149 | open(os.environ.get('PULLREQUEST_NUMBER_PATH'), 'w').write(f'{body["number"]}')
150 | open(os.environ.get('PULLREQUEST_URL_PATH'), 'w').write(body["html_url"])
151 |
152 | print("GitHub pull request created for $(params.REPO_FULL_NAME): "
153 | f'number={body["number"]} url={body["html_url"]}')
--------------------------------------------------------------------------------
/github-pr/supply-chain/pull-request/template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterTemplate
5 | metadata:
6 | name: pull-request
7 | spec:
8 | params:
9 | - name: pr_title
10 | default: "Supply chain produced a deliverable"
11 | - name: pr_body
12 | default: "Please review the updated artifacts."
13 | - name: serviceAccount
14 | default: default
15 |
16 | ytt: |
17 | #@ load("@ytt:data", "data")
18 |
19 | #@ def repo_host():
20 | #@ source_url = data.values.source.url
21 | #@ if source_url.startswith("ssh"):
22 | #@ return (source_url.split("ssh://git@github.com/")[1]).split(".git")[0]
23 | #@ end
24 | #@
25 | #@ return (source_url.split("https://git@github.com/")[1]).split(".git")[0]
26 | #@ end
27 |
28 | ---
29 | apiVersion: carto.run/v1alpha1
30 | kind: Runnable
31 | metadata:
32 | name: #@ data.values.workload.metadata.name + "-pull-request"
33 | labels:
34 | tekton.dev/task: github-open-pr
35 | app.kubernetes.io/component: pull-request
36 | #@ if/end hasattr(data.values.workload.metadata, "labels") and hasattr(data.values.workload.metadata.labels, "app.kubernetes.io/part-of"):
37 | app.kubernetes.io/part-of: #@ data.values.workload.metadata.labels["app.kubernetes.io/part-of"]
38 | spec:
39 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
40 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
41 |
42 | runTemplateRef:
43 | name: github-open-pr-taskrun
44 |
45 | selector:
46 | resource:
47 | apiVersion: tekton.dev/v1beta1
48 | kind: Task
49 | matchingLabels:
50 | task: open-github-pr
51 |
52 | inputs:
53 | serviceAccount: #@ data.values.params.serviceAccount
54 | repo: #@ repo_host()
55 | fromBranch: #@ data.values.source.revision
56 | toBranch: #@ data.values.params["gitops_branch"]
57 | title: #@ data.values.params.pr_title
58 | body: #@ data.values.params.pr_body
--------------------------------------------------------------------------------
/github-pr/supply-chain/source-test-scan-to-url.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSupplyChain
3 | metadata:
4 | name: source-test-scan-to-url
5 | spec:
6 | params:
7 | - default: main
8 | name: gitops_branch
9 | - default: supplychain
10 | name: gitops_user_name
11 | - default: supplychain
12 | name: gitops_user_email
13 | - default: supplychain@cluster.local
14 | name: gitops_commit_message
15 | - default: gitops-ssh
16 | name: gitops_ssh_secret
17 | resources:
18 | - name: source-provider
19 | params:
20 | - name: serviceAccount
21 | value: default
22 | - name: gitImplementation
23 | value: go-git
24 | templateRef:
25 | kind: ClusterSourceTemplate
26 | name: source-template
27 | - name: deliverable
28 | params:
29 | - name: registry
30 | value:
31 | repository: tapsme
32 | server: index.docker.io
33 | templateRef:
34 | kind: ClusterTemplate
35 | name: deliverable-template
36 | - name: source-tester
37 | sources:
38 | - name: source
39 | resource: source-provider
40 | templateRef:
41 | kind: ClusterSourceTemplate
42 | name: testing-pipeline
43 | - name: source-scanner
44 | sources:
45 | - name: source
46 | resource: source-tester
47 | templateRef:
48 | kind: ClusterSourceTemplate
49 | name: source-scanner-template
50 | - name: image-builder
51 | params:
52 | - name: serviceAccount
53 | value: default
54 | - name: clusterBuilder
55 | value: default
56 | - name: registry
57 | value:
58 | repository: tapsme
59 | server: index.docker.io
60 | sources:
61 | - name: source
62 | resource: source-scanner
63 | templateRef:
64 | kind: ClusterImageTemplate
65 | name: kpack-template
66 | - images:
67 | - name: image
68 | resource: image-builder
69 | name: image-scanner
70 | templateRef:
71 | kind: ClusterImageTemplate
72 | name: image-scanner-template
73 | - images:
74 | - name: image
75 | resource: image-scanner
76 | name: config-provider
77 | params:
78 | - name: serviceAccount
79 | value: default
80 | templateRef:
81 | kind: ClusterConfigTemplate
82 | name: convention-template
83 | - configs:
84 | - name: config
85 | resource: config-provider
86 | name: app-config
87 | templateRef:
88 | kind: ClusterConfigTemplate
89 | name: config-template
90 |
91 | # updated config writer template
92 | - name: config-writer
93 | templateRef:
94 | kind: ClusterSourceTemplate
95 | name: config-writer-source-template
96 | configs:
97 | - resource: app-config
98 | name: config
99 | sources:
100 | - resource: source-scanner
101 | name: source-scanner-template
102 | params:
103 | - name: serviceAccount
104 | value: default
105 | - name: registry
106 | value:
107 | repository: tapsme
108 | server: index.docker.io
109 | # end updated config writer template
110 |
111 | - name: github-pull-request
112 | templateRef:
113 | kind: ClusterTemplate
114 | name: pull-request
115 | sources:
116 | - resource: config-writer
117 | name: config-writer-source-template
118 |
119 | selector:
120 | apps.tanzu.vmware.com/has-tests: "true"
121 | apps.tanzu.vmware.com/workload-type: web
--------------------------------------------------------------------------------
/image-prebuilt/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x95castle1/custom-cartographer-supply-chain-examples/6f0778ce94efc310684215e82308c34d8cb2e127/image-prebuilt/.DS_Store
--------------------------------------------------------------------------------
/image-prebuilt/README.md:
--------------------------------------------------------------------------------
1 | ## Run the image-prebuilt use case
2 |
3 | This example can be run alongside an existing TAP installation that has the out of the box supply chain - testing and scanning.
4 | If you wish to run this on a cluster that doesnt have TAP, the steps in the prerequisites section are required.
5 | Either approaches (with or without pre-existing TAP install) have been validated and should work.
6 |
7 | ## Prerequisites
8 | 1. Add Tanzu TAP repository
9 |
10 | ```bash
11 | export INSTALL_REGISTRY_USERNAME='[tanzu net username]'
12 | export INSTALL_REGISTRY_PASSWORD='[tanzu net password]'
13 | export INSTALL_REGISTRY_HOSTNAME=registry.tanzu.vmware.com
14 | export TAP_VERSION=[version]
15 |
16 | tanzu secret registry add tap-registry \
17 | --username ${INSTALL_REGISTRY_USERNAME} --password ${INSTALL_REGISTRY_PASSWORD} \
18 | --server ${INSTALL_REGISTRY_HOSTNAME} \
19 | --export-to-all-namespaces --yes
20 |
21 | tanzu package repository add tanzu-tap-repository \
22 | --url registry.tanzu.vmware.com/tanzu-application-platform/tap-packages:$TAP_VERSION
23 | ```
24 |
25 | 2. Install Tanzu Source Controller
26 | ```bash
27 | tanzu package install source-controller -p controller.source.apps.tanzu.vmware.com -v [x.x.x]
28 | ```
29 |
30 | 3. Install Supply Chain Security Tools - Scan
31 | ```bash
32 | tanzu package install scan-controller --package-name scanning.apps.tanzu.vmware.com --version [x.x.x]
33 | ```
34 |
35 | 4. Install Supply Chain Security Tools - Store
36 | ```bash
37 | tanzu package install metadata-store --package-name metadata-store.apps.tanzu.vmware.com --version [x.x.x]
38 | ```
39 |
40 |
41 | ## Run
42 | > assumes current working directory is `repo-root/image-prebuilt`:
43 | ```
44 | kapp deploy --yes -a image-prebuilt-demo -c \
45 | -f <(ytt --ignore-unknown-comments -f . -f ../values.yml) \
46 | -f <(ytt --ignore-unknown-comments -f ../shared -f ../values.yml)
47 | ```
48 |
49 | ## View scan results
50 | Follow the instructions [here](https://docs.vmware.com/en/Tanzu-Application-Platform/1.0/tap/GUID-scst-store-additional.html)
--------------------------------------------------------------------------------
/image-prebuilt/delivery/delivery.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterDelivery
3 | metadata:
4 | name: delivery-image-prebuilt
5 | spec:
6 | selector:
7 | deliverable-intent: image-prebuilt
8 | resources:
9 | - name: image-provider
10 | templateRef:
11 | kind: ClusterSourceTemplate
12 | name: deliverable-image-source
13 |
14 | - name: deployer
15 | templateRef:
16 | kind: ClusterDeploymentTemplate
17 | name: app-deploy-tpl
18 | # in a supply chain, the output of a source template is only available as a `source`
19 | # in a delivery, a source template's output can be consumed as a `deployment`
20 | # every ClusterDeploymentTemplate must be passed exactly one deployment. the deployment
21 | # is not named (as other inputs can be)
22 | deployment:
23 | resource: image-provider
--------------------------------------------------------------------------------
/image-prebuilt/delivery/source/image/source-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSourceTemplate
3 | metadata:
4 | name: deliverable-image-source
5 | spec:
6 | revisionPath: .status.artifact.revision
7 | urlPath: .status.artifact.url
8 |
9 | template:
10 | apiVersion: source.apps.tanzu.vmware.com/v1alpha1
11 | kind: ImageRepository
12 | metadata:
13 | name: $(deliverable.metadata.name)$-app
14 | spec:
15 | serviceAccount: $(deliverable.spec.serviceAccountName)$
16 | interval: 1m0s
17 | image: $(deliverable.spec.source.image)$
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/config/config-template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterConfigTemplate
5 | metadata:
6 | name: app-config
7 | spec:
8 | configPath: .data
9 | params:
10 | - name: registry_server
11 | default: ""
12 | - name: registry_repository
13 | default: ""
14 |
15 | ytt: |
16 | #@ load("@ytt:data", "data")
17 | #@ load("@ytt:yaml", "yaml")
18 |
19 | #@ def delivery():
20 | apiVersion: apps/v1
21 | kind: Deployment
22 | metadata:
23 | name: #@ data.values.workload.metadata.name + "-app"
24 | spec:
25 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
26 | selector:
27 | matchLabels:
28 | app: #@ data.values.workload.metadata.name
29 | template:
30 | metadata:
31 | labels:
32 | app: #@ data.values.workload.metadata.name
33 | spec:
34 | containers:
35 | - name: main
36 | image: #@ data.values.image
37 | #@ end
38 |
39 | apiVersion: v1
40 | kind: ConfigMap
41 | metadata:
42 | name: #@ data.values.workload.metadata.name
43 | data:
44 | delivery.yml: #@ yaml.encode(delivery())
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/deliverable/template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterTemplate
3 | metadata:
4 | name: deliverable-tpl
5 | spec:
6 | params:
7 | - default: {}
8 | name: registry
9 | ytt: |
10 | #@ load("@ytt:data", "data")
11 |
12 | #@ def image():
13 | #@ return "/".join([
14 | #@ data.values.params.registry_server,
15 | #@ data.values.params.registry_repository,
16 | #@ "-".join([
17 | #@ data.values.workload.metadata.name,
18 | #@ data.values.workload.metadata.namespace,
19 | #@ "bundle",
20 | #@ ])
21 | #@ ]) + ":" + data.values.workload.metadata.uid
22 | #@ end
23 |
24 |
25 | ---
26 | apiVersion: carto.run/v1alpha1
27 | kind: Deliverable
28 | metadata:
29 | name: #@ data.values.workload.metadata.name
30 | labels:
31 | deliverable-intent: image-prebuilt
32 | #@ if/end hasattr(data.values.workload.metadata, "labels") and hasattr(data.values.workload.metadata.labels, "app.kubernetes.io/part-of"):
33 | app.kubernetes.io/part-of: #@ data.values.workload.metadata.labels["app.kubernetes.io/part-of"]
34 | spec:
35 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
36 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
37 |
38 | source:
39 | image: #@ image()
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/scan/image/image-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterImageTemplate
3 | metadata:
4 | name: image
5 | spec:
6 | imagePath: .status.compliantArtifact.registry.image
7 | ytt: |
8 | #@ load("@ytt:data", "data")
9 | apiVersion: scanning.apps.tanzu.vmware.com/v1beta1
10 | kind: ImageScan
11 | metadata:
12 | name: #@ data.values.workload.metadata.name
13 | labels:
14 | app.kubernetes.io/component: image-scan
15 | spec:
16 | registry:
17 | image: #@ data.values.image
18 | scanTemplate: image-scan-template
19 | scanPolicy: sample-scan-policy
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/scan/image/scan-policy.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | items:
3 | - apiVersion: scanning.apps.tanzu.vmware.com/v1beta1
4 | kind: ScanPolicy
5 | metadata:
6 | name: sample-scan-policy
7 | namespace: default
8 | spec:
9 | regoFile: |
10 | package policies
11 |
12 | default isCompliant = false
13 |
14 | # Accepted Values: "Critical", "High", "Medium", "Low", "Negligible", "UnknownSeverity"
15 | violatingSeverities := ["UnknownSeverity"] # ATTENTION: this should include Critical, High, and Medium but temporarily defaulting to just UnknownSeverity for demo purposes
16 | ignoreCVEs := []
17 |
18 | contains(array, elem) = true {
19 | array[_] = elem
20 | } else = false { true }
21 |
22 | isSafe(match) {
23 | fails := contains(violatingSeverities, match.Ratings.Rating[_].Severity)
24 | not fails
25 | }
26 |
27 | isSafe(match) {
28 | ignore := contains(ignoreCVEs, match.Id)
29 | ignore
30 | }
31 |
32 | isCompliant = isSafe(input.currentVulnerability)
33 | kind: List
34 | metadata:
35 | resourceVersion: ""
36 | selfLink: ""
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/scan/image/scan-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: scanning.apps.tanzu.vmware.com/v1beta1
2 | kind: ScanTemplate
3 | metadata:
4 | name: image-scan-template
5 | namespace: default
6 | spec:
7 | template:
8 | containers:
9 | - args:
10 | - -c
11 | - ./image/copy-docker-config.sh /secret-data && ./image/scan-image.sh /workspace
12 | scan.xml true
13 | command:
14 | - /bin/bash
15 | image: registry.tanzu.vmware.com/tanzu-application-platform/tap-packages@sha256:bdce1113e2c940305fa9fd34d7cae2dce247c3e309fcd442efc769b590aa19e4
16 | imagePullPolicy: IfNotPresent
17 | name: scanner
18 | resources:
19 | limits:
20 | cpu: 1000m
21 | requests:
22 | cpu: 250m
23 | memory: 128Mi
24 | volumeMounts:
25 | - mountPath: /.docker
26 | name: docker
27 | readOnly: false
28 | - mountPath: /workspace
29 | name: workspace
30 | readOnly: false
31 | - mountPath: /secret-data
32 | name: registry-cred
33 | readOnly: true
34 | imagePullSecrets:
35 | - name: tanzu-reg-cred
36 | restartPolicy: Never
37 | securityContext:
38 | runAsNonRoot: true
39 | volumes:
40 | - emptyDir: {}
41 | name: docker
42 | - emptyDir: {}
43 | name: workspace
44 | - name: registry-cred
45 | secret:
46 | secretName: reg-cred
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/source/image-repo-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterImageTemplate
3 | metadata:
4 | name: prebuilt-image
5 | spec:
6 | imagePath: .spec.image
7 |
8 | template:
9 | apiVersion: source.apps.tanzu.vmware.com/v1alpha1
10 | kind: ImageRepository
11 | metadata:
12 | name: $(workload.metadata.name)$
13 | spec:
14 | serviceAccount: $(workload.spec.serviceAccountName)$
15 | interval: 1m0s
16 | image: $(workload.spec.source.image)$
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/supply-chain.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: carto.run/v1alpha1
3 | kind: ClusterSupplyChain
4 | metadata:
5 | name: image-prebuilt-supply-chain
6 | spec:
7 | selector:
8 | workload-intent: image-prebuilt
9 | resources:
10 | - name: image-provider
11 | templateRef:
12 | kind: ClusterImageTemplate
13 | name: prebuilt-image
14 |
15 | - name: image-scanner
16 | templateRef:
17 | kind: ClusterImageTemplate
18 | name: image
19 | images:
20 | - resource: image-provider
21 | name: prebuilt-image
22 |
23 | - name: deployer
24 | templateRef:
25 | kind: ClusterTemplate
26 | name: app-deploy
27 | images:
28 | - resource: image-scanner
29 | name: image
30 |
31 | - name: config-provider
32 | templateRef:
33 | kind: ClusterConfigTemplate
34 | name: app-config
35 | images:
36 | - resource: image-scanner
37 | name: image
38 |
39 | # writes config from app-config to be pushed as a bundle by imgpkg
40 | - name: image-writer
41 | templateRef:
42 | kind: ClusterTemplate
43 | name: image-writer
44 | configs:
45 | - resource: config-provider
46 | name: app-config
47 |
48 | - name: deliverable
49 | templateRef:
50 | kind: ClusterTemplate
51 | name: deliverable-tpl
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/writer/run-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterRunTemplate
3 | metadata:
4 | name: tekton-taskrun-tpl
5 | spec:
6 | template:
7 | apiVersion: tekton.dev/v1beta1
8 | kind: TaskRun
9 | metadata:
10 | generateName: $(runnable.metadata.name)$-
11 | labels: $(runnable.metadata.labels)$
12 | spec:
13 | params: $(runnable.spec.inputs.params)$
14 | serviceAccountName: $(runnable.spec.inputs.serviceAccount)$
15 | taskRef: $(runnable.spec.inputs.taskRef)$
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/writer/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | apiVersion: tekton.dev/v1beta1
4 | kind: ClusterTask
5 | metadata:
6 | name: image-writer-task
7 | spec:
8 | description: |-
9 | a task that writes a given set of files (provided as a json base64-encoded)
10 | to a container image registry as an image making use of the imgpkg bundle
11 | format.
12 | params:
13 | - description: name of the registry + repository to push the bundle to
14 | name: bundle
15 | type: string
16 | - description: |
17 | base64-encoded json map of files to write to registry, for example - eyAiUkVBRE1FLm1kIjogIiMgUmVhZG1lIiB9
18 | name: files
19 | type: string
20 | steps:
21 | - image: registry.tanzu.vmware.com/tanzu-application-platform/tap-packages@sha256:e5e961933dfc7406d708c88b3226d7fe79266a58b75e2de93ca640ccd310f78d
22 | name: main
23 | resources: {}
24 | script: |-
25 | #!/usr/bin/env bash
26 |
27 | set -o errexit
28 | set -o xtrace
29 |
30 | cd `mktemp -d`
31 |
32 | echo -e "$(params.files)" | base64 --decode > files.json
33 | eval "$(cat files.json | jq -r 'to_entries | .[] | @sh "mkdir -p $(dirname \(.key)) && echo \(.value) > \(.key)"')"
34 |
35 | mkdir -p .imgpkg
36 |
37 | echo -e "---\napiVersion: imgpkg.carvel.dev/v1alpha1\nkind: ImagesLock" > ./.imgpkg/images.yml
38 |
39 | export IMGPKG_ENABLE_IAAS_AUTH=false
40 | imgpkg push -b $(params.bundle) -f .
41 | cat ./.imgpkg/images.yml
42 | securityContext:
43 | runAsUser: 0
--------------------------------------------------------------------------------
/image-prebuilt/supply-chain/writer/template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterTemplate
5 | metadata:
6 | name: image-writer
7 | spec:
8 | params:
9 | - name: registry_server
10 | default: ""
11 | - name: registry_repository
12 | default: ""
13 |
14 | ytt: |
15 | #@ load("@ytt:data", "data")
16 | #@ load("@ytt:json", "json")
17 | #@ load("@ytt:base64", "base64")
18 |
19 | #@ def image_bundle():
20 | #@ return "/".join([
21 | #@ data.values.params.registry_server,
22 | #@ data.values.params.registry_repository,
23 | #@ "-".join([
24 | #@ data.values.workload.metadata.name,
25 | #@ data.values.workload.metadata.namespace,
26 | #@ "bundle",
27 | #@ ])
28 | #@ ]) + ":" + data.values.workload.metadata.uid
29 | #@ end
30 |
31 | ---
32 | apiVersion: carto.run/v1alpha1
33 | kind: Runnable
34 | metadata:
35 | name: #@ data.values.workload.metadata.name + "-config-writer"
36 | spec:
37 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
38 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
39 |
40 | runTemplateRef:
41 | name: tekton-taskrun-tpl
42 |
43 | inputs:
44 | serviceAccount: #@ data.values.workload.spec.serviceAccountName
45 | taskRef:
46 | kind: ClusterTask
47 | name: image-writer-task
48 | params:
49 | - name: files
50 | value: #@ base64.encode(json.encode(data.values.config))
51 | - name: bundle
52 | value: #@ image_bundle()
--------------------------------------------------------------------------------
/image-prebuilt/workload-imageprebuilt.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: Workload
5 | metadata:
6 | name: image-prebuilt
7 | namespace: default
8 | labels:
9 | app.kubernetes.io/part-of: image-prebuilt
10 | workload-intent: image-prebuilt
11 | spec:
12 | serviceAccountName: #@ data.values.service_account_name
13 | params:
14 | - name: registry_server
15 | value: harbor-repo.vmware.com
16 | - name: registry_repository
17 | value: tapsme/cartographer
18 | source:
19 | image: harbor-repo.vmware.com/tapsme/special-spring-boot-app:0.0.2
--------------------------------------------------------------------------------
/multi-cluster/README.md:
--------------------------------------------------------------------------------
1 | ## Run the multi-cluster use case
2 |
3 | ## Assumption
4 | Purposeful TAP clusters (multi-cluster) are setup. At a minimum 2 distinct TAP clusters are involved - build (to turn source code into cloud native image) and run (to deploy).
5 |
6 |
7 | ## Rationale
8 | This is an enhancement on top of the out of the box supply chain provided with TAP to realize a cartographer deliverable produced from a TAP build cluster onto a TAP run cluster. It leverages the custom resource App (kappctrl.k14s.io/v1alpha1) to target the appropriate run cluster where deliverables read from git repositories will be applied.
9 |
10 | ## Installation:
11 | **The installation steps are to be run in your TAP cluster where you submit a workload (e.g. build cluster).**
12 |
13 | 1. Follow the instructions for making [Live modification of supply chains and templates](https://docs.vmware.com/en/Tanzu-Application-Platform/1.1/tap/GUID-scc-authoring-supply-chains.html#live-modification-of-supply-chains-and-templates-6).
14 |
15 | Below are the actual steps taken:
16 | - pause reconciliation of tap meta package
17 | ```
18 | kubectl patch packageinstall/tap -n tap-install -p '{"spec":{"paused":true}}' --type=merge
19 | ```
20 | - pause reconciliation of the supply chain applied in your cluster (this example uses basic)
21 | ```
22 | kubectl patch packageinstall/ootb-supply-chain-basic -n tap-install -p '{"spec":{"paused":true}}' --type=merge
23 | ```
24 |
25 | > assumes current working directory is `repo-root/multi-cluster`
26 |
27 | 3. Apply the templates (`kubectl apply -f .`) under supply-chain/deliverable-config and supply-chain/deliverable-config -writer. If you prefer to use kapp run `kapp deploy -a custom-templates -f .`
28 |
29 | 4. Update the ClusterSupplyChain. This example uses the basic supply cgain.
30 | ```
31 | kubectl replace -f source-to-url.yml --replace
32 | ```
33 |
34 | **The step below is OPTIONAL and should be applied in your TAP cluster where you run workload(s) (e.g. run cluster).**
35 |
36 | 5. (Optional) Apply the templates (`kubectl apply -f .`) under supply-chain/rbac in your target run cluster. This leverages the default service account in the default namespace and is given ClusterRole permission to manage deliverables regardless of the namespace. This is done for convenience. You are free to configure your own service account and provide fine grained permissions following least privilege access.
37 |
38 | ## Notes:
39 |
40 | - The secret specified in App.spec.cluster.kubeconfigSecretRef holds kubeconfig info of a target run cluster. This enables
41 | cross-cluster communication.
42 |
43 | Sample kube-config.yml template using a service account from your target run cluster-namespace.
44 | ```
45 | apiVersion: v1
46 | kind: Config
47 | clusters:
48 | - cluster:
49 | certificate-authority-data: ${ca}
50 | server: ${server}
51 | name: ${clusterName}
52 | contexts:
53 | - context:
54 | cluster: ${clusterName}
55 | user: ${serviceAccount}
56 | name: ${serviceAccount}@${clusterName}
57 | current-context: ${serviceAccount}@${clusterName}
58 | users:
59 | - name: ${serviceAccount}
60 | user:
61 | token: ${token}
62 | ```
63 |
64 | Sample command to create kubeconfig as a secret. **Note that this secret should be created in your TAP cluster where you submit a workload (e.g. build cluster)**. Expect future enhancements on this.
65 | ```
66 | kubectl -n default create secret generic kubeconfig-deliverable-reconciler-secret --from-file=value=./kubeconfig.yml
67 | ```
--------------------------------------------------------------------------------
/multi-cluster/deliverable-to-run-cluster-reconciler.yml:
--------------------------------------------------------------------------------
1 | apiVersion: kappctrl.k14s.io/v1alpha1
2 | kind: App
3 | metadata:
4 | name: deliverable-to-run-cluster-reconciler
5 | spec:
6 | fetch:
7 | - git:
8 | url: https://github.com/Mpluya/unicorn-run-qa-deliverable
9 | ref: origin/main
10 | syncPeriod: 1m0s
11 | cluster:
12 | # specifies namespace in destination cluster (optional)
13 | namespace: default
14 | # specifies secret containing kubeconfig (required)
15 | kubeconfigSecretRef:
16 | # specifies secret name within app's namespace (required)
17 | name: kubeconfig-deliverable-reconciler-secret
18 | # specifies key that contains kubeconfig (optional)
19 | key: value
20 | deploy:
21 | - kapp:
22 | rawOptions: ["--dangerous-allow-empty-list-of-resources=true"]
23 | template:
24 | - ytt: {}
25 | - kbld: {}
--------------------------------------------------------------------------------
/multi-cluster/rbac/deliverable-cluster-role-binding.yml:
--------------------------------------------------------------------------------
1 | apiVersion: rbac.authorization.k8s.io/v1
2 | kind: ClusterRoleBinding
3 | metadata:
4 | name: deliverable-reconciler
5 | roleRef:
6 | apiGroup: rbac.authorization.k8s.io
7 | kind: ClusterRole
8 | name: deliverable-reconciler
9 | subjects:
10 | - kind: ServiceAccount
11 | name: default
12 | namespace: default
--------------------------------------------------------------------------------
/multi-cluster/rbac/deliverable-cluster-role.yml:
--------------------------------------------------------------------------------
1 | apiVersion: rbac.authorization.k8s.io/v1
2 | kind: ClusterRole
3 | metadata:
4 | name: deliverable-reconciler
5 | rules:
6 | - apiGroups:
7 | - carto.run
8 | resources:
9 | - deliverables
10 | verbs:
11 | - "*"
--------------------------------------------------------------------------------
/multi-cluster/supply-chain/deliverable-config-writer/cluster-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterTemplate
3 | metadata:
4 | labels:
5 | name: config-writer-deliverable-template
6 | spec:
7 | params:
8 | - default: default
9 | name: serviceAccount
10 | ytt: |
11 | #@ load("@ytt:data", "data")
12 | #@ load("@ytt:json", "json")
13 | #@ load("@ytt:base64", "base64")
14 |
15 | #@ def param(key):
16 | #@ if not key in data.values.params:
17 | #@ return None
18 | #@ end
19 | #@ return data.values.params[key]
20 | #@ end
21 |
22 |
23 | ---
24 | apiVersion: carto.run/v1alpha1
25 | kind: Runnable
26 | metadata:
27 | name: #@ data.values.workload.metadata.name + "-deliverable-config-writer"
28 | labels:
29 | app.kubernetes.io/component: config-writer
30 | #@ if/end hasattr(data.values.workload.metadata, "labels") and hasattr(data.values.workload.metadata.labels, "app.kubernetes.io/part-of"):
31 | app.kubernetes.io/part-of: #@ data.values.workload.metadata.labels["app.kubernetes.io/part-of"]
32 | spec:
33 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
34 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
35 |
36 | runTemplateRef:
37 | name: tekton-taskrun
38 |
39 | inputs:
40 | serviceAccount: #@ data.values.params.serviceAccount
41 | taskRef:
42 | kind: ClusterTask
43 | name: #@ "git-writer"
44 | params:
45 | - name: git_repository
46 | value: #@ param("deliverable_repository")
47 | - name: git_branch
48 | value: #@ param("deliverable_branch")
49 | - name: git_user_name
50 | value: #@ param("gitops_user_name")
51 | - name: git_user_email
52 | value: #@ param("gitops_user_email")
53 | - name: git_commit_message
54 | value: #@ param("gitops_commit_message")
55 | - name: git_files
56 | value: #@ base64.encode(json.encode(data.values.config))
--------------------------------------------------------------------------------
/multi-cluster/supply-chain/deliverable-config/config-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterConfigTemplate
3 | metadata:
4 | name: config-deliverable-template
5 | spec:
6 | configPath: .data
7 | ytt: |
8 | #@ load("@ytt:data", "data")
9 | #@ load("@ytt:yaml", "yaml")
10 |
11 | #@ def has_git_params():
12 | #@ if 'gitops_repository_prefix' in data.values.params:
13 | #@ return True
14 | #@ end
15 | #@
16 | #@ if 'gitops_repository' in data.values.params:
17 | #@ return True
18 | #@ end
19 | #@
20 | #@ return False
21 | #@ end
22 |
23 | #@ def is_gitops():
24 | #@ return has_git_params()
25 | #@ end
26 |
27 | #@ def param(key):
28 | #@ if not key in data.values.params:
29 | #@ return None
30 | #@ end
31 | #@ return data.values.params[key]
32 | #@ end
33 |
34 | #@ def git_repository():
35 | #@ if 'gitops_repository' in data.values.params:
36 | #@ return param("gitops_repository")
37 | #@ end
38 | #@
39 | #@ prefix = param("gitops_repository_prefix")
40 | #@ return prefix + data.values.workload.metadata.name + ".git"
41 | #@ end
42 |
43 | #@ def merge_labels(fixed_values):
44 | #@ labels = {}
45 | #@ if hasattr(data.values.workload.metadata, "labels"):
46 | #@ labels.update(data.values.workload.metadata.labels)
47 | #@ end
48 | #@ labels.update(fixed_values)
49 | #@ return labels
50 | #@ end
51 |
52 | #@ def deliverable():
53 | apiVersion: carto.run/v1alpha1
54 | kind: Deliverable
55 | metadata:
56 | name: #@ data.values.workload.metadata.name
57 | namespace: #@ data.values.workload.metadata.namespace
58 | labels: #@ merge_labels({ "app.kubernetes.io/component": "deliverable", "app.tanzu.vmware.com/deliverable-type": "web" })
59 | spec:
60 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
61 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
62 |
63 | params:
64 | - name: "gitops_ssh_secret"
65 | value: #@ param("gitops_ssh_secret")
66 |
67 | source:
68 | git:
69 | url: #@ git_repository()
70 | ref:
71 | branch: #@ param("gitops_branch")
72 |
73 | #@ end
74 |
75 | ---
76 | apiVersion: v1
77 | kind: ConfigMap
78 | metadata:
79 | name: #@ data.values.workload.metadata.name + "-deliverable"
80 | labels: #@ merge_labels({ "app.kubernetes.io/component": "config" })
81 | data:
82 | #@yaml/text-templated-strings
83 | (@= data.values.workload.metadata.name @)-deliverable.yml: #@ yaml.encode(deliverable())
--------------------------------------------------------------------------------
/multi-cluster/supply-chain/source-to-url.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSupplyChain
3 | metadata:
4 | name: source-to-url
5 | spec:
6 | params:
7 | - name: deliverable_repository
8 | default: ssh://git@github.com/Mpluya/unicorn-run-qa-deliverable.git
9 | - name: deliverable_branch
10 | default: main
11 | - default: main
12 | name: gitops_branch
13 | - default: supplychain
14 | name: gitops_user_name
15 | - default: supplychain
16 | name: gitops_user_email
17 | - default: supplychain@cluster.local
18 | name: gitops_commit_message
19 | - default: ""
20 | name: gitops_ssh_secret
21 | resources:
22 | - name: source-provider
23 | params:
24 | - name: serviceAccount
25 | value: default
26 | - name: gitImplementation
27 | value: go-git
28 | templateRef:
29 | kind: ClusterSourceTemplate
30 | name: source-template
31 | - name: image-builder
32 | params:
33 | - name: serviceAccount
34 | value: default
35 | - name: clusterBuilder
36 | value: default
37 | - name: registry
38 | value:
39 | repository: tapsme
40 | server: index.docker.io
41 | sources:
42 | - name: source
43 | resource: source-provider
44 | templateRef:
45 | kind: ClusterImageTemplate
46 | name: kpack-template
47 | - images:
48 | - name: image
49 | resource: image-builder
50 | name: config-provider
51 | params:
52 | - name: serviceAccount
53 | value: default
54 | templateRef:
55 | kind: ClusterConfigTemplate
56 | name: convention-template
57 | - configs:
58 | - name: config
59 | resource: config-provider
60 | name: app-config
61 | templateRef:
62 | kind: ClusterConfigTemplate
63 | name: config-template
64 | - configs:
65 | - name: config
66 | resource: app-config
67 | name: app-config-writer
68 | params:
69 | - name: serviceAccount
70 | value: default
71 | - name: registry
72 | value:
73 | repository: tapsme
74 | server: index.docker.io
75 | templateRef:
76 | kind: ClusterTemplate
77 | name: config-writer-template
78 |
79 | - configs:
80 | name: deliverable-config
81 | templateRef:
82 | kind: ClusterConfigTemplate
83 | name: config-deliverable-template
84 |
85 | - name: deliverable-config-writer
86 | configs:
87 | - name: config
88 | resource: deliverable-config
89 | params:
90 | - name: serviceAccount
91 | value: default
92 | templateRef:
93 | kind: ClusterTemplate
94 | name: config-writer-deliverable-template
95 |
96 |
97 | selector:
98 | apps.tanzu.vmware.com/workload-type: web
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/README.md:
--------------------------------------------------------------------------------
1 |
2 | `kapp deploy -a multi-language-support-with-sonar -f multi-language-support-with-sonar`
3 |
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/clusterdelivery/deliverable-config-writer/commit-and-pr-task.yaml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | ---
4 | apiVersion: tekton.dev/v1beta1
5 | kind: ClusterTask
6 | metadata:
7 | name: commit-and-pr
8 | spec:
9 | description: |-
10 | A task that writes a given set of files (provided as a json base64-encoded)
11 | to a git repository under a specified path. A pull request is then opened
12 | to merge the changes into the specified base branch.
13 | params:
14 | - name: repository_owner
15 | description: The owner of the repository, either an organisation or username
16 | type: string
17 | - name: repository_name
18 | description: The name of the repository
19 | type: string
20 | - name: commit_branch
21 | type: string
22 | description: The name of the branch where desired changes are implemented
23 | - name: git_user_email
24 | description: User email address
25 | type: string
26 | default: "example@example.com"
27 | - name: git_user_name
28 | description: User name
29 | type: string
30 | default: "Example"
31 | - name: git_commit_message
32 | description: Message for the git commit
33 | type: string
34 | default: "New Commit"
35 | - name: git_files
36 | type: string
37 | description: >
38 | Base64-encoded json map of files to write to registry, for example -
39 | eyAiUkVBRE1FLm1kIjogIiMgUmVhZG1lIiB9
40 | - name: git_server_address
41 | type: string
42 | description: The git server location
43 | default: https://github.com
44 | - name: git_server_kind
45 | type: string
46 | description: The git server kind (e.g. github, gitlab, gitea, etc)
47 | default: github
48 | - name: pull_request_title
49 | type: string
50 | description: The title of the pull request
51 | - name: pull_request_body
52 | type: string
53 | description: The message body of the pull request
54 | default: ""
55 | - name: base_branch
56 | type: string
57 | description: The name of the branch the desired changes should be pulled in to
58 | default: main
59 | - name: sub_path
60 | description: Sub directory in which to write
61 | type: string
62 | default: "config"
63 | results:
64 | - name: pr-url
65 | description: The url of the successfully created pull request
66 | workspaces:
67 | - name: ws
68 | mountPath: /workspaces/ws
69 | steps:
70 | - name: git-clone-and-push
71 | image: tapsme/config-writer
72 | securityContext:
73 | runAsUser: 0
74 | workingDir: /root
75 | script: |
76 | #!/usr/bin/env bash
77 |
78 | set -o errexit
79 |
80 | commit_branch="$(params.commit_branch)"
81 | if [ -z "$commit_branch" ]; then
82 | commit_branch=$(date +%s | base64)
83 | fi
84 |
85 | set +o xtrace # Avoid leaking secrets, echo sensitive lines
86 |
87 | echo 'git_prefix=$(cat $(credentials.path)/.git-credentials)'
88 | git_prefix=$(cat $(credentials.path)/.git-credentials)
89 |
90 | echo 'git_repository="$git_prefix/$(params.repository_owner)/$(params.repository_name).git"'
91 | git_repository="$git_prefix/$(params.repository_owner)/$(params.repository_name).git"
92 |
93 | echo 'git clone --depth 1 -b "$commit_branch" "$git_repository" ./repo 2>&1 | sed "s|$git_prefix|REDACTED|g'
94 | git clone --depth 1 -b "$commit_branch" "$git_repository" ./repo 2>&1 | sed "s|$git_prefix|REDACTED|g"
95 | echo 'if [ ${PIPESTATUS[0]} -ne 0 ]; then'
96 | if [ ${PIPESTATUS[0]} -ne 0 ]; then
97 | set -o xtrace
98 | cd ./repo
99 | else
100 | echo 'git clone --depth 1 "$git_repository" ./repo 2>&1 | sed "s|$git_prefix|REDACTED|g"'
101 | git clone --depth 1 "$git_repository" ./repo 2>&1 | sed "s|$git_prefix|REDACTED|g"
102 | set -o xtrace
103 | cd ./repo
104 | git checkout -b "$commit_branch"
105 | fi
106 |
107 | git config user.email "$(params.git_user_email)"
108 | git config user.name "$(params.git_user_name)"
109 |
110 | mkdir -p $(params.sub_path) && rm -rf $(params.sub_path)/*
111 | cd $(params.sub_path)
112 |
113 | echo '$(params.git_files)' | base64 --decode > files.json
114 | eval "$(cat files.json | jq -r 'to_entries | .[] | @sh "mkdir -p $(dirname \(.key)) && echo \(.value) > \(.key) && git add \(.key)"')"
115 |
116 | git commit -m "$(params.git_commit_message)"
117 | git push origin $commit_branch
118 |
119 | echo "$commit_branch" > /workspaces/ws/commit_branch
120 |
121 | - name: ensure-base-branch-exists
122 | image: tapsme/config-writer
123 | securityContext:
124 | runAsUser: 0
125 | workingDir: /root
126 | script: |
127 | #!/usr/bin/env bash
128 |
129 | set -o errexit
130 | set -o pipefail
131 |
132 | set +o xtrace # Avoid leaking secrets, echo sensitive lines
133 |
134 | echo 'git_prefix=$(cat $(credentials.path)/.git-credentials)'
135 | git_prefix=$(cat $(credentials.path)/.git-credentials)
136 |
137 | echo 'git_repository="$git_prefix/$(params.repository_owner)/$(params.repository_name).git"'
138 | git_repository="$git_prefix/$(params.repository_owner)/$(params.repository_name).git"
139 |
140 | echo 'git clone --depth 1 -b "$commit_branch" "$git_repository" ./repo 2>&1 | sed "s|$git_prefix|REDACTED|g'
141 | git clone --depth 1 "$git_repository" ./repo 2>&1 | sed "s|$git_prefix|REDACTED|g"
142 |
143 | set -o xtrace
144 | cd ./repo
145 |
146 | if git show-ref --verify --quiet "refs/heads/$(params.base_branch)"; then
147 | echo "branch exists"
148 | else
149 | git checkout --orphan "$(params.base_branch)"
150 | git rm --cached . -r || true
151 | git config user.email "$(params.git_user_email)"
152 | git config user.name "$(params.git_user_name)"
153 | git commit -m "Initialize branch" --allow-empty
154 | git push origin $(params.base_branch)
155 | fi
156 |
157 | - name: open-pr
158 | image: tapsme/jx-scm
159 | script: |
160 | #!/usr/bin/env bash
161 |
162 | set -o errexit
163 | set -o pipefail
164 |
165 | head_branch=$(cat /workspaces/ws/commit_branch | tr -d '\n')
166 |
167 | token=$(cat $(credentials.path)/.git-credentials | sed -e 's/https:.*://' | sed -e 's/@.*//')
168 | echo $token
169 | jx-scm pull-request create \
170 | --kind "$(params.git_server_kind)" \
171 | --server "$(params.git_server_address)" \
172 | --username "$(params.git_user_name)" \
173 | --token "$token" \
174 | --owner "$(params.repository_owner)" \
175 | --name "$(params.repository_name)" \
176 | --head "$head_branch" \
177 | --title "$(params.pull_request_title)" \
178 | --body "$(params.pull_request_body)" \
179 | --base "$(params.base_branch)" \
180 | --allow-update 2>&1 |
181 | tee stdoutAndSterr.txt
182 |
183 | cat stdoutAndSterr.txt | sed -n -e 's/^.*\. url: //p' > $(results.pr-url.path)
184 |
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/clusterdelivery/deliverable-config-writer/commit-and-pr-taskrun-runtemplate.yaml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | ---
4 | apiVersion: carto.run/v1alpha1
5 | kind: ClusterRunTemplate
6 | metadata:
7 | name: commit-and-pr-pipelinerun-prod
8 | spec:
9 | outputs:
10 | pr-url: status.taskResults[?(@.name=="pr-url")].value
11 | template:
12 | apiVersion: tekton.dev/v1beta1
13 | kind: TaskRun
14 | metadata:
15 | generateName: $(runnable.metadata.name)$-commit-and-pr-
16 | labels: $(runnable.metadata.labels)$
17 | spec:
18 | serviceAccountName: $(runnable.spec.inputs.serviceAccount)$
19 | taskRef:
20 | name: commit-and-pr
21 | kind: ClusterTask
22 | workspaces:
23 | - name: ws
24 | emptyDir: { }
25 | params:
26 | - name: git_server_kind
27 | value: $(runnable.spec.inputs.git_server_kind)$
28 | - name: git_server_address
29 | value: $(runnable.spec.inputs.git_server_address)$
30 | - name: repository_owner
31 | value: $(runnable.spec.inputs.repository_owner)$
32 | - name: repository_name
33 | value: $(runnable.spec.inputs.repository_name)$
34 | - name: commit_branch
35 | value: $(runnable.spec.inputs.commit_branch)$
36 | - name: pull_request_title
37 | value: $(runnable.spec.inputs.pull_request_title)$
38 | - name: pull_request_body
39 | value: $(runnable.spec.inputs.pull_request_body)$
40 | - name: base_branch
41 | value: $(runnable.spec.inputs.base_branch)$
42 | - name: git_user_name
43 | value: $(runnable.spec.inputs.git_user_name)$
44 | - name: git_user_email
45 | value: $(runnable.spec.inputs.git_user_email)$
46 | - name: git_commit_message
47 | value: $(runnable.spec.inputs.git_commit_message)$
48 | - name: git_files
49 | value: $(runnable.spec.inputs.git_files)$
50 | - name: sub_path
51 | value: $(runnable.spec.inputs.sub_path)$
52 |
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/clusterdelivery/deliverable-config-writer/config-writer-and-pull-requester-template.yaml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | ---
4 | apiVersion: carto.run/v1alpha1
5 | kind: ClusterTemplate
6 | metadata:
7 | name: deliverable-config-writer-and-pr-template
8 | spec:
9 | ytt: |
10 | #@ load("@ytt:data", "data")
11 | #@ load("@ytt:json", "json")
12 | #@ load("@ytt:base64", "base64")
13 |
14 | #@ def merge_labels(fixed_values):
15 | #@ labels = {}
16 | #@ if hasattr(data.values.deliverable.metadata, "labels"):
17 | #@ labels.update(data.values.deliverable.metadata.labels)
18 | #@ end
19 | #@ labels.update(fixed_values)
20 | #@ return labels
21 | #@ end
22 |
23 | ---
24 | apiVersion: carto.run/v1alpha1
25 | kind: Runnable
26 | metadata:
27 | name: #@ data.values.deliverable.metadata.name + "-config-writer-pull-requester"
28 | labels: #@ merge_labels({ "app.kubernetes.io/component": "config-writer-pull-requester" })
29 | spec:
30 | #@ if/end hasattr(data.values.deliverable.spec, "serviceAccountName"):
31 | serviceAccountName: #@ data.values.deliverable.spec.serviceAccountName
32 |
33 | runTemplateRef:
34 | name: commit-and-pr-pipelinerun
35 |
36 | inputs:
37 | serviceAccount: #@ data.values.params.serviceAccount
38 | git_server_kind: "github"
39 | git_server_address: "https://github.com"
40 | commit_branch: ""
41 | pull_request_title: #@ "ready for review, delivery revision: " + data.values.source.revision
42 | pull_request_body: "generated by supply chain"
43 | repository_owner: #@ data.values.params.deliverable_repository_owner
44 | repository_name: #@ data.values.params.deliverable_repository_name
45 | base_branch: "main"
46 | git_user_name: "supplychain"
47 | git_user_email: "supplychain@cluster.local"
48 | git_commit_message: "supply chain promoted workload"
49 | git_files: #@ base64.encode(json.encode(data.values.config))
50 | sub_path: #@ "config/" + data.values.deliverable.metadata.namespace + "/" + data.values.deliverable.metadata.name
51 |
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/clusterdelivery/deliverable-config/config-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterConfigTemplate
3 | metadata:
4 | name: config-deliverable-template
5 | spec:
6 | configPath: .data
7 | ytt: |
8 | #@ load("@ytt:data", "data")
9 | #@ load("@ytt:yaml", "yaml")
10 |
11 | #@ def has_git_params():
12 | #@ if 'gitops_repository_prefix' in data.values.params:
13 | #@ return True
14 | #@ end
15 | #@
16 | #@ if 'gitops_repository' in data.values.params:
17 | #@ return True
18 | #@ end
19 | #@
20 | #@ return False
21 | #@ end
22 |
23 | #@ def is_gitops():
24 | #@ return has_git_params()
25 | #@ end
26 |
27 | #@ def param(key):
28 | #@ if not key in data.values.params:
29 | #@ return None
30 | #@ end
31 | #@ return data.values.params[key]
32 | #@ end
33 |
34 | #@ def strip_trailing_slash(some_string):
35 | #@ if some_string[-1] == "/":
36 | #@ return some_string[:-1]
37 | #@ end
38 | #@ return some_string
39 | #@ end
40 |
41 | #@ def deliverable():
42 | apiVersion: carto.run/v1alpha1
43 | kind: Deliverable
44 | metadata:
45 | name: #@ data.values.deliverable.metadata.name
46 | namespace: #@ data.values.deliverable.metadata.namespace
47 | labels:
48 | app.kubernetes.io/component: deliverable
49 | app.tanzu.vmware.com/deliverable-type: web
50 | app.tanzu.vmware.com/delivery-commit-sha: #@ data.values.source.revision
51 | spec:
52 | #@ if/end hasattr(data.values.deliverable.spec, "serviceAccountName"):
53 | serviceAccountName: #@ data.values.deliverable.spec.serviceAccountName
54 |
55 | params:
56 | - name: "gitops_ssh_secret"
57 | value: #@ param("gitops_ssh_secret")
58 | - name: "gitops_sub_path"
59 | value: #@ "config/" + data.values.deliverable.metadata.namespace + "/" + data.values.deliverable.metadata.name
60 |
61 | source:
62 | git:
63 | url: #@ data.values.deliverable.spec.source.git.url
64 | ref:
65 | branch: main
66 | #@ end
67 |
68 | ---
69 | apiVersion: v1
70 | kind: ConfigMap
71 | metadata:
72 | name: #@ data.values.deliverable.metadata.name + "-deliverable"
73 | labels:
74 | app.kubernetes.io/component: config
75 | data:
76 | #@yaml/text-templated-strings
77 | (@= data.values.deliverable.metadata.name @)-(@= data.values.deliverable.metadata.namespace @)-deliverable.yml: #@ yaml.encode(deliverable())
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/clusterdelivery/delivery.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterDelivery
5 | metadata:
6 | name: delivery-with-code-promotion
7 | spec:
8 | params:
9 | - name: deliverable_repository_owner
10 | default: Mpluya
11 | - name: deliverable_repository_name
12 | default: config-deliverable-prod
13 | selector:
14 | app.tanzu.vmware.com/deliverable-type: web
15 | deliverable-intent: code-promotion
16 | resources:
17 | - name: source-provider
18 | templateRef:
19 | kind: ClusterSourceTemplate
20 | name: delivery-source-template
21 | params:
22 | - name: serviceAccount
23 | value: default
24 | - name: gitImplementation
25 | value: go-git
26 |
27 | - name: deployer
28 | templateRef:
29 | kind: ClusterDeploymentTemplate
30 | name: app-deploy
31 | params:
32 | - name: serviceAccount
33 | value: default
34 | deployment:
35 | resource: source-provider
36 |
37 | - configs:
38 | name: prod-deliverable-config
39 | sources:
40 | - name: source
41 | resource: source-provider
42 | templateRef:
43 | kind: ClusterConfigTemplate
44 | name: config-deliverable-template
45 |
46 | - name: prod-deliverable-config-writer-and-pr
47 | configs:
48 | - name: config
49 | resource: prod-deliverable-config
50 | sources:
51 | - name: source
52 | resource: source-provider
53 | params:
54 | - name: serviceAccount
55 | value: default
56 | templateRef:
57 | kind: ClusterTemplate
58 | name: deliverable-config-writer-and-pr-template
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/deliverable-config-writer/cluster-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterTemplate
3 | metadata:
4 | labels:
5 | name: config-writer-deliverable-template
6 | spec:
7 | params:
8 | - default: default
9 | name: serviceAccount
10 | ytt: |
11 | #@ load("@ytt:data", "data")
12 | #@ load("@ytt:json", "json")
13 | #@ load("@ytt:base64", "base64")
14 | #@ load("@ytt:assert", "assert")
15 |
16 | #@ def merge_labels(fixed_values):
17 | #@ labels = {}
18 | #@ if hasattr(data.values.workload.metadata, "labels"):
19 | #@ labels.update(data.values.workload.metadata.labels)
20 | #@ end
21 | #@ labels.update(fixed_values)
22 | #@ return labels
23 | #@ end
24 |
25 | #@ def is_monorepo_approach():
26 | #@ if 'gitops_server_address' in data.values.params and 'gitops_repository_owner' in data.values.params and 'gitops_repository_name' in data.values.params:
27 | #@ return True
28 | #@ end
29 | #@ if 'gitops_server_address' in data.values.params or 'gitops_repository_owner' in data.values.params or 'gitops_repository_name' in data.values.params:
30 | #@ 'gitops_server_address' in data.values.params or assert.fail("missing param: gitops_server_address")
31 | #@ 'gitops_repository_owner' in data.values.params or assert.fail("missing param: gitops_repository_owner")
32 | #@ 'gitops_repository_name' in data.values.params or assert.fail("missing param: gitops_repository_name")
33 | #@ end
34 | #@ return False
35 | #@ end
36 |
37 | #@ def has_git_params():
38 | #@ if 'gitops_repository_prefix' in data.values.params:
39 | #@ return True
40 | #@ end
41 | #@
42 | #@ if 'gitops_repository' in data.values.params:
43 | #@ return True
44 | #@ end
45 | #@
46 | #@ return False
47 | #@ end
48 |
49 | #@ def is_gitops():
50 | #@ return is_monorepo_approach() or has_git_params()
51 | #@ end
52 |
53 | #@ def param(key):
54 | #@ if not key in data.values.params:
55 | #@ return None
56 | #@ end
57 | #@ return data.values.params[key]
58 | #@ end
59 |
60 | #@ def strip_trailing_slash(some_string):
61 | #@ if some_string[-1] == "/":
62 | #@ return some_string[:-1]
63 | #@ end
64 | #@ return some_string
65 | #@ end
66 |
67 | #@ def mono_repository():
68 | #@ strip_trailing_slash(data.values.params.gitops_server_address)
69 | #@ return "/".join([
70 | #@ strip_trailing_slash(data.values.params.gitops_server_address),
71 | #@ strip_trailing_slash(data.values.params.gitops_repository_owner),
72 | #@ data.values.params.gitops_repository_name,
73 | #@ ]) + ".git"
74 | #@ end
75 |
76 | #@ def git_repository():
77 | #@ if is_monorepo_approach():
78 | #@ return mono_repository()
79 | #@ end
80 | #@
81 | #@ if 'gitops_repository' in data.values.params:
82 | #@ return param("gitops_repository")
83 | #@ end
84 | #@
85 | #@ prefix = param("gitops_repository_prefix")
86 | #@ return prefix + data.values.workload.metadata.name + ".git"
87 | #@ end
88 | ---
89 | apiVersion: carto.run/v1alpha1
90 | kind: Runnable
91 | metadata:
92 | name: #@ data.values.workload.metadata.name + "-deliverable-config-writer"
93 | labels:
94 | app.kubernetes.io/component: config-writer
95 | #@ if/end hasattr(data.values.workload.metadata, "labels") and hasattr(data.values.workload.metadata.labels, "app.kubernetes.io/part-of"):
96 | app.kubernetes.io/part-of: #@ data.values.workload.metadata.labels["app.kubernetes.io/part-of"]
97 | spec:
98 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
99 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
100 |
101 | runTemplateRef:
102 | name: tekton-taskrun
103 |
104 | inputs:
105 | serviceAccount: #@ data.values.params.serviceAccount
106 | taskRef:
107 | kind: ClusterTask
108 | name: #@ "git-writer"
109 | params:
110 | - name: git_repository
111 | value: #@ param("deliverable_repository")
112 | - name: git_branch
113 | value: #@ param("deliverable_branch")
114 | - name: git_user_name
115 | value: #@ param("gitops_user_name")
116 | - name: git_user_email
117 | value: #@ param("gitops_user_email")
118 | - name: git_commit_message
119 | value: #@ param("gitops_commit_message")
120 | - name: git_files
121 | value: #@ base64.encode(json.encode(data.values.config))
122 | #@ if/end is_monorepo_approach():
123 | - name: sub_path
124 | value: #@ "config/" + data.values.workload.metadata.namespace + "/" + data.values.workload.metadata.name
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/deliverable-config/config-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterConfigTemplate
3 | metadata:
4 | name: config-deliverable-template
5 | spec:
6 | configPath: .data
7 | ytt: |
8 | #@ load("@ytt:data", "data")
9 | #@ load("@ytt:yaml", "yaml")
10 |
11 | #@ def has_git_params():
12 | #@ if 'gitops_repository_prefix' in data.values.params:
13 | #@ return True
14 | #@ end
15 | #@
16 | #@ if 'gitops_repository' in data.values.params:
17 | #@ return True
18 | #@ end
19 | #@
20 | #@ return False
21 | #@ end
22 |
23 | #@ def is_gitops():
24 | #@ return has_git_params()
25 | #@ end
26 |
27 | #@ def param(key):
28 | #@ if not key in data.values.params:
29 | #@ return None
30 | #@ end
31 | #@ return data.values.params[key]
32 | #@ end
33 |
34 | #@ def strip_trailing_slash(some_string):
35 | #@ if some_string[-1] == "/":
36 | #@ return some_string[:-1]
37 | #@ end
38 | #@ return some_string
39 | #@ end
40 |
41 | #@ def git_repository():
42 | #@ strip_trailing_slash(data.values.params.gitops_server_address)
43 | #@ return "/".join([
44 | #@ strip_trailing_slash(data.values.params.gitops_server_address),
45 | #@ strip_trailing_slash(data.values.params.gitops_repository_owner),
46 | #@ data.values.params.gitops_repository_name,
47 | #@ ]) + ".git"
48 | #@ end
49 |
50 |
51 | #@ def merge_labels(fixed_values):
52 | #@ labels = {}
53 | #@ if hasattr(data.values.workload.metadata, "labels"):
54 | #@ labels.update(data.values.workload.metadata.labels)
55 | #@ end
56 | #@ labels.update(fixed_values)
57 | #@ return labels
58 | #@ end
59 |
60 | #@ def deliverable():
61 | apiVersion: carto.run/v1alpha1
62 | kind: Deliverable
63 | metadata:
64 | name: #@ data.values.workload.metadata.name
65 | namespace: #@ data.values.workload.metadata.namespace
66 | labels: #@ merge_labels({ "app.kubernetes.io/component": "deliverable", "app.tanzu.vmware.com/deliverable-type": "web", "deliverable-intent": "code-promotion" })
67 | spec:
68 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
69 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
70 |
71 | params:
72 | - name: "gitops_ssh_secret"
73 | value: #@ param("gitops_ssh_secret")
74 | - name: "gitops_sub_path"
75 | value: #@ "config/" + data.values.workload.metadata.namespace + "/" + data.values.workload.metadata.name
76 |
77 | source:
78 | git:
79 | url: #@ git_repository()
80 | ref:
81 | branch: #@ param("gitops_branch")
82 | #@ end
83 |
84 | ---
85 | apiVersion: v1
86 | kind: ConfigMap
87 | metadata:
88 | name: #@ data.values.workload.metadata.name + "-deliverable"
89 | labels: #@ merge_labels({ "app.kubernetes.io/component": "config" })
90 | data:
91 | #@yaml/text-templated-strings
92 | (@= data.values.workload.metadata.name @)-(@= data.values.workload.metadata.namespace @)-deliverable.yml: #@ yaml.encode(deliverable())
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-analyzer/run-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterRunTemplate
3 | metadata:
4 | name: tekton-sonarqube-taskrun
5 | labels:
6 | apps.tanzu.vmware.com/sonarqube: "sonarqube"
7 | spec:
8 | outputs:
9 | revision: spec.params[?(@.name=="source-revision")].value
10 | url: spec.params[?(@.name=="source-url")].value
11 |
12 |
13 | template:
14 | apiVersion: tekton.dev/v1beta1
15 | kind: TaskRun
16 | metadata:
17 | generateName: code-analysis-$(runnable.metadata.name)$-
18 | labels: $(runnable.metadata.labels)$
19 | spec:
20 | serviceAccountName: $(runnable.spec.inputs.serviceAccount)$
21 | params:
22 | - name: source-url
23 | value: $(runnable.spec.inputs.source-url)$
24 | - name: source-revision
25 | value: $(runnable.spec.inputs.source-revision)$
26 | - name: SONAR_HOST_URL
27 | value: http://sonarqube.cvsdr.tapsme.org
28 | - name: SONAR_PROJECT_KEY
29 | value: $(runnable.spec.inputs.sonar-project-key)$
30 | - name: SONAR_LOGIN
31 | value: squ_689ee47bf781dd85e7d290025fe3fd4d4ffb1c15
32 | - name: WAIT_ON_SONAR_ANALYSIS
33 | value: $(runnable.spec.inputs.wait_on_sonar_analysis)$
34 |
35 | taskRef:
36 | name: $(selected.metadata.name)$
37 |
38 | workspaces:
39 | - name: custom-maven-settings
40 | secret:
41 | secretName: maven-settings
42 | - name: maven-settings
43 | subPath: maven-repo-cache
44 | persistentVolumeClaim:
45 | claimName: supplychainpvc
46 | - name: supplychain-workspace
47 | emptyDir: {}
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-analyzer/source-template.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSourceTemplate
3 | metadata:
4 | annotations:
5 | name: sonarqube-template
6 | spec:
7 | params:
8 | - name: wait_on_sonar_analysis
9 | default: {}
10 | revisionPath: .status.outputs.revision
11 | urlPath: .status.outputs.url
12 |
13 | ytt: |
14 | #@ load("@ytt:data", "data")
15 |
16 | #@ def merge_labels(fixed_values):
17 | #@ labels = {}
18 | #@ if hasattr(data.values.workload.metadata, "labels"):
19 | #@ labels.update(data.values.workload.metadata.labels)
20 | #@ end
21 | #@ labels.update(fixed_values)
22 | #@ return labels
23 | #@ end
24 |
25 | apiVersion: carto.run/v1alpha1
26 | kind: Runnable
27 | metadata:
28 | name: #@ data.values.workload.metadata.name + "-code-analysis"
29 | labels: #@ merge_labels({ "app.kubernetes.io/component": "test" })
30 | spec:
31 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
32 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
33 |
34 | runTemplateRef:
35 | name: tekton-sonarqube-taskrun
36 | kind: ClusterRunTemplate
37 |
38 | selector:
39 | resource:
40 | apiVersion: tekton.dev/v1beta1
41 | kind: Task
42 | matchingLabels:
43 | apps.tanzu.vmware.com/sonarqube: "sonarqube"
44 | apps.tanzu.vmware.com/language: #@ data.values.workload.metadata.labels["apps.tanzu.vmware.com/language"]
45 |
46 | inputs:
47 | source-url: #@ data.values.source.url
48 | source-revision: #@ data.values.source.revision
49 |
50 | #@ if hasattr(data.values.workload.spec, "serviceAccountName"):
51 | serviceAccount: #@ data.values.workload.spec.serviceAccountName
52 | #@ else:
53 | serviceAccount: default
54 | #@ end
55 |
56 | sonar-project-key: #@ data.values.workload.metadata.name
57 | wait_on_sonar_analysis: #@ data.values.params.wait_on_sonar_analysis
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-analyzer/task-dotnet.yml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: sonarqube-scanner-dotnet
5 | namespace: default
6 | labels:
7 | apps.tanzu.vmware.com/language: "dotnet"
8 | apps.tanzu.vmware.com/sonarqube: "sonarqube"
9 | annotations:
10 | tekton.dev/pipelines.minVersion: "0.12.1"
11 | tekton.dev/categories: Security
12 | tekton.dev/tags: security
13 | tekton.dev/displayName: "sonarqube scanner"
14 | tekton.dev/platforms: "linux/amd64"
15 | spec:
16 | params:
17 | - name: SONAR_HOST_URL
18 | description: Host URL where the sonarqube server is running
19 | default: ""
20 | - name: SONAR_PROJECT_KEY
21 | description: Project's unique key
22 | default: ""
23 | - name: SONAR_LOGIN
24 | description: Auth for the project
25 | default: ""
26 | - name: source-url
27 | description: Location of the source code
28 | - name: source-revision
29 | description: i.e. git hash
30 | default: ""
31 | - name: WAIT_ON_SONAR_ANALYSIS
32 | description: toggle to wait until sonarqube analysis is complete
33 |
34 | workspaces:
35 | - name: maven-settings
36 | - name: supplychain-workspace
37 |
38 |
39 | steps:
40 | - name: pull-code
41 | image: index.docker.io/tapsme/gradle@sha256:ba5d54bc93e3d7ae95481963c4cbd171100804a4fc64baf2ebabf0329c9e1179
42 | workingDir: $(workspaces.supplychain-workspace.path)
43 | script: |
44 | #!/usr/bin/env bash
45 | set -ex
46 | wget -qO- $(params.source-url) | tar xvz
47 |
48 | - name: sonar-scan
49 | image: index.docker.io/tapsme/dotnetsonar@sha256:0122ff42df5e2121ad3100dfca309e2f9cdf06d545d6e031f3e70f332b871a18
50 | workingDir: $(workspaces.supplychain-workspace.path)
51 | script: |
52 | #!/usr/bin/env bash
53 | set -ex
54 | dotnet-sonarscanner begin /k:$(params.SONAR_PROJECT_KEY) /d:sonar.host.url=$(params.SONAR_HOST_URL) /d:sonar.login=$(params.SONAR_LOGIN)
55 | dotnet build *.sln
56 | dotnet-sonarscanner end /d:sonar.login=$(params.SONAR_LOGIN)
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-analyzer/task.yml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: sonarqube-scanner
5 | namespace: default
6 | labels:
7 | apps.tanzu.vmware.com/language: "java"
8 | apps.tanzu.vmware.com/sonarqube: "sonarqube"
9 | annotations:
10 | tekton.dev/pipelines.minVersion: "0.12.1"
11 | tekton.dev/categories: Security
12 | tekton.dev/tags: security
13 | tekton.dev/displayName: "sonarqube scanner"
14 | tekton.dev/platforms: "linux/amd64"
15 | spec:
16 | params:
17 | - name: SONAR_HOST_URL
18 | description: Host URL where the sonarqube server is running
19 | default: ""
20 | - name: SONAR_PROJECT_KEY
21 | description: Project's unique key
22 | default: ""
23 | - name: SONAR_LOGIN
24 | description: Auth for the project
25 | default: ""
26 | - name: source-url
27 | description: Location of the source code
28 | - name: source-revision
29 | description: i.e. git hash
30 | default: ""
31 | - name: WAIT_ON_SONAR_ANALYSIS
32 | description: toggle to wait until sonarqube analysis is complete
33 |
34 | workspaces:
35 | - name: custom-maven-settings
36 | - name: maven-settings
37 | - name: supplychain-workspace
38 |
39 | steps:
40 | - name: compile
41 | image: index.docker.io/tapsme/gradle@sha256:ba5d54bc93e3d7ae95481963c4cbd171100804a4fc64baf2ebabf0329c9e1179
42 | workingDir: $(workspaces.supplychain-workspace.path)
43 | script: |
44 | #!/usr/bin/env bash
45 | set -ex
46 | wget -qO- $(params.source-url) | tar xvz
47 | ./mvnw compile -Dmaven.repo.local=$(workspaces.maven-settings.path) -s $(workspaces.custom-maven-settings.path)/settings.xml
48 | - name: sonar-properties-create
49 | image: index.docker.io/tapsme/gradle@sha256:ba5d54bc93e3d7ae95481963c4cbd171100804a4fc64baf2ebabf0329c9e1179
50 | workingDir: $(workspaces.supplychain-workspace.path)
51 | script: |
52 | #!/usr/bin/env bash
53 | replaceValues() {
54 | filename=$1
55 | thekey=$2
56 | newvalue=$3
57 | if ! grep -R "^[#]*\s*${thekey}=.*" $filename >/dev/null; then
58 | echo "APPENDING because '${thekey}' not found"
59 | echo "" >>$filename
60 | echo "$thekey=$newvalue" >>$filename
61 | else
62 | echo "SETTING because '${thekey}' found already"
63 | sed -ir "s|^[#]*\s*${thekey}=.*|$thekey=$newvalue|" $filename
64 | fi
65 | }
66 |
67 | # If we were given a properties file, then use that.
68 | if [[ -f $(workspaces.supplychain-workspace.path)/sonar-project.properties ]]; then
69 | echo "using user provided sonar-project.properties file"
70 | cp -RL $(workspaces.supplychain-workspace.path)/sonar-project.properties $(workspaces.supplychain-workspace.path)/sonar-project.properties
71 | fi
72 | if [[ -f $(workspaces.supplychain-workspace.path)/sonar-project.properties ]]; then
73 |
74 | # Allow overrides from parameters passed in from the supply chain.
75 | if [[ -n "$(params.SONAR_HOST_URL)" ]]; then
76 | replaceValues $(workspaces.supplychain-workspace.path)/sonar-project.properties sonar.host.url $(params.SONAR_HOST_URL)
77 | fi
78 | if [[ -n "$(params.SONAR_PROJECT_KEY)" ]]; then
79 | replaceValues $(workspaces.supplychain-workspace.path)/sonar-project.properties sonar.projectKey $(params.SONAR_PROJECT_KEY)
80 | fi
81 | if [[ -n "$(params.SONAR_LOGIN)" ]]; then
82 | replaceValues $(workspaces.supplychain-workspace.path)/sonar-project.properties sonar.login $(params.SONAR_LOGIN)
83 | fi
84 | else
85 | touch sonar-project.properties
86 | echo "sonar.projectKey=$(params.SONAR_PROJECT_KEY)" >> sonar-project.properties
87 | echo "sonar.host.url=$(params.SONAR_HOST_URL)" >> sonar-project.properties
88 | echo "sonar.login=$(params.SONAR_LOGIN)" >> sonar-project.properties
89 | echo "sonar.sources=." >> sonar-project.properties
90 | fi
91 | echo "---------------------------"
92 | cat $(workspaces.supplychain-workspace.path)/sonar-project.properties
93 |
94 | - name: sonar-scan
95 | image: index.docker.io/tapsme/sonar-scanner-cli@sha256:b8c95a37025f3c13162118cd55761ea0b2a13d1837f9deec51b7b6d82c52040a
96 | workingDir: $(workspaces.supplychain-workspace.path)
97 | command:
98 | - sonar-scanner
99 |
100 | - name: quality-gate
101 | image: index.docker.io/tapsme/alpine-bash-curl-jq@sha256:a5369f1e4e9d139ed6a4064686cd0ff57a75f8d1e928944c540fe753c332acfd
102 | workingDir: $(workspaces.supplychain-workspace.path)
103 | script: |
104 | #!/usr/bin/env bash
105 | if [ -z "$(params.WAIT_ON_SONAR_ANALYSIS)" ] || [ "$(params.WAIT_ON_SONAR_ANALYSIS)" == "false" ]; then
106 | echo "not waiting for analysis to finish"
107 | exit 0
108 | fi
109 |
110 | metadataFile=$(workspaces.supplychain-workspace.path)/.scannerwork/report-task.txt
111 | sonarPropsFile=$(workspaces.supplychain-workspace.path)/sonar-project.properties
112 | if [[ ! -f "$metadataFile" ]]; then
113 | echo "$metadataFile does not exist."
114 | exit 1
115 | fi
116 |
117 | cat $metadataFile
118 | serverUrl="$(sed -n 's/serverUrl=\(.*\)/\1/p' "${metadataFile}")"
119 | ceTaskUrl="$(sed -n 's/ceTaskUrl=\(.*\)/\1/p' "${metadataFile}")"
120 | sonarToken="$(sed -n 's/sonar.login=\(.*\)/\1/p' "${sonarPropsFile}")"
121 |
122 | if [ -z "${serverUrl}" ] || [ -z "${ceTaskUrl}" ]; then
123 | echo "Invalid report metadata file."
124 | exit 1
125 | fi
126 |
127 | task="$(curl --silent --fail --show-error --user "${sonarToken}": "${ceTaskUrl}")"
128 | status="$(jq -r '.task.status' <<< "$task")"
129 |
130 | until [[ ${status} != "PENDING" && ${status} != "IN_PROGRESS" ]]; do
131 | printf '.'
132 | sleep 5s
133 | task="$(curl --silent --fail --show-error --user "${sonarToken}": "${ceTaskUrl}")"
134 | status="$(jq -r '.task.status' <<< "$task")"
135 | done
136 |
137 | analysisId="$(jq -r '.task.analysisId' <<< "${task}")"
138 | echo "analysisId: " $analysisId
139 |
140 | qualityGateUrl="${serverUrl}/api/qualitygates/project_status?analysisId=${analysisId}"
141 |
142 | qualityGateStatus="$(curl --silent --fail --show-error --user "${sonarToken}": "${qualityGateUrl}" | jq -r '.projectStatus.status')"
143 |
144 | if [[ ${qualityGateStatus} == "OK" ]]; then
145 | echo "quality-gate-status::PASSED"
146 | elif [[ ${qualityGateStatus} == "WARN" ]]; then
147 | echo "quality-gate-status::WARN"
148 | elif [[ ${qualityGateStatus} == "ERROR" ]]; then
149 | echo "quality-gate-status::FAILED"
150 | exit 1
151 | else
152 | echo "quality-gate-status::FAILED"
153 | exit 1
154 | fi
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-test-analyze-scan-to-url.yml:
--------------------------------------------------------------------------------
1 | apiVersion: carto.run/v1alpha1
2 | kind: ClusterSupplyChain
3 | metadata:
4 | name: source-test-analyze-scan-to-url
5 | spec:
6 | params:
7 | - name: deliverable_repository
8 | default: ssh://git@github.com/Mpluya/polaris-run-qa-deliverable.git
9 | - name: deliverable_branch
10 | default: main
11 | - name: maven_repository_url
12 | value: https://repo.maven.apache.org/maven2
13 | - default: main
14 | name: gitops_branch
15 | - default: supplychain
16 | name: gitops_user_name
17 | - default: supplychain
18 | name: gitops_user_email
19 | - default: supplychain@cluster.local
20 | name: gitops_commit_message
21 | - default: "gitops-ssh"
22 | name: gitops_ssh_secret
23 | - default: ssh://git@github.com
24 | name: gitops_server_address
25 | - default: Mpluya
26 | name: gitops_repository_owner
27 | - default: config-polaris-demo
28 | name: gitops_repository_name
29 | - default: github
30 | name: gitops_pull_request_server_kind
31 | - default: ""
32 | name: gitops_commit_branch
33 | - default: ready for review
34 | name: gitops_pull_request_title
35 | - default: generated by supply chain
36 | name: gitops_pull_request_body
37 | resources:
38 | - name: source-provider
39 | params:
40 | - name: serviceAccount
41 | value: default
42 | - name: gitImplementation
43 | value: go-git
44 | templateRef:
45 | kind: ClusterSourceTemplate
46 | name: source-template
47 |
48 | - name: source-tester
49 | sources:
50 | - name: source
51 | resource: source-provider
52 | templateRef:
53 | kind: ClusterSourceTemplate
54 | name: testing-pipeline
55 |
56 |
57 | - name: source-scanner
58 | params:
59 | - default: scan-policy
60 | name: scanning_source_policy
61 | - default: blob-source-scan-template
62 | name: scanning_source_template
63 | sources:
64 | - name: source
65 | resource: source-tester
66 | templateRef:
67 | kind: ClusterSourceTemplate
68 | name: source-scanner-template
69 | - name: image-builder
70 | params:
71 | - name: serviceAccount
72 | value: default
73 | - name: registry
74 | value:
75 | ca_cert_data: ""
76 | repository: tapsme
77 | server: index.docker.io
78 | - default: default
79 | name: clusterBuilder
80 | - default: ./Dockerfile
81 | name: dockerfile
82 | - default: ./
83 | name: docker_build_context
84 | - default: []
85 | name: docker_build_extra_args
86 | sources:
87 | - name: source
88 | resource: source-scanner
89 | templateRef:
90 | kind: ClusterImageTemplate
91 | options:
92 | - name: kpack-template
93 | selector:
94 | matchFields:
95 | - key: spec.params[?(@.name=="dockerfile")]
96 | operator: DoesNotExist
97 | - name: kaniko-template
98 | selector:
99 | matchFields:
100 | - key: spec.params[?(@.name=="dockerfile")]
101 | operator: Exists
102 | - images:
103 | - name: image
104 | resource: image-builder
105 | name: image-scanner
106 | params:
107 | - default: snyk-scan-policy
108 | name: scanning_image_policy
109 | - default: snyk-private-image-scan-template
110 | name: scanning_image_template
111 | templateRef:
112 | kind: ClusterImageTemplate
113 | name: image-scanner-template
114 | - images:
115 | - name: image
116 | resource: image-scanner
117 | name: config-provider
118 | params:
119 | - name: serviceAccount
120 | value: default
121 | templateRef:
122 | kind: ClusterConfigTemplate
123 | name: convention-template
124 | - configs:
125 | - name: config
126 | resource: config-provider
127 | name: app-config
128 | templateRef:
129 | kind: ClusterConfigTemplate
130 | name: config-template
131 | - configs:
132 | - name: config
133 | resource: app-config
134 | name: config-writer
135 | params:
136 | - name: serviceAccount
137 | value: default
138 | - name: registry
139 | value:
140 | ca_cert_data: ""
141 | repository: tapsme
142 | server: index.docker.io
143 | templateRef:
144 | kind: ClusterTemplate
145 | name: config-writer-template
146 |
147 | - configs:
148 | name: deliverable-config
149 | templateRef:
150 | kind: ClusterConfigTemplate
151 | name: config-deliverable-template
152 |
153 | - name: deliverable-config-writer
154 | configs:
155 | - name: config
156 | resource: deliverable-config
157 | params:
158 | - name: serviceAccount
159 | value: default
160 | templateRef:
161 | kind: ClusterTemplate
162 | name: config-writer-deliverable-template
163 |
164 | selector:
165 | apps.tanzu.vmware.com/has-tests: "true"
166 | apps.tanzu.vmware.com/workload-type: web
167 | workload-intent: code-analysis
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-tester/run-template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | ---
4 | apiVersion: carto.run/v1alpha1
5 | kind: ClusterRunTemplate
6 | metadata:
7 | name: tekton-source-pipelinerun
8 | spec:
9 | outputs:
10 | url: spec.params[?(@.name=="source-url")].value
11 | revision: spec.params[?(@.name=="source-revision")].value
12 |
13 | template:
14 | apiVersion: tekton.dev/v1beta1
15 | kind: PipelineRun
16 | metadata:
17 | generateName: $(runnable.metadata.name)$-
18 | labels: $(runnable.metadata.labels)$
19 | spec:
20 | workspaces:
21 | - name: custom-maven-settings
22 | secret:
23 | secretName: maven-settings
24 | - name: maven-settings
25 | subPath: maven-repo-cache
26 | persistentVolumeClaim:
27 | claimName: supplychainpvc
28 | - name: supplychain-workspace
29 | emptyDir: {}
30 | pipelineRef:
31 | name: $(selected.metadata.name)$
32 | params:
33 | - name: source-url
34 | value: $(runnable.spec.inputs.source-url)$
35 | - name: source-revision
36 | value: $(runnable.spec.inputs.source-revision)$
37 |
--------------------------------------------------------------------------------
/multi-language-support-with-sonar/supplychain/source-tester/source-template.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | #@ if/end "testing-pipeline" not in data.values.excluded_templates:
4 | ---
5 | apiVersion: carto.run/v1alpha1
6 | kind: ClusterSourceTemplate
7 | metadata:
8 | name: testing-pipeline
9 | spec:
10 | urlPath: .status.outputs.url
11 | revisionPath: .status.outputs.revision
12 |
13 | healthRule:
14 | singleConditionType: Ready
15 |
16 | ytt: |
17 | #@ load("@ytt:data", "data")
18 | #@ load("@ytt:assert", "assert")
19 |
20 | #@ def merge_labels(fixed_values):
21 | #@ labels = {}
22 | #@ if hasattr(data.values.workload.metadata, "labels"):
23 | #@ labels.update(data.values.workload.metadata.labels)
24 | #@ end
25 | #@ labels.update(fixed_values)
26 | #@ return labels
27 | #@ end
28 |
29 | ---
30 | apiVersion: carto.run/v1alpha1
31 | kind: Runnable
32 | metadata:
33 | name: #@ data.values.workload.metadata.name
34 | labels: #@ merge_labels({ "app.kubernetes.io/component": "test" })
35 | spec:
36 | #@ if/end hasattr(data.values.workload.spec, "serviceAccountName"):
37 | serviceAccountName: #@ data.values.workload.spec.serviceAccountName
38 |
39 | runTemplateRef:
40 | name: tekton-source-pipelinerun
41 | kind: ClusterRunTemplate
42 |
43 | selector:
44 | resource:
45 | apiVersion: tekton.dev/v1beta1
46 | kind: Pipeline
47 | matchingLabels:
48 | apps.tanzu.vmware.com/pipeline: test
49 | apps.tanzu.vmware.com/language: #@ data.values.workload.metadata.labels["apps.tanzu.vmware.com/language"] or assert.fail("please add a language label on your workload, e.g. apps.tanzu.vmware.com/language: java")
50 | inputs:
51 | source-url: #@ data.values.source.url
52 | source-revision: #@ data.values.source.revision
--------------------------------------------------------------------------------
/shared/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x95castle1/custom-cartographer-supply-chain-examples/6f0778ce94efc310684215e82308c34d8cb2e127/shared/.DS_Store
--------------------------------------------------------------------------------
/shared/delivery/deploy/deployment.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: carto.run/v1alpha1
3 | kind: ClusterDeploymentTemplate
4 | metadata:
5 | name: app-deploy-tpl
6 | spec:
7 | observedCompletion:
8 | succeeded:
9 | key: '.status.conditions[?(@.type=="ReconcileSucceeded")].status'
10 | value: 'True'
11 | failed:
12 | key: '.status.conditions[?(@.type=="ReconcileSucceeded")].status'
13 | value: 'False'
14 |
15 | template:
16 | apiVersion: kappctrl.k14s.io/v1alpha1
17 | kind: App
18 | metadata:
19 | name: $(deliverable.metadata.name)$
20 | spec:
21 | serviceAccountName: $(deliverable.spec.serviceAccountName)$
22 | fetch:
23 | - http:
24 | url: $(deployment.url)$
25 | template:
26 | - ytt: {}
27 | - kbld: {}
28 | deploy:
29 | - kapp: {}
30 |
--------------------------------------------------------------------------------
/shared/git-secret.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 |
3 | ---
4 | apiVersion: v1
5 | kind: Secret
6 | metadata:
7 | name: gitops-ssh-secret
8 | data:
9 | identity: #@ data.values.git_writer.base64_encoded_ssh_key
10 | known_hosts: #@ data.values.git_writer.base64_encoded_known_hosts
--------------------------------------------------------------------------------
/shared/registry-secret.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | #@ load("@ytt:json", "json")
3 | ---
4 | apiVersion: v1
5 | kind: Secret
6 | metadata:
7 | name: tanzu-reg-cred
8 | type: kubernetes.io/dockerconfigjson
9 | stringData:
10 | #@ registry_creds = {"username": data.values.tanzu_registry.username, "password": data.values.tanzu_registry.password}
11 | .dockerconfigjson: #@ json.encode({"auths": {data.values.tanzu_registry.server: registry_creds}})
--------------------------------------------------------------------------------
/shared/secret.yml:
--------------------------------------------------------------------------------
1 | #@ load("@ytt:data", "data")
2 | #@ load("@ytt:json", "json")
3 | ---
4 | apiVersion: v1
5 | kind: Secret
6 | metadata:
7 | name: reg-cred
8 | type: kubernetes.io/dockerconfigjson
9 | stringData:
10 | #@ registry_creds = {"username": data.values.registry.username, "password": data.values.registry.password}
11 | .dockerconfigjson: #@ json.encode({"auths": {data.values.registry.server: registry_creds}})
--------------------------------------------------------------------------------
/shared/service-account.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 VMware
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | #@ load("@ytt:data", "data")
16 |
17 | #
18 | # The service-account is referenced by the workload and provides permissions for
19 | # Cartographer to create templated objects
20 | #
21 | ---
22 | apiVersion: v1
23 | kind: ServiceAccount
24 | metadata:
25 | name: #@ data.values.service_account_name
26 | #@ if data.values.registry.password != "":
27 | secrets:
28 | - name: reg-cred
29 | - name: tanzu-reg-cred
30 | imagePullSecrets:
31 | - name: reg-cred
32 | - name: tanzu-reg-cred
33 | #@ end
34 | ---
35 | apiVersion: rbac.authorization.k8s.io/v1
36 | kind: RoleBinding
37 | metadata:
38 | name: workload-role-binding
39 | roleRef:
40 | apiGroup: rbac.authorization.k8s.io
41 | kind: Role
42 | name: workload-role
43 | subjects:
44 | - kind: ServiceAccount
45 | name: #@ data.values.service_account_name
46 |
47 | ---
48 | apiVersion: rbac.authorization.k8s.io/v1
49 | kind: Role
50 | metadata:
51 | name: workload-role
52 | rules:
53 | - apiGroups:
54 | - source.toolkit.fluxcd.io
55 | - source.apps.tanzu.vmware.com
56 | - kpack.io
57 | - kapp.k14s.io/v1alpha1
58 | - kappctrl.k14s.io
59 | resources:
60 | - gitrepositories
61 | - imagerepositories
62 | - images
63 | - configs
64 | - apps
65 | verbs:
66 | - list
67 | - create
68 | - update
69 | - delete
70 | - patch
71 | - watch
72 | - get
73 | - apiGroups:
74 | - extensions
75 | - apps
76 | resources:
77 | - deployments
78 | verbs:
79 | - '*'
80 | - apiGroups:
81 | - tekton.dev
82 | resources:
83 | - tasks
84 | - taskruns
85 | - pipelineruns
86 | verbs:
87 | - '*'
88 | - apiGroups:
89 | - ''
90 | resources:
91 | - configmaps
92 | - pods
93 | verbs:
94 | - '*'
95 | - apiGroups:
96 | - carto.run
97 | resources:
98 | - runnables
99 | - deliverables
100 | verbs:
101 | - '*'
102 | - apiGroups:
103 | - scanning.apps.tanzu.vmware.com
104 | resources:
105 | - imagescans
106 | - sourcescans
107 | verbs:
108 | - '*'
109 |
--------------------------------------------------------------------------------
/shared/supply-chain/deploy/k8s/app-deploy.yml:
--------------------------------------------------------------------------------
1 |
2 | ---
3 | apiVersion: carto.run/v1alpha1
4 | kind: ClusterTemplate
5 | metadata:
6 | name: app-deploy
7 | spec:
8 | template:
9 | apiVersion: apps/v1
10 | kind: Deployment
11 | metadata:
12 | name: $(workload.metadata.name)$
13 | spec:
14 | serviceAccountName: $(workload.spec.serviceAccountName)$
15 | selector:
16 | matchLabels:
17 | app: $(workload.metadata.name)$
18 | template:
19 | metadata:
20 | labels:
21 | app: $(workload.metadata.name)$
22 | spec:
23 | containers:
24 | - name: main
25 | image: $(images.image.image)$ # consume the image that we depend
26 | # on from `kpack/Image`
--------------------------------------------------------------------------------