Many of the instructions here replicate what's in the tektoncd/pipeline development guide, with a couple of caveats currently.
- This project has not yet been tested with GKE
- The instructions here pertain to building and deploying the backend that lets us interact with Tekton resources, as well as running the frontend locally for development.
We would love to accomplish these tasks and to update this document, contributions welcome!
You must install these tools:
go
: The language Tekton Dashboard is built ingit
: For source controldep
: For managing external Go dependencies. - Please Install dep v0.5.0 or greater.ko
: For development.ko
version v0.1 or higher is required fordashboard
to work correctly.- Node.js & npm: For building and running the frontend locally. See
engines
in package.json for versions used. kubectl
: For interacting with your kube cluster.
Your [$GOPATH
] setting is critical for ko apply
to function properly: a
successful run will typically involve building pushing images instead of only
configuring Kubernetes resources.
Note that there exists a bug in certain versions of kubectl
whereby the auth
field is missing from created secrets. Known good versions we've tested are 1.11.3 and 1.13.2.
The Go tools require that you clone the repository to the
src/github.com/tektoncd/dashboard
directory in your
GOPATH
.
To check out this repository:
- Create your own fork of this repo
- Clone it to your machine:
mkdir -p ${GOPATH}/src/github.com/tektoncd
cd ${GOPATH}/src/github.com/tektoncd
git clone git@github.com:${YOUR_GITHUB_USERNAME}/dashboard.git
cd dashboard
git remote add upstream git@github.com:tektoncd/dashboard.git
git remote set-url --push upstream no_push
Adding the upstream
remote sets you up nicely for regularly
syncing your fork.
- We've had good success using Docker Desktop: ensure your Kubernetes cluster is healthy and you have plenty of disk space allocated as PVs will be created for PipelineRuns.
- Ensure you can push images to a Docker registry - the above listed requirements are only for local development, otherwise we pull in the tooling for you in the image.
GOPATH
: If you don't have one, simply pick a directory and addexport GOPATH=...
$GOPATH/bin
onPATH
: This is so that tooling installed viago get
will work properly.KO_DOCKER_REPO
: The docker repository to which developer images should be pushed (e.g.gcr.io/[gcloud-project]
ordocker.io<myusername>
). You can also run a local registry and setKO_DOCKER_REPO
to reference the registry (e.g. atlocalhost:5000/mydashboardimages
).
.bashrc
example:
export GOPATH="$HOME/go"
export PATH="${PATH}:${GOPATH}/bin"
export KO_DOCKER_REPO='docker.io/myusername'
Make sure to configure
authentication
for your KO_DOCKER_REPO
if required. To be able to push images to
gcr.io/<project>
, you need to run this once:
gcloud auth configure-docker
The user you are using to interact with your k8s cluster must be a cluster admin to create role bindings:
# Using gcloud to get your current user
USER=$(gcloud config get-value core/account)
# Make that user a cluster admin
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user="${USER}"
Currently you must install the Tekton dashboard into the same namespace you wish to create and get Tekton resources in.
While iterating on the project, you may need to:
- Run
dep ensure -v
to retrieve dependencies required to build - Run the Alpine based Go tests in Docker with:
docker build -f Dockerfile_test .
- Run the Stretch based Go tests with race condition checking in Docker with:
docker build -f Dockerfile_race_test .
- Install the dashboard
- Interact with the created Kubernetes service - we've had success using Postman on Mac and data provided must be JSON
Tekton Dashboard does not involve any custom resource definitions, we only interact with them.
You can stand up a version of the dashboard on-cluster (to your
kubectl config current-context
):
First install and build the npm project.
npm install
There is a dedicated npm job for ko builds
npm run build_ko
This will build the static resources and add them to the kodata
directory.
ko apply -f config/
The dashboard can be accessed by running kubectl proxy
, which proxies requests through the API Server. Assuming default
is the install namespace for the dashboard, you can access the web UI at localhost:8001/api/v1/namespaces/default/services/tekton-dashboard:http/proxy/
As you make changes to the code, you can redeploy your dashboard by simply using ko apply
against the config
directory again.
You can clean up everything with:
ko delete -f config/
To look at the dashboard logs, run:
kubectl logs -l app=tekton-dashboard
npm install
Run npm start
for a dev server. Navigate to http://localhost:8000/
in your browser. The app will automatically hot-reload any changes to the source files, including CSS. If it is unable to hot-reload it will fallback to a full page refresh.
Note: If you've exposed the backend by some other means than port-forwarding port 9097 as described above, update API_DOMAIN
in config_frontend/config.json
to provide the correct details.
Run npm run build
to build the project. The build artifacts will be stored in the dist/
directory. This will perform a production build of the static resources. It correctly bundles React in production mode and optimizes the build for the best performance. Filenames include hashes to facilitate long-term caching.
Run npm test
to execute the unit tests via Jest in interactive watch mode. This also generates a code coverage report by default.
Coverage threshold is set to 90%, if it falls below the threshold the test script will fail.
Tests are defined in *.test.js
files alongside the code under test.
Run npm run lint
to execute the linter (eslint + prettier). This will ensure code follows the conventions and standards used by the project.
Run npm run lint:fix
to automatically fix a number of types of problem including code style.
Run npm run storybook
to start storybook in development mode. Navigate to http://localhost:4000/
in your browser. The app will automatically hot-reload any changes to the source files, including CSS.
Stories are defined in *.stories.js
files alongside their components.
Run npm run storybook:build
to build the static storybook files. The build artifacts will be stored in the static-storybook/
directory and can be hosted on GitHub Pages or any other static resource server.
The backend API provides the following endpoints at /v1/namespaces/<namespace>
:
GET endpoints
Namespaces
GET /v1/namespaces/
Get all namespaces for the cluster
Returns HTTP code 200 and a list of namespaces in the cluster
Returns HTTP code 404 if an error occurred getting the namespaces
Service Accounts
GET /v1/namespaces/<namespace>/serviceaccounts
Get all ServiceAccounts
Returns HTTP code 200 and a list of ServiceAccounts in the cluster
Returns HTTP code 404 if an error occurred getting the ServiceAccounts
Pipelines
GET /v1/namespaces/<namespace>/pipelines
Get all Tekton Pipelines
Returns HTTP code 200 and a list of Pipelines in the given namespace
Returns HTTP code 404 if an error occurred getting the Pipeline list
GET /v1/namespaces/<namespace>/pipelines/<pipeline-name>
Get a Tekton Pipeline by name
Returns HTTP code 200 and the given pipeline in the given namespace if found
Returns HTTP code 404 if an error occurred getting the Pipeline
PipelineRuns
GET /v1/namespaces/<namespace>/pipelineruns
Get all Tekton PipelineRuns, also supports '?name=<pipeline-name>' querying
Get all Tekton PipelineRuns, also supports '?repository=https://gitserver/foo/bar' querying
Returns HTTP code 200 and a list of PipelineRuns, optionally matching the above query, in the given namespace
Returns HTTP code 404 if an error occurred getting the PipelineRun list
GET /v1/namespaces/<namespace>/pipelineruns/<pipelinerun-name>
Get a Tekton PipelineRun by name
Returns HTTP code 200 and the given PipelineRun in the given namespace
Returns HTTP code 404 if an error occurred getting the PipelineRun
Tasks
GET /v1/namespaces/<namespace>/tasks
Get all Tekton tasks
Returns HTTP code 200 and a list of Tasks in the given namespace
Returns HTTP code 404 if an error occurred getting the Task list
GET /v1/namespaces/<namespace>/tasks/<task-name>
Get a Tekton Task by name
Returns HTTP code 200 and the given Task in the given namespace if found
Returns HTTP code 404 if an error occurred getting the TaskRun
TaskRuns
GET /v1/namespaces/<namespace>/taskruns
Get all Tekton TaskRuns
Get all Tekton TaskRuns, also supports '?name=<task-name>' querying
Returns HTTP code 200 and a list of TaskRuns in the given namespace
Returns HTTP code 404 if an error occurred getting the TaskRun list
GET /v1/namespaces/<namespace>/taskruns/<taskrun-name>
Get a Tekton TaskRun by name
Returns HTTP code 200 and the given TaskRun in the given namespace if found
Returns HTTP code 404 if an error occurred getting the TaskRun
PipelineResources
GET /v1/namespaces/<namespace>/pipelineresources
Get all Tekton PipelineResources
Returns HTTP code 200 and a list of PipelineResources in the given namespace
Returns HTTP code 404 if an error occurred getting the PipelineResource list
GET /v1/namespaces/<namespace>/pipelineresources/<pipelineresource-name>
Get a Tekton PipelineResource by name
Returns HTTP code 200 and the given PipelineResource in the given namespace if found
Returns HTTP code 404 if an error occurred getting the PipelineResource
Logs
GET /v1/namespaces/<namespace>/logs/<pod-name>
Get the logs for a Pod by name
Returns HTTP code 200 and the pod's logs in the given namespace if found
Returns HTTP code 404 if an error occurred getting the logs or no pod was found by name in the given namespace
GET /v1/namespaces/<namespace>/taskrunlogs/<taskrun-name>
Get the logs for a TaskRun by name
Returns HTTP code 200 and the logs from a TaskRun
Example payload response is formatted as so:
{
"PodName": "run-pipeline0-pipeline0-task-bk48w-pod-0fd388",
"Steps": [
{
"ContainerName": "build-step-git-source-pipeline0-git-source-lqzds",
"Logs": [
"{\"level\":\"warn\",\"ts\":1554153223.112332,\"logger\":\"fallback-logger\",\"caller\":\"logging/config.go:65\",\"msg\":\"Fetch GitHub commit ID from kodata failed: \\\"ref: refs/heads/master\\\" is not a valid GitHub commit ID\"}",
"{\"level\":\"info\",\"ts\":1554153223.7619479,\"logger\":\"fallback-logger\",\"caller\":\"git-init/main.go:100\",\"msg\":\"Successfully cloned \\\"https://github.com/ncskier/tekton-pipeline-config\\\" @ \\\"master\\\" in path \\\"/workspace/git-source\\\"\"}"
]
},
{
"ContainerName": "build-step-kubectl-apply",
"Logs": [
"task.tekton.dev/build-push created",
"task.tekton.dev/deploy-simple-kubectl-task created",
"pipeline.tekton.dev/simple-pipeline created"
]
},
{
"ContainerName": "nop",
"Logs": [
"Build successful"
]
},
{
"ContainerName": "build-step-credential-initializer-ml54v",
"Logs": [
"{\"level\":\"warn\",\"ts\":1554153217.318807,\"logger\":\"fallback-logger\",\"caller\":\"logging/config.go:65\",\"msg\":\"Fetch GitHub commit ID from kodata failed: \\\"ref: refs/heads/master\\\" is not a valid GitHub commit ID\"}",
"{\"level\":\"info\",\"ts\":1554153217.3199604,\"logger\":\"fallback-logger\",\"caller\":\"creds-init/main.go:40\",\"msg\":\"Credentials initialized.\"}"
]
},
{
"ContainerName": "build-step-place-tools",
"Logs": null
}
]
}
Returns HTTP code 404 if an error occurred getting the logs or TaskRun pod was found by name in the given namespace
GET /v1/namespaces/<namespace>/pipelinerunlogs/<pipelinerun-name>
Get the logs for a PipelineRun by name
Returns HTTP code 200 and the logs from a PipelineRun (unformatted)
Credentials
GET /v1/namespaces/<namespace>/credentials
Get all credentials by name in the given namespace
Returns HTTP code 500 if an error occurred getting the credentials
Returns HTTP code 200 and the given credential as a Kubernetes secret in the given namespace with a blanked out password if found, otherwise an empty list is returned
GET /v1/namespaces/<namespace>/credentials/<id>
Get a credential by ID
Returns HTTP code 400 if the credential does not exist by name or an invalid namespace was provided
Returns HTTP code 500 if an error occurred getting the credential
Returns HTTP code 200 and the given credential as a Kubernetes secret in the given namespace with a blanked out password, otherwise an empty list is returned
Knative
GET /v1/namespaces/<namespace>/knative/installstatus
Get the install status of a Knative resource group.
The request body should contain the resource group to check for. Shorthand values are accepted for Knative serving and eventing-sources: use ("component": "serving" or "eventing-sources"). Any Kubernetes group can be used too, for example: `extensions/v1beta1`
Returns HTTP code 204 if the component is installed (any Kubernetes resource can be provided)
Returns HTTP code 400 if a bad request is sent
Returns HTTP code 417 (expectation failed) if the resource is not registered
Note that a check of the resource definition being registered is performed: not that pods are running and healthy
Extensions
GET /v1/extensions
Get all extensions in the given namespace
Returns HTTP code 500 if an error occurred getting the extensions
Returns HTTP code 200 and the given extensions in the given namespace if found, otherwise an empty list is returned
POST endpoints
Credentials
POST /v1/namespaces/<namespace>/credentials
Create a new credential
Request body must contain a name and type ('accesstoken' or 'userpass'). They may contain a description and the URL that the credential will be used for (e.g. the Git server). It can also include serviceAccount that gets patched with the secret. Accesstokens must contain an 'accesstoken' and type userpass must contain 'username' and 'password'.
Returns HTTP code 201 if the credential was created OK and sets the 'Content-Location' header
Returns HTTP code 400 if a bad request was provided
Returns HTTP code 406 if no body is provided
Returns HTTP code 500 if an error occurred creating the credential
Example POSTs (non-trivial as it involves the URL map):
{
"name": "mysecretname",
"username": "myusername",
"password": "mypassword",
"description": "my secret for github",
"url": {"tekton.dev/git-0": "https://github.com"}
"serviceAccount": "sa1"
}
PipelineRuns
POST /v1/namespaces/<namespace>/pipelineruns
Creates a new manual PipelineRun based on a specified Pipeline
Request body must contain pipelinename for the Pipeline to run
Optional parameters listed below may be provided in the request body depending on requirements of the Pipeline:
- pipelineruntype can be specifed as helm if your Pipeline is deploying with Helm
- gitresourcename, gitcommit, and repourl can be provided in the request body if your Pipeline requires a PipelineResource of type `git`
- imageresourcename, gitcommit and reponame can be provided in the request body if your Pipeline requires a PipelineResource of type `image`
- helmsecret and registrysecret are optional depending on whether the Pipeline requires secrets for accessing an insecure registry or using Helm
- serviceaccount can be provided to specify the serviceaccount to use for the PipelineRun
- registrylocation can be provided to specify where you wish to push built images
Returns HTTP code 201 if the PipelineRun was created successfully
Returns HTTP code 400 if a bad request was provided
Returns HTTP code 412 if the Pipeline to create the PipelineRun could not be found
Example POST - for a Pipeline that clones a repository from GitHub and pushes to Dockerhub using a configured secret
{
"pipelinename": "mypipeline",
"serviceaccount": "tekton-pipelines",
"registrylocation": "dockerhubusername",
"gitresourcename": "mygitresourcename",
"imageresourcename": "myimageresourcename",
"gitcommit": "branchorcommit",
"repourl": "https://github.com/myorg/myrepo",
"reponame": "myrepo"
}
PUT endpoints
Credentials
PUT /v1/namespaces/<namespace>/credentials/<id>
Update credential by ID
Request body must contain id, username, password, type ('accesstoken' or 'userpass'), description and the URL that the credential will be used for (e.g. the Git server)
Returns HTTP code 204 if the credential was updated OK (no contents are provided in the response)
Returns HTTP code 400 if a bad request was provided or if an error occurs updating the credential
PipelineRuns
PUT /v1/namespaces/<namespace>/pipelineruns/<pipelinerun-name>
Update pipelinerun status
Request body must contain desired status ("status": "PipelineRunCancelled" to cancel a running one).
Returns HTTP code 204 if the PipelineRun was cancelled successfully (no contents are provided in the response)
Returns HTTP code 400 if a bad request was used
Returns HTTP code 404 if the requested PipelineRun could not be found
Returns HTTP code 412 if the status was already set to that
Returns HTTP code 500 if the PipelineRun could not be stopped (an error has occurred when updating the PipelineRun)
DELETE endpoints
Credentials
DELETE /v1/namespaces/<namespace>/credentials/<id>
Delete a credential by ID
Returns HTTP code 200 if the credential was deleted
Returns HTTP code 400 if a bad request was used or if the secret was not found
Returns HTTP code 500 if the found credential could not be deleted
Backend
Backend can be extended by registering backend extensions. The backend extension is discovered by adding the label and the annotations in the extension service.
annotations:
tekton-dashboard-endpoints: <path of the extension at the proxy>
tekton-dashboard-display-name: <display name of the extension> (optional)
tekton-dashboard-bundle-location: <ui bundle location of the extension> (optional)
labels:
tekton-dashboard-extension: "true"
1.Each extension is mounted onto /v1/extensions/extension-name/ at the dashboard 1.Requests to /v1/extensions/extension-name/ are routed to / at the extension in question. / at the extension is always exposed in the expectation that many extensions will only need one endpoint. 1.If tekton-dashboard-endpoints is set to foo then /v1/extensions/extension-name/foo is routed to /foo at the extension 1.Multiple context roots can be specified by using the . character to separate them: e.g. if tekton-dashboard-endpoints: foo.bar then /v1/extensions/extension-name/foo is routed to /foo and /v1/extensions/extension-name/bar is routed to /bar at the extension. 1."/" is a reserved context root for javascript. "tekton-dashboard-endpoints" must be always set if the extension has javascript.