You can build from source by providing source code for the workload with any Supply Chain package.
You can provide source code for the workload from one of three places:
- A Git repository.
- A directory in your local computer's file system.
- A Maven repository.
Supply Chain
-- fetch source * either from Git or local directory
-- test
-- build
-- scan
-- apply-conventions
-- push config
This document provides details about each approach.
Note To provide a prebuilt container image instead of building the application from the beginning by using the supply chain, see Using an existing image.
To provide source code from a Git repository to the supply chains,
you must fill workload.spec.source.git
. With the Tanzu CLI, you can do so by using the following flags:
--git-branch
: branch within the Git repository to checkout--git-commit
: commit SHA within the Git repository to checkout--git-repo
: Git URL to remote source code--git-tag
: tag within the Git repository to checkout
For example, after installing ootb-supply-chain-basic
, to create a
Workload
the source code for which comes from the main
branch of the
github.com/vmware-tanzu/application-accelerator-samples
Git repository,
and the subdirectory tanzu-java-web-app
run:
tanzu apps workload create tanzu-java-web-app \
--app tanzu-java-web-app \
--type web \
--git-repo https://github.com/vmware-tanzu/application-accelerator-samples \
--sub-path tanzu-java-web-app \
--git-branch main
Expect to see the following output:
Create workload:
1 + |---
2 + |apiVersion: carto.run/v1alpha1
3 + |kind: Workload
4 + |metadata:
5 + | labels:
6 + | app.kubernetes.io/part-of: tanzu-java-web-app
7 + | apps.tanzu.vmware.com/workload-type: web
8 + | name: tanzu-java-web-app
9 + | namespace: default
10 + |spec:
11 + | source:
12 + | git:
13 + | ref:
14 + | branch: main
15 + | url: https://github.com/vmware-tanzu/application-accelerator-samples
16 + | subPath: tanzu-java-web-app
Important The Git repository URL must include the scheme:
http://
,https://
, orssh://
.
To fetch source code from a repository that requires credentials, you must
provide those by using a Kubernetes secret object that the GitRepository
object created for that workload references.
See How It Works
to learn more about detecting changes to the repository.
Workload/tanzu-java-web-app
└─GitRepository/tanzu-java-web-app
└───────> secretRef: {name: GIT-SECRET-NAME}
|
either a default from TAP installation or
gitops_ssh_secret Workload parameter
Platform operators who install the Out of the Box Supply Chain packages
by using Tanzu Application Platform profiles can customize the default name of
the secret (git-ssh
) by editing the corresponding ootb_supply_chain*
property in the tap-values.yaml
file:
ootb_supply_chain_basic:
gitops:
ssh_secret: GIT-SECRET-NAME
For platform operators who install the ootb-supply-chain-*
package individually
by using tanzu package install
, they can edit the
ootb-supply-chain-*-values.yml
as follows:
gitops:
ssh_secret: GIT-SECRET-NAME
You can also override the default secret name directly in the workload by using
the gitops_ssh_secret
parameter, regardless of how Tanzu Application Platform
is installed. You can use the --param
flag in Tanzu CLI. For example:
tanzu apps workload create tanzu-java-web-app \
--app tanzu-java-web-app \
--type web \
--git-repo https://github.com/vmware-tanzu/application-accelerator-samples \
--sub-path tanzu-java-web-app \
--git-branch main \
--param gitops_ssh_secret=SECRET-NAME
Expect to see the following output:
Create workload:
1 + |---
2 + |apiVersion: carto.run/v1alpha1
3 + |kind: Workload
4 + |metadata:
5 + | labels:
6 + | app.kubernetes.io/part-of: tanzu-java-web-app
7 + | apps.tanzu.vmware.com/workload-type: web
8 + | name: tanzu-java-web-app
9 + | namespace: default
10 + |spec:
11 + | params:
12 + | - name: gitops_ssh_secret #! parameter that overrides the default
13 + | value: GIT-SECRET-NAME #! secret name
14 + | source:
15 + | git:
16 + | ref:
17 + | branch: main
18 + | url: https://github.com/vmware-tanzu/application-accelerator-samples
19 + | subPath: tanzu-java-web-app
Note A secret reference is only provided to
GitRepository
ifgitops_ssh_secret
is set to a non-empty string in some fashion, either by a package property or a workload parameter. To force aGitRepository
to not reference a secret, set the value to an empty string (""
).
After defining the name of the Kubernetes secret, you can define the secret.
Despite both the package value and workload parameter being called gitops.ssh_secret
, you can use HTTP(S) transports as well:
-
Ensure that the repository in the
Workload
specification useshttp://
orhttps://
schemes in any URLs that relate to the repositories. For example,https://github.com/my-org/my-repo
instead ofgithub.com/my-org/my-repo
orssh://github.com:my-org/my-repo
. -
In the same namespace as the workload, create a Kubernetes secret object of type
kubernetes.io/basic-auth
with the name matching the one expected by the supply chain. For example:apiVersion: v1 kind: Secret metadata: name: GIT-SECRET-NAME annotations: tekton.dev/git-0: GIT-SERVER # ! required type: kubernetes.io/basic-auth stringData: username: GIT-USERNAME password: GIT-PASSWORD
-
With the secret created with the name matching the one configured for
gitops.ssh_secret
, attach it to theServiceAccount
used by the workload. For example:apiVersion: v1 kind: ServiceAccount metadata: name: default secrets: - name: registry-credentials - name: tap-registry - name: GIT-SECRET-NAME imagePullSecrets: - name: registry-credentials - name: tap-registry
For more information about the credentials and setting up the Kubernetes secret, see Git Authentication's HTTP section.
Aside from using HTTP(S) as a transport, you can also use SSH:
-
Ensure that the repository URL in the workload specification uses
ssh://
as the scheme in the URL, for example,ssh://[email protected]:my-org/my-repo.git
-
Create a Kubernetes secret object of type
kubernetes.io/ssh-auth
:apiVersion: v1 kind: Secret metadata: name: GIT-SECRET-NAME annotations: tekton.dev/git-0: GIT-SERVER type: kubernetes.io/ssh-auth stringData: ssh-privatekey: SSH-PRIVATE-KEY # private key with push-permissions identity: SSH-PRIVATE-KEY # private key with pull permissions identity.pub: SSH-PUBLIC-KEY # public of the `identity` private key known_hosts: GIT-SERVER-PUBLIC-KEYS # git server public keys
-
With the secret created with the name matching the one configured for
gitops.ssh_secret
, attach it to the ServiceAccount used by the workload. For example:apiVersion: v1 kind: ServiceAccount metadata: name: default secrets: - name: registry-credentials - name: tap-registry - name: GIT-SECRET-NAME imagePullSecrets: - name: registry-credentials - name: tap-registry
For information about how to generate the keys and set up SSH with the Git server, see Git Authentication's SSH section.
With the workload.spec.source.git
filled, the supply chain takes care of
managing a child GitRepository
object that keeps track of commits made to the
Git repository stated in workload.spec.source.git
.
For each revision found, gitrepository.status.artifact
gets updated providing
information about an HTTP endpoint that the controller makes available for
other components to fetch the source code from within the cluster.
The digest of the latest commit:
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: tanzu-java-web-app
spec:
gitImplementation: go-git
ignore: '!.git'
interval: 1m0s
ref: {branch: main}
timeout: 20s
url: https://github.com/vmware-tanzu/application-accelerator-samples
status:
artifact:
checksum: 375c2daee5fc8657c5c5b49711a8e94d400994d7
lastUpdateTime: "2022-04-07T15:02:30Z"
path: gitrepository/default/tanzu-java-web-app/d85df1fc.tar.gz
revision: main/d85df1fc28c6b86ca54bd613f55991645d3b257c
url: http://source-controller.flux-system.svc.cluster.local./gitrepository/default/tanzu-java-web-app/d85df1fc.tar.gz
conditions:
- lastTransitionTime: "2022-04-07T15:02:30Z"
message: 'Fetched revision: main/d85df1fc28c6b86ca54bd613f55991645d3b257c'
reason: GitOperationSucceed
status: "True"
type: Ready
observedGeneration: 1
Cartographer passes the artifact URL and revision to further components in the supply chain. Those components must consume the source code from an internal URL where a tarball with the source code is fetched, without having to process any Git-specific details in multiple places.
You can pass the following parameters by using the workload object's
workload.spec.params
field to override the default behavior of the
GitRepository
object created for keeping track of the changes to a repository:
gitImplementation
: name of the Git implementation (go-git
) to fetch the source code.gitops_ssh_secret
: name of the secret in the same namespace as the workload where credentials to fetch the repository are found.
You can also customize the following parameters with defaults for the whole cluster.
Do this by using properties for either tap-values.yaml
when installing supply chains by using Tanzu Application Platform profiles,
or ootb-supply-chain-*-values.yml
when installing the OOTB packages
individually):
gitops.ssh_secret
: the same asgitops_ssh_secret
workload parameter
You can provide source code from a local directory such as, from a directory in the developer's file system. The Tanzu CLI provides two flags to specify the source code location in the file system and where the source code is pushed to as a container image:
--local-path
: path on the local file system to a directory of source code to build for the workload--source-image
: destination image repository where source code is staged before being built
This way, whether the cluster the developer targets is local (a cluster in the developer's machine) or not, the source code is made available by using a container image registry.
For example, if a developer has source code under the current directory
(.
) and access to a repository in a container image
registry, you can create a workload as follows:
tanzu apps workload create tanzu-java-web-app \
--app tanzu-java-web-app \
--type web \
--local-path . \
--source-image $REGISTRY/test
Publish source in "." to "REGISTRY-SERVER/REGISTRY-REPOSITORY"?
It may be visible to others who can pull images from that repository
Yes
Publishing source in "." to "REGISTRY-SERVER/REGISTRY-REPOSITORY"...
Published source
Create workload:
1 + |---
2 + |apiVersion: carto.run/v1alpha1
3 + |kind: Workload
4 + |metadata:
5 + | labels:
6 + | app.kubernetes.io/part-of: tanzu-java-web-app
7 + | apps.tanzu.vmware.com/workload-type: web
8 + | name: tanzu-java-web-app
9 + | namespace: default
10 + |spec:
11 + | source:
12 + | image: REGISTRY-SERVER/REGISTRY-REPOSITORY:latest@<digest>
Where:
REGISTRY-SERVER
is the container image registry.REGISTRY-REPOSITORY
is the repository in the container image registry.
Both the cluster and the developer's machine must be configured to properly provide credentials for accessing the container image registry where the local source code is published to.
The Tanzu CLI must push the source code to the container image registry
indicated by --source-image
. To do so, the CLI must find the credentials,
so the developer must configure their machine accordingly.
To ensure credentials are available, use docker
to make the necessary
credentials available for the Tanzu CLI to perform the image push. Run:
docker login REGISTRY-SERVER -u REGISTRY-USERNAME -p REGISTRY-PASSWORD
Aside from the developer's ability to push source code to the container image registry, the cluster must also have the proper credentials, so it can pull that container image, unpack it, run tests, and build the application.
To provide the cluster with the credentials, point the ServiceAccount used by the workload at the Kubernetes secret that contains the credentials.
If the registry that the developer targets is the same one for which credentials were provided while setting up the workload namespace, no further action is required. Otherwise, follow the same steps as recommended for the application image.
A workload specifies that source code must come from an image by setting
workload.spec.source.image
to point at the registry provided by using
--source-image
. Instead of having a GitRepository object created, an
ImageRepository object is instantiated, with its specification filled in such a
way to keep track of images pushed to the registry provided by the user.
Take the following workload as an example:
apiVersion: carto.run/v1alpha1
kind: Workload
metadata:
name: app
labels:
app.kubernetes.io/part-of: app
apps.tanzu.vmware.com/workload-type: web
spec:
source:
image: 10.188.0.3:5000/test:latest
Instead of a GitRepository
object, an ImageRepository
is created:
Workload/app
│
- ├─GitRepository/app
+ ├─ImageRepository/app
│
├─Image/app
│ ├─Build/app-build-1
│ │ └─Pod/app-build-1-build-pod
│ ├─PersistentVolumeClaim/app-cache
│ └─SourceResolver/app-source
│
├─PodIntent/app
│
├─ConfigMap/app
│
└─Runnable/app-config-writer
└─TaskRun/app-config-writer-2zj7w
└─Pod/app-config-writer-2zj7w-pod
ImageRepository
provides the same semantics as GitRepository
,
except that it looks for source code in container image registries rather than
Git repositories.
This approach aids integration with existing CI systems, such as Jenkins, and can pull artifacts from existing Maven repositories, including Jfrog Artifactory.
There are no dedicated fields in the Workload
resource for
specifying the Maven artifact configuration. You must fill in the
name
/value
pairs in the params
structure.
For example:
apiVersion: carto.run/v1alpha1
kind: Workload
metadata:
name: my-workload
labels:
apps.tanzu.vmware.com/workload-type: web
spec:
params:
- name: maven
value:
groupId: com.example
artifactId: springboot-initial
version: RELEASE # latest 'RELEASE' or a specific version (e.g.: '1.2.2')
type: jar # optional (defaults to 'jar')
classifier: sources # optional
There are two ways to create a workload that defines a specific version of a Maven artifact as source in the Tanzu CLI.
The first way is to define the source through CLI flags. For example:
tanzu apps workload apply my-workload \
--maven-artifact springboot-initial \
--maven-version 2.6.0 \
--maven-group com.example \
--type web --app spring-boot-initial -y
Another flag that can be used alongside the others in this type of command is --maven-type
, which refers to the Maven packaging type and defaults to jar
if not specified.
The second one is through complex params (in JSON or YAML format). To specify the Maven info with this method, run:
tanzu apps workload apply my-workload \
--param-yaml maven='{"artifactId": "springboot-initial", "version": "2.6.0", "groupId": "com.example"}'\
--type web --app spring-boot-initial -y
To create a workload that defines the RELEASE
version of a maven artifact as source, run:
tanzu apps workload apply my-workload \
--param-yaml maven='{"artifactId": "springboot-initial", "version": "RELEASE", "groupId": "com.example"}'\
--type web --app spring-boot-initial -y
The Maven repository URL and required credentials are defined in the supply chain, not the workload. For more information, see Installing OOTB Basic.
The MavenArtifact only supports authentication using basic authentication.
Additionally, MavenArtifact supports security using the TLS protocol. The Application Operator can configure the MavenArtifact to use a custom, or self-signed certificate authority (CA).
The MavenArtifact expects that all of the earlier credentials are provided in one secret, formatted as shown later:
---
apiVersion: v1
kind: Secret
metadata:
name: maven-credentials
type: Opaque
data:
username: <BASE64> # basic auth user name
password: <BASE64> # basic auth password
caFile: <BASE64> # PEM Encoded certificate data for custom CA
You cannot use the Tanzu CLI to create secrets such as this, but you can use the kubectl CLI instead.
For example:
kubectl create secret generic maven-credentials \
--from-literal=username=literal-username \
--from-file=password=/path/to/file/with/password.txt \
--from-file=caFile=/path/to/ca-certificate.pem