Development Guide
Read this document to learn how to develop the project. Please also follow guidelines defined in this document.
Prerequisites
Make
Go at least 1.16
GoReleaser CLI installed
NOTE: Use the commit SHA, as we use the
no_unique_dist_dir
feature, which was not yet released.go install github.com/goreleaser/goreleaser@b53dbb89d02aa3673782f3d063d7d5039446baac
Helper scripts may introduce additional dependencies. However, all helper scripts support the SKIP_DEPS_INSTALLATION
environment variable flag.
By default, flag is set to true
, so all scripts try to use tools installed on your local machine as this speed up the process.
If you do not want to install any additional tools, or you want to ensure reproducible scripts
results export SKIP_DEPS_INSTALLATION=false
, so the proper tool version will be automatically installed and used.
Dependency management
This project uses go modules
as a dependency manager. To install all required dependencies, use the following command:
go mod download
Makefile
This project make to run most common tasks. In order to get help, run the following command:
make help
Testing
Unit tests
To run all unit tests, execute:
make test-unit
To generate the unit test coverage HTML report, execute:
make test-cover-html
NOTE: The default browser with the generated report opens automatically.
Lint tests
To run lint tests, execute:
make test-lint
To automatically fix lint issues, execute:
make fix-lint-issues
Integration tests
We support the cross-functional integration tests that are defined in test package and
Kubernetes controller integration tests which are using fake K8s API Server and etcd
.
Cross-functional
The cross-functional tests are executed on kind
where all Capact components are pre-installed.
make test-integration
K8s controller
The Kubernetes controller tests are executed on your local machine by starting a local control plane - etcd
and kube-apiserver
.
For that purpose we use the envtest library.
make test-k8s-controller
Docker Image Security Scan
To build images and execute a Snyk vulnerability scan on the containers, execute:
make image-security-scan
NOTE: It is required to accept Snyk's TOC in order for this to work. It is recommended to create a free Snyk account.
Development cluster
To run development cluster, we use kind
.
Create a cluster and install components
To create the development cluster and install all components, execute:
make dev-cluster
You can export the following environment variables to configure the script:
- To disable monitoring stack installation, use
DISABLE_MONITORING_INSTALLATION=true
. - To disable kubed installation, use
DISABLE_KUBED_INSTALLATION=true
. - To disable
/etc/hosts
update with all Capact subdomain, useDISABLE_HOSTS_UPDATE=true
. - To disable setting self-signed TLS certificate for
*.capact.local
as trusted, useDISABLE_ADDING_TRUSTED_CERT=true
. - To disable Database Populator, use
ENABLE_POPULATOR=false
- To enable test setup, use
USE_TEST_SETUP=true
. - To disable higher resource requests and limits for components, use
INCREASE_RESOURCE_LIMITS=false
. - To override Capact Helm chart values, use
CUSTOM_CAPACT_SET_FLAGS
e.g.CUSTOM_CAPACT_SET_FLAGS="--set gateway.auth.password=myPass"
. - To override Ingress NGINX Helm chart values, use
CUSTOM_NGINX_SET_FLAGS
. - To override the Git branch from which the source manifests should be populated, use
HUB_MANIFESTS_SOURCE_REPO_REF
, e.g.HUB_MANIFESTS_SOURCE_REPO_REF="my-fancy-branch"
- To override Cert Manager Helm chart values, use
CUSTOM_CERT_MANAGER_SET_FLAGS
.
Access Gateway GraphQL Playground
Capact Gateway aggregates all GraphQL APIs from multiple components (Local Hub, Public Hub, Engine) into a single endpoint.
To see the Gateway URL and authentication details, use the following command:
helm get notes -n capact-system capact
Rebuild Docker images and update cluster
To rebuild all Docker images and upgrade the Helm charts on development cluster with new images, execute:
make dev-cluster-update
Swap a cluster deployment with your local process
To make it easier to develop services running on Kubernetes, you can use Telepresence. Instead of rebuilding a component image and deploying it on Kubernetes, you can setup a Telepresence session and run the local process in your cluster.
To use Telepresence to swap a cluster deployment, execute the following command:
telepresence --namespace {namespace} --swap-deployment {deployment-name}
Now you can run your process in your Telepresence shell. The shell inherits all the environment variables from the replaced Pod. Refer to the Usage instructions for a particular component in a corresponding README file.
Delete cluster
To delete the development cluster, execute:
make dev-cluster-delete
Build and push Docker images
There are a Make targets dedicated to build and push Capact Docker images.
We have images for:
- application defined under cmd directory
- tests defined under test directory
- infra tools defined under /hack/images directory
The default build and push configuration can be change via environment variables. For example:
export DOCKER_REPOSITORY=ghcr.io/capactio/
export DOCKER_TAG=latest
All components
To build all Docker images with your changes and push them to a registry, follow these steps.
Build all Docker images:
make build-all-images
Push the Docker images to registry:
make push-all-images
Single component
If you want to build and push Docker image for a single component, follow these steps:
Build a specific Docker image:
For application defined under cmd package use it names, e.g. for
hub
:make build-app-image-hub
For tests defined under test package use it names, e.g. for
e2e
:make build-test-image-e2e
Push the built Docker image to a registry:
For application defined under cmd package use it names, e.g. for
hub
:make push-app-image-hub
For tests defined under test package use it names, e.g. for
e2e
:make push-test-image-e2e
Releasing Helm Charts
In order to push the latest Help charts to the configured GCS bucket, execute the following:
make release-charts
Build Binaries
To build all the CLI tools binaries (Capact CLI and Populator), execute the following:
make build-all-tools
The binaries will be placed under the bin/
subdirectory in the root of the source tree.
Generators
To execute all generators, execute:
make generate
Read below sections to execute only a specific generator.
Generate Go code from the OCF JSON Schemas
This project uses the quicktype library, which improves development by generating Go code from the JSON Schemas.
Each time the specification is changed you can regenerate the Go struct. To do this, execute:
make gen-go-api-from-ocf-spec
To generate the Go structs for a specific OCF version, execute:
OCF_VERSION={VERSION} make gen-go-api-from-ocf-spec
NOTE: Go structs are generated in
pkg/sdk/apis
package.
Generate K8s resources
This project uses controller-gen for generating utility code and Kubernetes YAML. Code and manifests generation is controlled by the presence of special "marker comments" in Go code.
Each time the Go code related to K8s controller is change, you need to update generated resources. To do this, execute:
make gen-k8s-resources
Generate code from GraphQL schema
This project uses the GQLGen library, which generates the Go struct and server from GraphQL schema definition.
In Capact project we have three GraphQL schemas, from which the Go code is generated:
Each time the GraphQL schema changes, you need to update generated resources. To do this, execute:
make gen-graphql-resources
Generate documentation
For the Capact CLI development we use Cobra library. The documentation for the CLI is generated automatically based on CLI commands code.
To regenerate the documentation for CLI, execute:
make gen-docs
Instrumentation
This section describes the approach for Capact components instrumentation.
Enable metrics scrape
We use Prometheus Operator for monitoring. To enable metrics scraping, you need to create a ServiceMonitor with capact.io/scrape-metrics: "true"
label. ServiceMonitor can be created in any Namespace.
Check Engine metrics.yaml file for a reference on how to create a proper Service and ServiceMonitor.
Add Grafana Dashboard
To make the Grafana dashboard management easier, we use Grafana Dashboard sidecar. It watches all ConfigMaps in the cluster with a label grafana_dashboard: "1"
. Changes to the ConfigMaps are monitored and the imported dashboards are updated or deleted accordingly.
A recommendation is to use one ConfigMap per dashboard as Grafana doesn't handle multiple dashboards properly. Additionally, we keep dashboards as JSON files in a separate folder and load them into ConfigMap using Files.Get
Helm command. As a result:
- Dashboard is more readable.
- No escaping is needed for double curly brackets.
- IDE can still support JSON formatting/validation.
Check the Engine Helm chart for a reference on how to store and load the dashboards from JSON to ConfigMap.
CAUTION: The size of a ConfigMap is limited to 1 MB.
Useful materials when creating Grafana dashboards:
Access Prometheus and Grafana
If you installed Capact with monitoring enabled, the Prometheus and Grafana are not exposed using Ingress. You can access them by forwarding Service ports to your localhost.
Prometheus
Forward the Prometheus server to your localhost:
kubectl port-forward svc/monitoring-kube-prometheus-prometheus -n capact-system 9090
Now can open your browser at http://localhost:9090. In the Prometheus dashboard, you can query on the metrics, see all the predefined alerts and Prometheus targets.
Grafana
Forward the Grafana server to your localhost:
kubectl port-forward svc/monitoring-grafana -n capact-system 3000:80
Now you can open your browser at http://localhost:3000 to access the Grafana instance. To log in, use:
username: admin
password: okon