Technical Documentation: tektoncd/pipeline
βΉοΈ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference
Overview (`README.md`)
Tekton Pipelines
The Tekton Pipelines project provides k8s-style resources for declaring
CI/CD-style pipelines.
Tekton Pipelines are Cloud Native:
- Run on Kubernetes
- Have Kubernetes clusters as a first class type
- Use containers as their building blocks
Tekton Pipelines are Decoupled:
- One Pipeline can be used to deploy to any k8s cluster
- The Tasks which make up a Pipeline can easily be run in isolation
- Resources such as git repos can easily be swapped between runs
Tekton Pipelines are Typed:
- The concept of typed resources means that for a resource such as an
Image,
implementations can easily be swapped out (e.g. building with
kaniko v.s.
buildkit)
Want to start using Pipelines
- Installing Tekton Pipelines
- Jump in with the "Getting started" tutorial!
- Take a look at our roadmap
- Discover our releases
Required Kubernetes Version
- Starting from the v0.24.x release of Tekton: Kubernetes version 1.18 or later
- Starting from the v0.27.x release of Tekton: Kubernetes version 1.19 or later
- Starting from the v0.30.x release of Tekton: Kubernetes version 1.20 or later
- Starting from the v0.33.x release of Tekton: Kubernetes version 1.21 or later
- Starting from the v0.39.x release of Tekton: Kubernetes version 1.22 or later
- Starting from the v0.41.x release of Tekton: Kubernetes version 1.23 or later
- Starting from the v0.45.x release of Tekton: Kubernetes version 1.24 or later
- Starting from the v0.51.x release of Tekton: Kubernetes version 1.25 or later
- Starting from the v0.59.x release of Tekton: Kubernetes version 1.27 or later
- Starting from the v0.61.x release of Tekton: Kubernetes version 1.28 or later
Read the docs
The latest version of our docs is available at:
Version specific links are available in the releases page and on the
Tekton website.
See our API compatibility policy for info on the
stability level of the API.
See our Deprecations table for features that have been
deprecated and the earliest date they'll be removed.
Migrating
v1beta1 to v1
Several Tekton CRDs and API spec fields, including ClusterTask CRD and Pipeline
Resources fields, were updated or deprecated during the migration from v1beta1
to v1.
For users migrating their Tasks and Pipelines from v1beta1 to v1, check
out the v1beta1 to v1 migration guide.
v1alpha1 to v1beta1
In the move from v1alpha1 to v1beta1 several spec fields and Tekton
CRDs were updated or removed .
For users migrating their Tasks and Pipelines from v1alpha1 to v1beta1, check
out the spec changes and migration paths.
Want to contribute
We are so excited to have you!
- See CONTRIBUTING.md for an overview of our processes
- See DEVELOPMENT.md for how to get started
- Deep dive into demystifying the inner workings
(advanced reading material) - Look at our
good first issues
and our
help wanted issues
Overview (`docs/README.md`)
Tekton Pipelines
Tekton Pipelines is a Kubernetes extension that installs and runs on your Kubernetes cluster.
It defines a set of Kubernetes Custom Resources that act as building blocks from which you can assemble CI/CD pipelines. Once installed,
Tekton Pipelines becomes available via the Kubernetes CLI (kubectl) and via API calls, just
like pods and other resources. Tekton is open-source and part of the CD Foundation,
a Linux Foundation project.
Tekton Pipelines entities
Tekton Pipelines defines the following entities:
| Entity | Description |
|---|---|
Task |
Defines a series of steps which launch specific build or delivery tools that ingest specific inputs and produce specific outputs. |
TaskRun |
Instantiates a Task for execution with specific inputs, outputs, and execution parameters. Can be invoked on its own or as part of a Pipeline. |
Pipeline |
Defines a series of Tasks that accomplish a specific build or delivery goal. Can be triggered by an event or invoked from a PipelineRun. |
PipelineRun |
Instantiates a Pipeline for execution with specific inputs, outputs, and execution parameters. |
PipelineResource (Deprecated) |
Defines locations for inputs ingested and outputs produced by the steps in Tasks. |
Run (alpha) |
Instantiates a Custom Task for execution when specific inputs. |
Getting started
To get started, complete the Tekton Pipelines Tutorial and go through our
examples.
Understanding Tekton Pipelines
See the following topics to learn how to use Tekton Pipelines in your project:
- Creating a Task
- Running a standalone Task
- Creating a Pipeline
- Running a Pipeline
- Defining Workspaces
- Configuring authentication
- Using labels
- Viewing logs
- Pipelines metrics
- Variable Substitutions
- Running a Custom Task
- Remote resolution of Pipelines and Tasks
- Trusted Resources
Contributing to Tekton Pipelines
If you'd like to contribute to the Tekton Pipelines project, see the Tekton Pipeline Contributor's Guide.
Except as otherwise noted, the content of this page is licensed under the
Creative Commons Attribution 4.0 License,
and code samples are licensed under the
Apache 2.0 License.
Overview (`examples/README.md`)
Examples
This directory contains examples of Tekton Pipelines in action.
To deploy them to your cluster (after
installing the CRDs and running the controller):
Some examples have metadata:generateName instead of metadata:name. These examples
can not be executed by kubectl apply. Please use kubectl create instead.
In few examples to demonstrate tasks that push image to registry, sample URLgcr.io/christiewilson-catfactory is used. To run these examples yourself, you
will need to change the values of this sample registry URL to a registry you can
push to from inside your cluster. If you are following instructions
here to setup then use the value of$KO_DOCKER_REPO instead of gcr.io/christiewilson-catfactory.
# To invoke a TaskRun
kubectl apply -f examples/v1/taskruns/
# To invoke a PipelineRun
kubectl apply -f examples/v1/pipelineruns/Results
You can track the progress of your taskruns and pipelineruns with this command,
which will also format the output nicely.
$ kubectl get taskruns -o=custom-columns-file=./test/columns.txt
NAME TYPE STATUS START
test-git-branch Succeeded True 2019-02-11T21:21:03Z
test-git-ref Succeeded True 2019-02-11T21:21:02Z
test-git-tag Succeeded True 2019-02-11T21:21:02Z$ kubectl get pipelineruns -o=custom-columns-file=./test/columns.txt
NAME TYPE STATUS START
demo-pipeline-run-1 Succeeded True 2019-02-11T21:21:03Z
output-pipeline-run Succeeded True 2019-02-11T21:35:43ZYou can also use kubectl get tr or kubectl get pr to query all taskruns orpipelineruns respectively.
Overview (`hack/README.md`)
Assorted scripts for development
This directory contains several scripts useful in the development process of
Tekton Pipelines.
update-codegen.sh: Updates auto-generated client
libraries.update-deps.sh: Updates Go dependencies.update-openapigen.sh: Updates OpenAPI specification and Swagger file.verify-codegen.sh: Verifies that auto-generated
client libraries are up-to-date.update-reference-docs.shand related files: Generatesdocs/pipeline-api.md.reference-docs-gen-config.jsonis the configuration file for thegen-api-reference-docsbinary.reference-docs-templatecontains Go templates for the generated Markdown.
generate-dependabot.sh: Generates.github/dependabot.ymlfrom.github/dependabot.config.yml. This allows monitoring dependencies on multiple release branches with a single configuration file. A GitHub Actions workflow automatically regenerates this file weekly and creates a PR if changes are detected.- Release docs have been moved to the top-level
tektondir
Overview (`tekton/README.md`)
Tekton Repo CI/CD
Why does Tekton pipelines have a folder called tekton? Cuz we think it would be cool
if the tekton folder were the place to look for CI/CD logic in most repos!
We dogfood our project by using Tekton Pipelines to build, test and release
Tekton Pipelines! This directory contains theTasks andPipelines
that we use.
Create an official release
To create an official release, follow the steps in the release-cheat-sheet.
Create a patch release
Sometimes we'll find bugs that we want to backport fixes for into previous releases
or discover things that were missing from a release that are required by upstream
consumers of a project. In that case we'll make a patch release. To make one:
- Create a milestone to track issues and pull requests to include in the release,
e.g. v0.12.1 - The issues when possible should first be fixed and merged into master. As they
are fixed, add the issues to the milestone and tag them withneeds-cherry-pick. - Create a branch for the release named
release-<version number>x, e.g.release-v0.13.0x
and push it to the repo https://github.com/tektoncd/pipeline (you may need help from
an OWNER with permission to push) if that release branch does not exist. - Use git cherry-pick to cherry pick the
fixes from master into the release branch you have created (use-xto include
the original commit information). - Check that you have cherry picked all issues in the milestone and look for any
pull requests you may have missed with withneeds-cherry-pick. - Remove
needs-cherry-pick
from all issues that have been cherry picked. - Create an official release for the patch, with the
patch version incremented - Close the milestone.
Nightly releases
Existing approach:
The nightly release pipeline is
triggered nightly by Tekton.
This Pipeline uses:
Setup
To start from scratch and use these Pipelines and Tasks:
- Install Tekton
- Setup the Tasks and Pipelines
- Create the required service account + secrets
- Setup post-processing
Install Tekton
# If this is your first time installing Tekton in the cluster you might need to give yourself permission to do so
kubectl create clusterrolebinding cluster-admin-binding-someusername \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
# Example, Tekton v0.9.1
export TEKTON_VERSION=0.9.1
kubectl apply --filename https://infra.tekton.dev/tekton-releases/pipeline/previous/v${TEKTON_VERSION}/release.yamlInstall tasks and pipelines
Add all the Tasks to the cluster, including thegolang
Tasks from thetektoncd/catalog, and the
release Tasks fromtektoncd/plumbing.
Use a version of the tektoncdcatalog
tasks that is compatible with version of Tekton being released, usually master.
Install Task from plumbing too:
# Apply the Tasks we are using from the catalog
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/golang-build/0.3/golang-build.yaml
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/golang-test/0.2/golang-test.yaml
# Apply Tasks and other resources from Plumbing.
#
# If you want to install everything, including tekton-nightly components,
# run this command from the root of the plumbing repo (this requires
# "tekton-nightly" namespace to already be created in your cluster):
kubectl kustomize ./tekton/resources/release | kubectl apply -f -
# If you don't want the tekton-nightly components then run the following
# command from the root of the plumbing repo:
kubectl kustomize ./tekton/resources/release/overlays/default | kubectl apply -f -Apply the tasks from the pipeline repo:
# Apply the Tasks and Pipelines we use from this repo
kubectl apply -f tekton/publish.yaml
kubectl apply -f tekton/release-pipeline.yaml
# Apply the resources - note that when manually releasing you'll re-apply these
kubectl apply -f tekton/resources.yamlTasks and Pipelines from this repo are:
publish.yaml- ThisTaskuseskanikoto build and
publish base images, and useskoto build all of the container images we
release and generate therelease.yamlrelease-pipeline.yaml- ThisPipeline
uses thegolangTasks from thetektoncd/catalogandpublish.yaml'sTask.
Dogfooding Cluster connectivity and secrets
To connect to the cloud instance and OKE cluster we need the Oracle Cloud CLI client. Install Oracle Cloud CLI from https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm
The next step is to establish connection from the local client to the cloud instance. Login to the Oracle Cloud Console and create a new
API keyfrom the user profile.
Follow the steps here: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#two
Download a Private Key and Add a new API key as mentioned in the doc. Copy the config file to~/.oci/configand update the path to the private key file in config.
With this the config is ready for usage by the CLI.Test the connection by doing a get of the OKE cluster id.
Refer here https://docs.oracle.com/en-us/iaas/tools/oci-cli/3.70.0/oci_cli_docs/cmdref/ce.html for the CLI options.
Command to create a kubeconfig in your local could be obtained from console navigating to the OKE > Actions > Access Cluster. Run the command pointing to the PUBLIC_ENDPOINT and we should be connected to the cluster.NOTE: When executing release pipelines, some tasks require OCI CLI commands which need credentials. The OCI credentials secret is already deployed to the dogfooding cluster via terraform and is mounted as a workspace to tasks that require it (such as the precheck task). Release managers do not need to create this secret manually. This is stated here for troubleshooting purposes.
Setup post processing
Post-processing services perform post release automated tasks. Today the only
service available collects the PipelineRun logs uploads them to the release
bucket. To use release post-processing services, the PipelineResource inresources.yaml must be configured with a valid targetURL in the
cloud event PipelineResource named post-release-trigger:
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: post-release-trigger
spec:
type: cloudEvent
params:
- name: targetURI
value: http://el-pipeline-release-post-processing.default.svc.cluster.local:8080 # This has to be changed to a valid URLThe targetURL should point to the event listener configured in the cluster.
The example above is configured with the correct value for the dogfooding
cluster, using the event listener pipeline-release-post-processing.
Supporting scripts and images
Some supporting scripts have been written using Python3:
- koparse - Contains logic for parsing
release.yamlfiles created
byko
ko image
In order to run ko, and to be able to use a cluster's default credentials, we
need an image which contains:
kogolang- Required bykoto buildgcloud- Required to auth with default namespace credentials
The image which we use for this is built from
tekton/ko/Dockerfile.
go-containerregistry#383
is about publishing a ko image, which hopefully we'll be able to move it.
GitHub Action based approach:
The GitHub Actions workflow provides an alternative approach for automated nightly releases with enhanced CI/CD capabilities and better integration with GitHub infrastructure.
The nightly release workflow is triggered daily and uses:
- release-nightly-pipeline.yaml - Tekton Pipeline for nightly releases
- publish-nightly.yaml - Tekton Task for building and publishing nightly images
Key Features:
Automated Scheduling:
- Runs daily at 03:00 UTC via cron schedule
- Supports manual triggering with customizable parameters
- Intelligent change detection - only releases when there are recent commits (configurable)
Multi-mode Operation:
- Production mode: For
tektoncd/pipelinerepository with full release capabilities - Fork mode: For testing in forks with isolated buckets and registries
Usage:
Scheduled Release:
The workflow runs automatically every night and will create a release if:
- There have been commits in the last 25 hours, OR
- Force release is enabled, OR
- It's manually triggered
Manual Release:
# Trigger via GitHub UI or CLI
gh workflow run nightly-release.yaml \
--field kubernetes_version=v1.33.0 \
--field force_release=true \
--field dry_run=falseFork Testing:
For testing in forks, the workflow automatically:
- Uses a test bucket pattern:
gs://tekton-releases-nightly-{repo-owner} - Publishes to
ghcr.io/{owner}/pipeline/*instead of production registry - Skips certain production-only validations
Output:
The workflow generates:
- Container images tagged with
vYYYYMMDD-{sha7}format - Release YAML manifests uploaded to GCS bucket
- Multi-architecture image support
- Comprehensive build logs and artifacts
This approach provides better observability, easier debugging, and more flexible configuration compared to the traditional Tekton-only pipeline approach.
Overview (`test/README.md`)
Tests
To run tests:
Unit tests and build tests (those run by presubmits) run against your Pipelines clone:
# Unit tests
go test ./...
# Build tests
./test/presubmit-tests.sh --build-testsE2E tests run test cases in your local Pipelines clone
against the Pipelines installation on your current kube cluster.
To ensure your local changes are reflected on your cluster, you must first build
and install them with ko apply -R -f ./config/.
# Integration tests
go test -v -count=1 -tags=e2e -timeout=20m ./test
# Conformance tests
go test -v -count=1 -tags=conformance -timeout=10m ./testBy running the commands above, you start the tests on the cluster of current-context
in local kubeconfig file (~/.kube/config by default) in you local machine.
Sometimes local tests pass but presubmit tests fail, one possible reason
is the difference of running environments. The envs that our presubmit test
uses are stored in ./*.env files. Specifically,
- e2e-tests-kind-prow-alpha.env for
pull-tekton-pipeline-alpha-integration-tests- e2e-tests-kind-prow-beta.env for [
pull-tekton-pipeline-beta-integration-tests]
(TODO: https://github.com/tektoncd/pipeline/issues/6048 Add permanent link after plumbing setup for prow)
- e2e-tests-kind-prow.env for
pull-tekton-pipeline-integration-tests
Unit tests
Unit tests live side by side with the code they are testing and can be run with:
go test ./...By default go test will not run the end to end tests,
which need -tags=e2e to be enabled.
Unit testing Controllers
Kubernetes client-go provides a number of
fake clients and objects for unit testing. The ones we are using are:
- Fake Kubernetes client:
Provides a fake REST interface to interact with Kubernetes API - Fake pipeline client
: Provides a fake REST PipelineClient Interface to interact with Pipeline
CRDs.
You can create a fake PipelineClient for the Controller under test like
this:
import (
fakepipelineclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/fake
)
pipelineClient := fakepipelineclientset.NewSimpleClientset()This
pipelineClient
is initialized with no runtime objects. You can also initialize the client with
Kubernetes objects and can interact with them using thepipelineClient.Pipeline()
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
obj := &v1alpha1.PipelineRun {
ObjectMeta: metav1.ObjectMeta {
Name: "name",
Namespace: "namespace",
},
Spec: v1alpha1.PipelineRunSpec {
PipelineRef: v1alpha1.PipelineRef {
Name: "test-pipeline",
APIVersion: "a1",
},
}
}
pipelineClient := fakepipelineclientset.NewSimpleClientset(obj)
objs := pipelineClient.Pipeline().PipelineRuns("namespace").List(v1.ListOptions{})
// You can verify if List was called in your test like this
action := pipelineClient.Actions()[0]
if action.GetVerb() != "list" {
t.Errorf("expected list to be called, found %s", action.GetVerb())
}To test the Controller of CRD (CustomResourceDefinitions), you need to add the
CRD to the informers so that the
listers can get the access.
For example, the following code will test PipelineRun
pipelineClient := fakepipelineclientset.NewSimpleClientset()
sharedInfomer := informers.NewSharedInformerFactory(pipelineClient, 0)
pipelineRunsInformer := sharedInfomer.Pipeline().V1alpha1().PipelineRuns()
obj := &v1alpha1.PipelineRun {
ObjectMeta: metav1.ObjectMeta {
Name: "name",
Namespace: "namespace",
},
Spec: v1alpha1.PipelineRunSpec {
PipelineRef: v1alpha1.PipelineRef {
Name: "test-pipeline",
APIVersion: "a1",
},
}
}
pipelineRunsInformer.Informer().GetIndexer().Add(obj)End to end tests
Setup
Environment variables used by end to end tests:
KO_DOCKER_REPO- Set this to an image registry your tests can push images toGCP_SERVICE_ACCOUNT_KEY_PATH- Tests that need to interact with GCS buckets
will use the json credentials at this path to authenticate with GCS.SYSTEM_NAMESPACE- Set this to your Tekton deployment namespace liketekton-pipelines.
Without this setting, the E2E test will useknative-testingas default namespace.In Kaniko e2e test, setting
GCP_SERVICE_ACCOUNT_KEY_PATHas the path of the
GCP service account JSON key which has permissions to push to the registry
specified inKO_DOCKER_REPOwill enable Kaniko to use those credentials when
pushing an image.In GCS taskrun test, GCP service account JSON key file at path
GCP_SERVICE_ACCOUNT_KEY_PATH, if present, is used to generate Kubernetes
secret to access GCS bucket.In Storage artifact bucket test, the
GCP_SERVICE_ACCOUNT_KEY_PATHJSON key
is used to create/delete a bucket which will be used for output to input
linking by thePipelineRuncontroller.
Please note that in order to run the e2e tests in local machine, apply below optional RBAC config that grants controller access to Pod logs:
kubectl apply -f optional_config/enable-log-access-to-controller/To create a service account usable in the e2e tests:
PROJECT_ID=your-gcp-project
ACCOUNT_NAME=service-account-name
# gcloud configure project
gcloud config set project $PROJECT_ID
# create the service account
gcloud iam service-accounts create $ACCOUNT_NAME --display-name $ACCOUNT_NAME
EMAIL=$(gcloud iam service-accounts list | grep $ACCOUNT_NAME | awk '{print $2}')
# add the storage.admin policy to the account so it can push containers
gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$EMAIL --role roles/storage.admin
# create the JSON key
gcloud iam service-accounts keys create config.json --iam-account=$EMAIL
export GCP_SERVICE_ACCOUNT_KEY_PATH="$PWD/config.json"
export SYSTEM_NAMESPACE=tekton-pipelinesRunning
Before running e2e tests, make sure you have:
- A running Kubernetes cluster (e.g.
kind) with Tekton installed:
ko apply -R -f config/- Apply the optional RBAC required by the controller to access pod logs:
kubectl apply -f optional_config/enable-log-access-to-controller/- The required environment variables should be set:
export KO_DOCKER_REPO=kind.local # or your custom registry
export SYSTEM_NAMESPACE=tekton-pipelinesEnd to end tests live in this directory. To run these tests, you must providego with -tags=e2e. To run the full e2e test suite against your current cluster locally, deactivate the tests that require root access:
go test -v -count=1 -tags=e2e -timeout=20m ./test -skipRootUserTests=trueTo run a specific e2e test:
go test -v -count=1 -tags=e2e -timeout=20m ./test -run ^TestPipelineRunBy default the tests run against your current kubeconfig
context, but you can change that and other settings with the flags:
go test -v -count=1 -tags=e2e -timeout=20m ./test
go test -v -count=1 -tags=e2e -timeout=20m ./test --kubeconfig ~/special/kubeconfig --cluster myspecialclusterIf tests are applied to the cluster with hardware architecture different to the base one
(for instance go test starts on amd64 architecture and --kubeconfig points to s390x Kubernetes cluster),
use TEST_RUNTIME_ARCH environment variable to specify the target hardware architecture(amd64, s390x, ppc64le, arm, arm64, etc)
You can also use
all of flags defined in knative/pkg/test.
To include tests for Windows, you need to specify the windows_e2e build tag. For example:
go test -v -count=1 -tags=e2e,windows_e2e -timeout=20m ./testPlease note that in order to run Windows tests there must be at least one Windows node available in the target Kubernetes cluster.
Flags
- By default the e2e tests against the current cluster in
~/.kube/configusing
the environment specified in
your environment variables. - Since these tests are fairly slow, running them with logging enabled is
recommended (-v). - Using
--logverboseto see the verbose log output from
test as well as from k8s libraries. - Using
-count=1is
the idiomatic way to disable test caching. - The end to end tests take a long time to run so a value like
-timeout=20m
can be useful depending on what you're running - TestKanikoTaskRun requires containers to run with root user. Using
-skipRootUserTests=trueskips it.
You can use test flags to control the environment your tests run
against, i.e. override
your environment variables:
go test -v -tags=e2e -count=1 ./test --kubeconfig ~/special/kubeconfig --cluster myspecialclusterTests importing github.com/tektoncd/pipeline/test
recognize the
flags added by knative/pkg/test.
Tests are run in a new random namespace prefixed with the word arendelle-.
Unless you set the TEST_KEEP_NAMESPACES environment variable they will get
automatically cleaned up after running the test.
Running specific test cases
To run all the test cases with their names starting with the same letters, e.g.
TestTaskRun, use
the -run flag with go test:
go test -v -tags=e2e -count=1 ./test -run ^TestTaskRunRunning YAML tests
To run the YAML e2e tests, run the following command:
go test -v -count=1 -tags=examples -timeout=20m ./test/To limit parallelism of tests, use -parallel=n where n is the number of
tests to run in parallel.
Running upgrade tests
There are two scenarios in upgrade tests. One is to install the previous release, upgrade to the current release, and
validate whether the Tekton pipeline works. The other is to install the previous release, create the pipelines and tasks,
upgrade to the current release, and validate whether the Tekton pipeline works.
Prerequisites for running upgrade tests locally
- Set up the cluster
Running against a fresh kind cluster
- export SKIP_INITIALIZE=true
Running against a GKE cluster
- export PROJECT_ID=
- install kubetest
- export PROJECT_ID=
To run the upgrade tests, run the following command:
./test/e2e-tests-upgrade.shAdding integration tests
In the test dir you will find several libraries in the test
package you can use in your tests.
This library exists partially in this directory and partially inknative/pkg/test.
The libs in this dir can:
init_test.goinitializes anything needed globally be the
tests- Get access to client objects
- Generate random names
- Poll Pipeline resources
All integration tests must be marked with the e2e
build constraint so that go test ./... can
be used to run only the unit tests, i.e.:
// +build e2eGet access to client objects
To initialize client objects use the command line flags which
describe the environment:
func setup(t *testing.T) *test.Clients {
clients, err := test.NewClients(kubeconfig, cluster, namespaceName)
if err != nil {
t.Fatalf("Couldn't initialize clients: %v", err)
}
return clients
}The Clients struct contains initialized clients for accessing:
- Kubernetes objects
Pipelines
For example, to create a Pipeline:
_, err = clients.v1PipelineClient.Pipelines.Create(test.Route(namespaceName, pipelineName))And you can use the client to clean up resources created by your test (e.g. in
your test cleanup):
func tearDown(clients *test.Clients) {
if clients != nil {
clients.Delete([]string{routeName}, []string{configName})
}
}See clients.go.
Generate random names
You can use the function GenerateName() to append a random string for crds
or anything else, so that your tests can use unique names each time they run.
import "github.com/tektoncd/pipeline/pkg/names"
namespace := names.SimpleNameGenerator.GenerateName("arendelle")Poll Pipeline resources
After creating Pipeline resources or making changes to them, you will need to
wait for the system to realize those changes. You can use polling methods to
check the resources reach the desired state.
The WaitFor* functions use the Kuberneteswait package. For
polling they usePollImmediate
behind the scene. And the callback function isConditionFunc,
which returns a bool to indicate if the function should stop, and an error
to indicate if there was an error.
For example, you can poll a TaskRun until having a Status.Condition:
err = WaitForTaskRunState(c, hwTaskRunName, func(tr *v1alpha1.TaskRun) (bool, error) {
if len(tr.Status.Conditions) > 0 {
return true, nil
}
return false, nil
}, "TaskRunHasCondition", v1Version)Metrics will be emitted
for these Wait methods tracking how long test poll for.
Conformance tests
Conformance tests live in this directory. These tests are used to check API specs
of Pipelines. To run these tests, you must provide go with -tags=conformance. By default, the tests
run against your current kubeconfig context, but you can change that and other settings with the flags like
the end to end tests:
go test -v -count=1 -tags=conformace -timeout=10m ./test
go test -v -count=1 -tags=conformace -timeout=10m ./test --kubeconfig ~/special/kubeconfig --cluster myspecialclusterFlags that could be set in conformance tests are exactly the same as flags in end to end tests.
Just note that the build tags should be -tags=conformance.
Presubmit tests
presubmit-tests.sh is the entry point for all tests
run on presubmit by Prow.
You can run this locally with:
test/presubmit-tests.sh
test/presubmit-tests.sh --build-tests
test/presubmit-tests.sh --unit-testsProw is configured in
the knative config.yaml in tektoncd/plumbing
via the sections for tektoncd/pipeline.
Running presubmit integration tests
The presubmit integration tests entrypoint will run:
- The integration tests
- A test of our example CRDs
When run using Prow, integration tests will try to get a new cluster using
boskos and
these hardcoded GKE projects,
which only
the tektoncd/plumbing OWNERS
have access to.
If you would like to run the integration tests against your cluster, you can use
the current context in your kubeconfig, provide KO_DOCKER_REPO (as specified
in the DEVELOPMENT.md), usee2e-tests.sh directly and provide the --run-tests argument:
export KO_DOCKER_REPO=gcr.io/my_docker_repo
test/e2e-tests.sh --run-testsOr you can set $PROJECT_ID to a GCP project and rely on
kubetest to
setup a cluster for you:
export PROJECT_ID=my_gcp_project
test/presubmit-tests.sh --integration-testsPer Feature flag tests
Per-feature flag tests verify that the combinations of feature flags work together
correctly, ensuring that individual flags don't interfere with each other's
functionality and that overall outcomes remain consistent.
Per TEP0138,
minimum end-to-end tests for stable features are utilized, mocking stable, beta,
and alpha stability levels within different test environments.
To run these tests, you must provide go with -tags=featureflags. By default, the tests
run against your current kubeconfig context, but you can change that and other settings with the flags like
the end to end tests:
go test -v -count=1 -tags=featureflags -timeout=60m ./test -run ^TestPerFeatureFlagFlags that could be set in featureflags tests are exactly the same as flags in end to end tests.
Just note that the build tags should be -tags=featureflags.
Test Categorization: Parallel vs Serial Execution
The e2e test suite implements a categorization system that allows tests to run in parallel or serial mode,
optimizing test execution time while ensuring safety for tests that modify shared cluster state.
Overview
Tests are categorized using comment annotations in the source code:
- Parallel tests: Safe to run concurrently, don't modify shared cluster state
- Serial tests: Must run sequentially because they modify ConfigMaps in
system.Namespace()
The test runner (TestMain in init_test.go) parses these annotations and orchestrates test execution accordingly.
Annotation Format
Tests use structured Go comments to declare their execution mode:
// @test:execution=parallel
func TestMyParallelTest(t *testing.T) {
// Test implementation
}
// @test:execution=serial
// @test:reason=modifies results-from field in feature-flags ConfigMap
// @test:tags=artifacts,featureflags,stateful
func TestMySerialTest(t *testing.T) {
// Test implementation
}Annotation fields:
@test:execution- Required: eitherparallelorserial@test:reason- Recommended for serial tests: explains why serial execution is needed@test:tags- Optional: comma-separated tags for categorization and filtering
Running Tests by Category
Use the -category flag to control which tests run:
# Run only parallel tests (fast, safe for concurrent execution)
go test -tags=e2e -category=parallel -timeout=20m ./test
# Run only serial tests (slower, sequential execution)
go test -tags=e2e -category=serial -timeout=20m ./test
# Run all tests with proper ordering (serial β parallel β unknown)
go test -tags=e2e -category=all -timeout=30m ./test
# Show test categorization without running tests
go test -tags=e2e -show-tests ./testNote: When the -run flag is provided, category filtering is automatically skipped and the
user's test filter takes precedence. This allows running individual tests without category orchestration:
# Run a specific test (skips category filtering)
go test -tags=e2e -run ^TestBundleResolverCache$ ./testExecution Order
When running with -category=all, tests execute in this order:
- Serial tests run first, sequentially, with fail-fast behavior
- Parallel tests run next, concurrently
- Unknown tests (unannotated) run last
This ensures that tests modifying shared state complete before parallel execution begins.
When to Mark Tests as Serial
A test MUST be marked serial if it:
- Modifies ConfigMaps in
system.Namespace()(typicallytekton-pipelines) - Changes feature flags in the
feature-flagsConfigMap - Modifies any other shared cluster-wide configuration or resources
Common examples:
- Tests changing
enable-api-fields,results-from,coschedulefeature flags - Tests modifying
trusted-resources-verification-no-match-policy - Any test calling
updateConfigMap(ctx, c.KubeClient, system.Namespace(), ...) - Tests modifying controller replicas
When to Mark Tests as Parallel
A test can be marked parallel if it:
- Only creates/modifies resources in its own test namespace
- Doesn't modify
system.Namespace()ConfigMaps - Can safely run concurrently with other tests
This includes most conformance tests, resolver tests, workspace tests, etc.
Implementation Details
The categorization system is implemented via:
TestMain (
init_test.go): Parses annotations from source files using Go's AST parser,
categorizes tests, and routes execution based on the-categoryflag.Annotation Parser: Scans
*_test.gofiles, extracts@test:*comments, and builds
a manifest of test metadata.Test Filtering: Uses
flag.Set("test.run", pattern)to filter which tests execute
in each run.
Overview (`cmd/entrypoint/README.md`)
entrypoint
This binary is used to override the entrypoint of a container by
wrapping it and executing original entrypoint command in a subprocess.
Tekton uses this to make sure TaskRuns' steps are executed in order, only
after sidecars are ready and previous steps have completed successfully.
Flags
The following flags are available:
-entrypoint: "original" command to be executed (as
entrypoint). This will be executed as a sub-process onentrypoint-post_file: file path to write once the sub-process has
finished. If the sub-process failed, it will write to{{post_file}}.errinstead of{{post_file}}.-wait_file: file path to watch before starting the sub-process. It
watches for{{wait_file}}and{{wait_file}}.errpresence and
will either execute the sub-process (in case of{{wait_file}}) or
skip the execution, write to{{post_file}}.errand return an error
(exitCode>= 0)-wait_file_content: expects thewait_fileto contain actual
contents. It will continue watching forwait_fileuntil it has
content.-stdout_path: If specified, the stdout of the sub-process will be
copied to the given path on the local filesystem.-stderr_path: If specified, the stderr of the sub-process will be
copied to the given path on the local filesystem. It can be set to the
same value as{{stdout_path}}so both streams are copied to the same
file. However, there is no ordering guarantee on data copied from both
streams.-enable_spire: If set will enable signing of the results by SPIRE. Signing
results by SPIRE ensures that no process other than the current process can
tamper the results and go undetected.-spire_socket_path: This flag makes sense only when enable_spire is set.
When enable_spire is set, spire_socket_path is used to point to the
SPIRE agent socket for SPIFFE workload API.
Any extra positional arguments are passed to the original entrypoint command.
Example
The following example of usage for entrypoint waits for/tekton/run/3/out file to exist and executes the command bash with argsecho and hello, then writes the file /tekton/run/4/out, or/tekton/run/4/out.err in case the command fails.
entrypoint \
-wait_file /tekton/run/3/out \
-post_file /tekton/run/4/out \
-entrypoint bash -- \
echo helloWaiting for Sidecars
In cases where the TaskRun's Pod has sidecar containers -- including, possibly,
injected sidecars that Tekton itself didn't specify -- the first step should
also wait until all those sidecars have reported as ready. Starting before
sidecars are ready could lead to flaky errors if steps rely on the sidecar
being ready to succeed.
To account for this, the Tekton controller starts TaskRun Pods with the first
step's entrypoint binary configured to wait for a special file provided by the
Kubernetes Downward
API.
This allows Tekton to write a Pod annotation when all sidecars report as ready,
and for the value of that annotation to appear to the Pod as a file in a
Volume. To the Pod, that file always exists, but without content until the
annotation is set, so we instruct the entrypoint to wait for the -wait_file
to contain contents before proceeding.
Example
The following example of usage for entrypoint waits for/tekton/downward/ready file to exist and contain actual contents
(-wait_file_contents), and executes the command bash with argsecho and hello, then writes the file /tekton/run/1/out, or/tekton/run/1/out.err in case the command fails.
entrypoint \
-wait_file /tekton/downward/ready \
-wait_file_contents \
-post_file /tekton/run/1/out \
-entrypoint bash -- \
echo hello`cp` Mode
In order to make the entrypoint binary available to the user's steps, it gets
copied to a Volume that's shared with all the steps' containers as read-only. This is done
in an initContainer pre-step, that runs before steps start.
To reduce external dependencies, the entrypoint binary actually copies
itself to the shared Volume. When executed with the positional args of cp <src> <dst>, the entrypoint binary copies the <src> file to <dst> and
exits.
It's executed as an initContainer in the TaskRun's Pod like:
initContainers:
- image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/entrypoint
args:
- cp
- /ko-app/entrypoint # <-- path to the entrypoint binary inside the image
- /tekton/bin/entrypoint
volumeMounts:
- name: tekton-internal-bin
mountPath: /tekton/bin
containers:
- image: user-image
command:
- /tekton/bin/entrypoint
... args to entrypoint ...
volumeMounts:
- name: tekton-internal-bin
mountPath: /tekton/bin
readonly: true
volumes:
- name: tekton-internal-bin
volumeSource:
emptyDir: {}Overview (`cmd/nop/README.md`)
`nop` Image
This image is responsible for two internal functions of Tekton:
- Stopping sidecar containers[#stopping-sidecar-containers]
- Affinity Assistant StatefulSet[#affinity-assistant-statefulset]
The nop image satisfies these two functions with a minimally small image,
both to optimize image pull latency and to present a minimal surface for a
potential attacker.
Stopping sidecar containers
When all steps in a TaskRun are complete, Tekton attempts to gracefully stop
any running sidecar containers, by replacing their image with an image that
exits immediately, regardless of any args passed to the container.
When the nop image is run with any args (except one unique string, described
below), it will exit with the exit code zero
immediately.
- NB: If the sidecar container has its
commandspecified, thenop
binary will not be invoked, and may exit with a non-zero exit code. Tekton
will not interpret this as a TaskRun failure, but it may result in noisy
logs/metrics being emitted.
Affinity Assistant StatefulSet
The Affinity Assistant, which powers workspaces, works
by running aStatefulSet
with an container that runs indefinitely. This container doesn't need to do
anything, it just needs to exist.
When the nop image is passed the string tekton_run_indefinitely (a unique,
Tekton-identified string), it will run indefinitely until it receives a signal
to terminate. The affinity assistant StatefulSet passes this arg to ensure its
container runs indefinitely.
Overview (`docs/developers/README.md`)
Developer docs
This document is aimed at helping maintainers/developers of project understand
the complexity.
We also recommend checking out the
Teknical Tekton
channel for training and tutorials on Tekton!
Contents
- Developing on Tekton:
- Local Setup: Getting your local environment set up to develop on Tekton.
- Testing:
- Overview: Running Tekton tests.
- Best Practices: Guidelines for writing effective unit tests.
- Tracing: Enabling Jaeger tracing
- How Tekton is run on Kubernetes:
- Controller Logic: How Tekton extends Kubernetes using Knative.
- TaskRun Logic: How TaskRuns are run in pods.
- Resources Labeling: Labels applied to Tekton resources.
- Multi-Tenant Support: Running Tekton in multi-tenant configurations.
- Informer Cache Transform: Memory optimization that strips fields from cached objects.
- API Versioning: How Tekton supports multiple API versions and feature gates.
- How specific features are implemented:
Overview (`docs/resolver-template/README.md`)
Resolver Template
This directory contains a working Resolver based on the instructions
from the developer howto in the docs.
Resolver Type
This Resolver responds to type demo.
Parameters
| Name | Desccription | Example Value |
|---|---|---|
url |
The repository url. | https://example.com/repo/ |
Using the template to start a new Resolver
You can use this as a template to quickly get a new Resolver up and
running with your own preferred storage backend.
To reuse the template, simply copy this entire subdirectory to a new
directory.
The entire program for the latest framework is defined in./cmd/resolver/main.go and provides stub
implementations of all the methods defined by the framework.Resolver
interface.
If you choose to use the previous framework (deprecated) is defined in./cmd/demoresolver/main.go and provides stub
implementations of all the methods defined by the framework.Resolver
interface.
Once copied you'll need to run go mod init and go mod tidy at the root
of your project. We don't need this in tektoncd/resolution because this
submodule relies on the go.mod and go.sum defined at the root of the repo.
After your go module is initialized and dependencies tidied, updateconfig/demo-resolver-deployment.yaml. The image field of the container
will need to point to your new go module's name, with a ko:// prefix.
Deploying the Resolver
Requirements
- A computer with
kubectlandkoinstalled. - The
tekton-pipelinesnamespace andResolutionRequest
controller installed. See the getting started
guide for
instructions.
Install
- Install the
"demo"Resolver:
$ ko apply -f ./config/demo-resolver-deployment.yamlTesting
Try creating a ResolutionRequest targeting "demo" with no parameters:
$ cat <<EOF > rrtest.yaml
apiVersion: resolution.tekton.dev/v1beta1
kind: ResolutionRequest
metadata:
name: test-resolver-template
labels:
resolution.tekton.dev/type: demo
EOF
$ kubectl apply -f ./rrtest.yaml
$ kubectl get resolutionrequest -w test-resolver-templateYou should shortly see the ResolutionRequest succeed and the content of
a hello-world Pipeline base64-encoded in the object's status.data
field.
Example PipelineRun
Here's an example PipelineRun that uses the hard-coded demo Pipeline:
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: resolver-demo
spec:
pipelineRef:
resolver: demoWhat's Supported?
- Just one hard-coded
Pipelinefor demonstration purposes.
Except as otherwise noted, the content of this page is licensed under the
Creative Commons Attribution 4.0 License,
and code samples are licensed under the
Apache 2.0 License.
Overview (`docs/security/README.md`)
Security Best Practices
Overview
Tekton Pipelines runs Tasks and Pipelines as Kubernetes workloads. Security
properties such as namespace isolation, RBAC, admission control, service account
permissions, storage access, and network access are provided by Kubernetes and
by the platform configuration around Tekton.
This page describes security best practices for authoring and operating TektonTaskRuns and PipelineRuns where lower-trust workloads could affect
higher-trust workloads.
The broader Tekton Security Threat Model establishes the
principle behind this guidance: Tekton relies on Kubernetes and the surrounding
platform for isolation and enforcement, rather than acting as a security
boundary itself. The workspace scenarios on this page are a worked example of
that model.
Workspace isolation across trust boundaries
Workspaces are a way for TaskRuns and PipelineRuns to mount Kubernetes
volumes. They can be used to share source, build outputs, caches, credentials,
and other files between Tasks. When a workspace is backed by aPersistentVolumeClaim, the security properties of that workspace are the
security properties of the underlying Kubernetes volume.
Treat every shared workspace as part of the trust model for the Tasks andPipelineRuns that can mount it. For example, a PipelineRun that validates an
untrusted pull request and a PipelineRun that builds or publishes a trusted
release should not share the same writeable PVC.
Trust model
Tekton does not enforce filesystem-level isolation between separatePipelineRuns that intentionally mount the same persistent workspace. If twoPipelineRuns bind the same PVC to a workspace, the Pods created for both runs
can access the same files according to the PVC access mode, Kubernetes volume
permissions, and the container security context.
This behavior is by design: workspace sharing is explicit and opt-in. It also
means that isolation between trusted and untrusted workloads is the
responsibility of the pipeline author and cluster operator. Use Kubernetes RBAC,
namespaces, ServiceAccounts, and storage policy to limit which users and
controllers can create PipelineRuns that reference sensitive PVCs.
readOnly workspace bindings can prevent writes from that mount, but they do
not make existing contents trustworthy. Do not treat a shared volume as safe for
a higher-trust run only because the higher-trust run mounts it read-only.
Recommended pattern: per-run `Workspaces`
Use volumeClaimTemplate when a PipelineRun needs a writeable persistent
workspace but should not share files with other runs. A volumeClaimTemplate
creates a new PVC for each PipelineRun or TaskRun, so data written by one run
is not visible through the same workspace binding in another run.
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: validate-pr-
spec:
pipelineRef:
name: validate-pr
workspaces:
- name: source
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1GiPVCs created from volumeClaimTemplate are automatically provisioned. Their
cleanup behavior depends on the PipelineRun lifecycle and the configured
Affinity Assistant mode. See PVC Auto-Cleanup for Workspaces Mode
for details on cleanup after completion.
Avoid sharing PVCs across trust boundaries
Only bind an existing persistentVolumeClaim to a workspace when everyPipelineRun that can mount that claim belongs to the same trust domain and is
allowed to read or modify the files on that volume.
Avoid patterns like the following when the PipelineRuns are triggered by
inputs at different trust levels, such as untrusted pull requests and trusted
release automation:
workspaces:
- name: artifacts
persistentVolumeClaim:
claimName: shared-artifacts-rwxA shared PVC can allow one run to read files left by another run, modify files
that a later run will consume, or race with another run that is reading or
writing the same paths. A subPath on a shared PVC can help organize data, but
it should not be treated as a security boundary between trust domains.
If persistent data must cross a trust boundary, write it to a controlled storage
or artifact system that performs the appropriate validation, signing, promotion,
or access checks before a trusted pipeline consumes it.
Step-level Isolated Workspaces can limit
which Steps and Sidecars inside one Task receive a workspace. That feature
does not isolate separate PipelineRuns that bind the same PVC.
`ReadWriteMany` PVCs
ReadWriteMany is a Kubernetes access mode that allows a volume to be mounted
as read-write by multiple Nodes at the same time, when supported by the storage
provider. Any Pod that is allowed to mount a ReadWriteMany PVC can access the
same filesystem concurrently. This is Kubernetes volume behavior, not behavior
specific to Tekton.
Do not use ReadWriteMany as an isolation mechanism. It is useful for shared
caches and coordinated workflows inside a single trust domain, but it increases
the impact of accidentally sharing a PVC between unrelated or differently
trusted PipelineRuns.
ReadWriteOnce is also not a trust boundary. It limits where the volume can be
mounted, but it does not clear previous contents or prevent a later run with
access to the same PVC from reading or modifying those contents.
Checklist
- Use
volumeClaimTemplatefor writeable workspaces that should be isolated perPipelineRunorTaskRun. - Do not share an existing PVC between pipelines that run code, inputs, or
credentials from different trust levels. - Treat
ReadWriteManyPVCs as concurrently shared filesystems accessible to
any Pod that can mount them. - Do not rely on
subPath, access mode, or task ordering as a security boundary
between trusted and untrusted workloads. - Use separate namespaces, ServiceAccounts, RBAC, and storage classes or claims
for separate trust domains. - Promote artifacts across trust boundaries through systems that validate and
authorize the data before trusted pipelines consume it.
Overview (`test/resolver-with-timeout/README.md`)
The main.go is copied from https://github.com/tektoncd/pipeline/tree/main/docs/resolver-template/cmd/resolver/main.go
This resolver is using timeout parameter to simulate a delay on the resolver response for the testing purpose.
Overview (`examples/v1/pipelineruns/README.md`)
PipelineRun Examples
This directory contains example PipelineRun configurations demonstrating various features of Tekton Pipelines. These examples showcase how to define, configure, and run pipelines with different capabilities such as parameters, workspaces, results, conditional execution, and advanced execution patterns.
These files are intended as reference implementations to help users understand how different PipelineRun configurations work in practice.
Prerequisites
Before running these examples, ensure the following components are installed and configured:
Kubernetes Cluster
You need access to a running Kubernetes cluster. This can be a local cluster (e.g. Kind, Minikube) or a managed cluster from a cloud provider.
Tekton Pipelines
Tekton Pipelines must be installed in the cluster, as these examples rely on Tekton custom resources such as Pipeline, Task, and PipelineRun.
Installation instructions:
https://tekton.dev/docs/pipelines/install/
kubectl
The Kubernetes CLI (kubectl) must be installed and configured to communicate with your cluster.
Documentation:
https://kubernetes.io/docs/tasks/tools/
(Optional) Tekton CLI
The Tekton CLI (tkn) is useful for inspecting PipelineRuns and streaming logs.
Installation instructions:
https://tekton.dev/docs/cli/
Feature Flags
Some examples may require specific Tekton feature flags to be enabled depending on the functionality being demonstrated.
Running the Examples
Some examples in this directory define a PipelineRun resource that can be created directly in your Kubernetes cluster.
If the file defines a fixed metadata.name, you can run it with:
kubectl apply -f <file>.yamlSome examples instead use metadata.generateName. This allows the resource to be created multiple times with unique names.
For these files you should use:
kubectl create -f <file>.yamlUsing kubectl apply on resources that use generateName will fail because apply requires a fixed resource name.
After creating a PipelineRun, you can inspect it with:
kubectl get pipelineruns
kubectl describe pipelinerun <name>You can also view logs for a PipelineRun using the Tekton CLI (tkn):
tkn pipelinerun logs <name> -fExample Categories
Basic Examples
Simple PipelineRun examples demonstrating basic pipeline execution.
Parameters and Results
Examples demonstrating how parameters and results are passed between pipelines and tasks.
Workspaces
Examples demonstrating how workspaces are used to share data between tasks.
Conditional Execution (When Expressions)
Examples showing how to conditionally run tasks based on when expressions.
Pipeline Specification Examples
Examples demonstrating inline pipeline or task specifications.
Execution Behavior and Status
Examples illustrating pipeline execution behavior and reporting.
Final Tasks and Results
Examples demonstrating the use of final tasks and pipeline results.
StepActions
Examples demonstrating the use of StepActions.
Display Name
Examples demonstrating display name usage.
Regression / Edge Case Examples
Examples created to validate bug fixes or regression scenarios.
Additional Resources
- Tekton Pipelines documentation (https://tekton.dev/docs/pipelines/)
- Tekton GitHub repository (https://github.com/tektoncd/pipeline)
Overview (`examples/v1/taskruns/README.md`)
TaskRun Examples
This directory contains example TaskRun configurations demonstrating various Tekton Pipelines features. These examples illustrate how to run individual Tasks and showcase functionality such as parameters, workspaces, sidecars, secrets, StepActions, environment configuration, and execution behavior.
These files serve as reference implementations to help users understand how different TaskRun configurations work in practice.
Prerequisites
Before running these examples, ensure the following components are installed and configured:
Kubernetes Cluster
You need access to a running Kubernetes cluster. This can be a local cluster (such as Kind or Minikube) or a managed cluster from a cloud provider.
Tekton Pipelines
Tekton Pipelines must be installed in the cluster, as these examples rely on Tekton custom resources such as Task, TaskRun, and related pipeline components.
Installation instructions:
https://tekton.dev/docs/pipelines/install/
kubectl
The Kubernetes CLI (kubectl) must be installed and configured to communicate with your cluster.
Documentation:
https://kubernetes.io/docs/tasks/tools/
(Optional) Tekton CLI
The Tekton CLI (tkn) is useful for inspecting TaskRuns and streaming logs.
Installation instructions:
https://tekton.dev/docs/cli/
Feature Flags
Some examples may require specific Tekton feature flags to be enabled depending on the functionality being demonstrated.
Running the Examples
Most examples in this directory define a TaskRun resource that can be created directly in your Kubernetes cluster.
If the file defines a fixed metadata.name, you can run it with:
kubectl apply -f <file>.yamlSome examples instead use metadata.generateName. This allows the resource to be created multiple times with unique names.
For those files you should use:
kubectl create -f <file>.yamlUsing kubectl apply on resources that use generateName will fail because apply requires a fixed resource name.
After creating a TaskRun, you can inspect it with:
kubectl get taskruns
kubectl describe taskrun <name>You can also stream logs for a TaskRun using the Tekton CLI:
tkn taskrun logs <name> -fExample Categories
Basic Examples
Simple TaskRun examples demonstrating basic execution behavior.
Parameters and Results
Examples demonstrating how parameters and results are used within Tasks and TaskRuns.
Environment and Configuration
Examples showing how environment variables and configuration are provided to tasks.
Volumes and Filesystems
Examples demonstrating volume mounting and filesystem configuration.
Workspaces
Examples showing how Tekton workspaces are used to share data between steps and sidecars.
Sidecars
Examples demonstrating the use of sidecar containers alongside task steps.
StepActions
Examples demonstrating the use of StepActions.
Step Templates and Execution Behavior
Examples demonstrating step templates and execution configuration.
Security and Permissions
Examples demonstrating security-related configurations.
Error Handling
Examples demonstrating error handling and failure behavior.
Regression and Internal Validation
Examples primarily used for testing or regression validation.
Additional Resources
- Tekton Pipelines documentation (https://tekton.dev/docs/pipelines/)
- Tekton GitHub repository (https://github.com/tektoncd/pipeline)
Overview (`test/custom-task-ctrls/wait-task-beta/README.md`)
Beta Wait Custom Task for Tekton
This folder is largely copied from experimental/wait-task
for the testing purpose, with resources used for building and releasing the
wait custom task removed.
It provides a Beta version of Tekton Custom
Task that, when run, simply waits a
given amount of time before succeeding, specified by an input parameter namedduration. It also supports timeout and retries.
Overview (`vendor/cel.dev/expr/README.md`)
Common Expression Language
The Common Expression Language (CEL) implements common semantics for expression
evaluation, enabling different applications to more easily interoperate.
Key Applications
- Security policy: organizations have complex infrastructure and need common
tooling to reason about the system as a whole - Protocols: expressions are a useful data type and require interoperability
across programming languages and platforms.
Guiding philosophy:
- Keep it small & fast.
- CEL evaluates in linear time, is mutation free, and not Turing-complete.
This limitation is a feature of the language design, which allows the
implementation to evaluate orders of magnitude faster than equivalently
sandboxed JavaScript.
- CEL evaluates in linear time, is mutation free, and not Turing-complete.
- Make it extensible.
- CEL is designed to be embedded in applications, and allows for
extensibility via its context which allows for functions and data to be
provided by the software that embeds it.
- CEL is designed to be embedded in applications, and allows for
- Developer-friendly.
- The language is approachable to developers. The initial spec was based
on the experience of developing Firebase Rules and usability testing
many prior iterations. - The library itself and accompanying toolings should be easy to adopt by
teams that seek to integrate CEL into their platforms.
- The language is approachable to developers. The initial spec was based
The required components of a system that supports CEL are:
- The textual representation of an expression as written by a developer. It is
of similar syntax to expressions in C/C++/Java/JavaScript - A representation of the program's abstract syntax tree (AST).
- A compiler library that converts the textual representation to the binary
representation. This can be done ahead of time (in the control plane) or
just before evaluation (in the data plane). - A context containing one or more typed variables, often protobuf messages.
Most use-cases will useattribute_context.proto - An evaluator library that takes the binary format in the context and
produces a result, usually a Boolean.
For use cases which require persistence or cross-process communcation, it is
highly recommended to serialize the type-checked expression as a protocol
buffer. The CEL team will maintains canonical protocol buffers for ASTs and
will keep these versions identical and wire-compatible in perpetuity:
Example of boolean conditions and object construction:
// Condition
account.balance >= transaction.withdrawal
|| (account.overdraftProtection
&& account.overdraftLimit >= transaction.withdrawal - account.balance)
// Object construction
common.GeoPoint{ latitude: 10.0, longitude: -5.5 }For more detail, see:
Released under the Apache License.
Overview (`vendor/cloud.google.com/go/README.md`)
Google Cloud Client Libraries for Go
Go packages for Google Cloud Platform services.
Installation
go get cloud.google.com/go/firestore@latest # Replace firestore with the package you want to use.NOTE: Some of these packages are under development, and may occasionally
make backwards-incompatible changes.
Supported APIs
For an updated list of all of our released APIs please see our
reference docs.
[Go Versions Supported](#supported-versions)
Our libraries are compatible with the two most recent major Go
releases, the same policy the Go
programming language follows. This means the currently supported versions are:
- Go 1.24
- Go 1.25
Authentication
By default, each client library will use Application Default Credentials
(ADC) to automatically configure the credentials used in calling the API endpoint.
When using the libraries in a Google Cloud Platform environment such as Compute
Engine, Kubernetes Engine, or App Engine, no additional authentication steps are
necessary. See Authentication methods at Google
and Authenticate for using client libraries
for more information.
client, err := storage.NewClient(ctx)For applications running elsewhere, such as your local development environment,
you can use the gcloud auth application-default login command from the
Google Cloud CLI to set user credentials in
your local filesystem. Application Default Credentials will automatically detect
these credentials. See Set up ADC for a local development
environment
for more information.
Alternately, you may need to provide an explicit path to your credentials. To authenticate
using a service account
key file, either set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path
to your key file, or programmatically passoption.WithCredentialsFile
to the NewClient function of the desired package. For example:
client, err := storage.NewClient(ctx, option.WithCredentialsFile("path/to/keyfile.json"))You can exert even more control over authentication by using the
credentials package to
create an auth.Credentials.
Then pass option.WithAuthCredentials
to the NewClient function:
creds, err := credentials.DetectDefault(&credentials.DetectOptions{...})
...
client, err := storage.NewClient(ctx, option.WithAuthCredentials(creds))Contributing
Contributions are welcome. Please, see the
CONTRIBUTING
document for details.
Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms.
See Contributor Code of Conduct
for more information.
Links
- Go on Google Cloud
- Getting started with Go on Google Cloud
- App Engine Quickstart
- Cloud Functions Quickstart
- Cloud Run Quickstart
Overview (`vendor/dario.cat/mergo/README.md`)
Mergo
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
Mergo merges same-type structs and maps by setting default values in zero-value fields. Mergo won't merge unexported (private) fields. It will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
Also a lovely comune (municipality) in the Province of Ancona in the Italian region of Marche.
Status
Mergo is stable and frozen, ready for production. Check a short list of the projects using at large scale it here.
No new features are accepted. They will be considered for a future v2 that improves the implementation and fixes bugs for corner cases.
Important notes
1.0.0
In 1.0.0 Mergo moves to a vanity URL dario.cat/mergo. No more v1 versions will be released.
If the vanity URL is causing issues in your project due to a dependency pulling Mergo - it isn't a direct dependency in your project - it is recommended to use replace to pin the version to the last one with the old import URL:
replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.160.3.9
Please keep in mind that a problematic PR broke 0.3.9. I reverted it in 0.3.10, and I consider it stable but not bug-free. Also, this version adds support for go modules.
Keep in mind that in 0.3.2, Mergo changed Merge()and Map() signatures to support transformers. I added an optional/variadic argument so that it won't break the existing code.
If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with go get -u dario.cat/mergo. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
Donations
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
Mergo in the wild
Mergo is used by thousands of projects, including:
- containerd/containerd
- datadog/datadog-agent
- docker/cli/
- goreleaser/goreleaser
- go-micro/go-micro
- grafana/loki
- masterminds/sprig
- moby/moby
- slackhq/nebula
- volcano-sh/volcano
Install
go get dario.cat/mergo
// use in your .go code
import (
"dario.cat/mergo"
)Usage
You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. It won't merge empty structs value as they are zero values too. Also, maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection).
if err := mergo.Merge(&dst, src); err != nil {
// ...
}Also, you can merge overwriting values using the transformer WithOverride.
if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
// ...
}If you need to override pointers, so the source pointer's value is assigned to the destination's pointer, you must use WithoutDereference:
package main
import (
"fmt"
"dario.cat/mergo"
)
type Foo struct {
A *string
B int64
}
func main() {
first := "first"
second := "second"
src := Foo{
A: &first,
B: 2,
}
dest := Foo{
A: &second,
B: 1,
}
mergo.Merge(&dest, src, mergo.WithOverride, mergo.WithoutDereference)
}Additionally, you can map a map[string]interface{} to a struct (and otherwise, from struct to map), following the same restrictions as in Merge(). Keys are capitalized to find each corresponding exported field.
if err := mergo.Map(&dst, srcMap); err != nil {
// ...
}Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as map[string]interface{}. They will be just assigned as values.
Here is a nice example:
package main
import (
"fmt"
"dario.cat/mergo"
)
type Foo struct {
A string
B int64
}
func main() {
src := Foo{
A: "one",
B: 2,
}
dest := Foo{
A: "two",
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
}Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, time.Time is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero time.Time?
package main
import (
"fmt"
"dario.cat/mergo"
"reflect"
"time"
)
type timeTransformer struct {
}
func (t timeTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ == reflect.TypeOf(time.Time{}) {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
isZero := dst.MethodByName("IsZero")
result := isZero.Call([]reflect.Value{})
if result[0].Bool() {
dst.Set(src)
}
}
return nil
}
}
return nil
}
type Snapshot struct {
Time time.Time
// ...
}
func main() {
src := Snapshot{time.Now()}
dest := Snapshot{}
mergo.Merge(&dest, src, mergo.WithTransformers(timeTransformer{}))
fmt.Println(dest)
// Will print
// { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 }
}Contact me
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): @im_dario
About
Written by Dario CastaΓ±Γ©.
License
BSD 3-Clause license, as Go language.
Overview (`vendor/fortio.org/safecast/README.md`)
safecast
Avoid accidental overflow of numbers during go type conversions (e.g instead of shorter := bigger.(int8) type conversions use shorter := safecast.MustConv[int8](bigger).
Safecast allows you to safely convert between numeric types in Go and return errors (or panic when using the Must* variants) when the cast would result in a loss of precision, range or sign.
See https://pkg.go.dev/fortio.org/safecast for docs and example.
This is usable from any go with generics (1.18 or later) though our CI uses the latest go.
safecast is about avoiding gosec G115 and CWE-190: Integer Overflow or Wraparound class of overflow and loss of precision bugs, extended to float64/float32 issues.
Credit for the idea (and a finding a bug in the first implementation) goes to @ccoVeille, Please see https://github.com/ccoVeille/go-safecast for an different style API and implementation to pick whichever fits your style best (though I believe this implementation and API is better both in simplicity of principle (round trip check) and performance and api surface).
Please note that conversions from integer to float are suffering from CPU architecture differences and issues at the "edge" (max int) which are handled by Convert but you should use the new int only Conv/MustConv if possible, to avoid them.
Overview (`vendor/go.opentelemetry.io/otel/README.md`)
OpenTelemetry-Go
OpenTelemetry-Go is the Go implementation of OpenTelemetry.
It provides a set of APIs to directly measure performance and behavior of your software and send this data to observability platforms.
Project Status
| Signal | Status |
|---|---|
| Traces | Stable |
| Metrics | Stable |
| Logs | Beta^1 |
Progress and status specific to this repository is tracked in our
project boards
and
milestones.
Project versioning information and stability guarantees can be found in the
versioning documentation.
Compatibility
OpenTelemetry-Go ensures compatibility with the current supported versions of
the Go language:
Each major Go release is supported until there are two newer major releases.
For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was supported until the Go 1.8 release.
For versions of Go that are no longer supported upstream, opentelemetry-go will
stop ensuring compatibility with these versions in the following manner:
- A minor release of opentelemetry-go will be made to add support for the new
supported release of Go. - The following minor release of opentelemetry-go will remove compatibility
testing for the oldest (now archived upstream) version of Go. This, and
future, releases of opentelemetry-go may include features only supported by
the currently supported versions of Go.
Currently, this project supports the following environments.
| OS | Go Version | Architecture |
|---|---|---|
| Ubuntu | 1.26 | amd64 |
| Ubuntu | 1.25 | amd64 |
| Ubuntu | 1.26 | 386 |
| Ubuntu | 1.25 | 386 |
| Ubuntu | 1.26 | arm64 |
| Ubuntu | 1.25 | arm64 |
| macOS | 1.26 | amd64 |
| macOS | 1.25 | amd64 |
| macOS | 1.26 | arm64 |
| macOS | 1.25 | arm64 |
| Windows | 1.26 | amd64 |
| Windows | 1.25 | amd64 |
| Windows | 1.26 | 386 |
| Windows | 1.25 | 386 |
While this project should work for other systems, no compatibility guarantees
are made for those systems currently.
Getting Started
You can find a getting started guide on opentelemetry.io.
OpenTelemetry's goal is to provide a single set of APIs to capture distributed
traces and metrics from your application and send them to an observability
platform. This project allows you to do just that for applications written in
Go. There are two steps to this process: instrument your application, and
configure an exporter.
Instrumentation
To start capturing distributed traces and metric events from your application
it first needs to be instrumented. The easiest way to do this is by using an
instrumentation library for your code. Be sure to check out the officially
supported instrumentation
libraries.
If you need to extend the telemetry an instrumentation library provides or want
to build your own instrumentation for your application directly you will need
to use the
Go otel
package. The examples
are a good way to see some practical uses of this process.
Export
Now that your application is instrumented to collect telemetry, it needs an
export pipeline to send that telemetry to an observability platform.
All officially supported exporters for the OpenTelemetry project are contained in the exporters directory.
| Exporter | Logs | Metrics | Traces |
|---|---|---|---|
| OTLP | β | β | β |
| Prometheus | β | ||
| stdout | β | β | β |
| Zipkin | β |
Contributing
See the contributing documentation.
Overview (`vendor/go.uber.org/multierr/README.md`)
multierr [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
multierr allows combining one or more Go errors together.
Features
- Idiomatic:
multierr follows best practices in Go, and keeps your code idiomatic.- It keeps the underlying error type hidden,
allowing you to deal inerrorvalues exclusively. - It provides APIs to safely append into an error from a
deferstatement.
- It keeps the underlying error type hidden,
- Performant:
multierr is optimized for performance:- It avoids allocations where possible.
- It utilizes slice resizing semantics to optimize common cases
like appending into the same error object from a loop.
- Interoperable:
multierr interoperates with the Go standard library's error APIs seamlessly:- The
errors.Isanderrors.Asfunctions just work.
- The
- Lightweight:
multierr comes with virtually no dependencies.
Installation
go get -u go.uber.org/multierr@latestStatus
Stable: No breaking changes will be made before 2.0.
Released under the MIT License.
Overview (`vendor/go.uber.org/zap/README.md`)
:zap: zap
Installation
go get -u go.uber.org/zap
Note that zap only supports the two most recent minor versions of Go.
Quick Start
In contexts where performance is nice, but not critical, use theSugaredLogger. It's 4-10x faster than other structured logging
packages and includes both structured and printf-style APIs.
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)When performance and type safety are critical, use the Logger. It's even
faster than the SugaredLogger and allocates far less, but it only supports
structured logging.
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)See the documentation and FAQ for more details.
Performance
For applications that log in the hot path, reflection-based serialization and
string formatting are prohibitively expensive — they're CPU-intensive
and make many small allocations. Put differently, using encoding/json andfmt.Fprintf to log tons of interface{}s makes your application slow.
Zap takes a different approach. It includes a reflection-free, zero-allocation
JSON encoder, and the base Logger strives to avoid serialization overhead
and allocations wherever possible. By building the high-level SugaredLogger
on that foundation, zap lets users choose when they need to count every
allocation and when they'd prefer a more familiar, loosely typed API.
As measured by its own benchmarking suite, not only is zap more performant
than comparable structured logging packages — it's also faster than the
standard library. Like all benchmarks, take these with a grain of salt.1
Log a message and 10 fields:
| Package | Time | Time % to zap | Objects Allocated |
|---|---|---|---|
| :zap: zap | 656 ns/op | +0% | 5 allocs/op |
| :zap: zap (sugared) | 935 ns/op | +43% | 10 allocs/op |
| zerolog | 380 ns/op | -42% | 1 allocs/op |
| go-kit | 2249 ns/op | +243% | 57 allocs/op |
| slog (LogAttrs) | 2479 ns/op | +278% | 40 allocs/op |
| slog | 2481 ns/op | +278% | 42 allocs/op |
| apex/log | 9591 ns/op | +1362% | 63 allocs/op |
| log15 | 11393 ns/op | +1637% | 75 allocs/op |
| logrus | 11654 ns/op | +1677% | 79 allocs/op |
Log a message with a logger that already has 10 fields of context:
| Package | Time | Time % to zap | Objects Allocated |
|---|---|---|---|
| :zap: zap | 67 ns/op | +0% | 0 allocs/op |
| :zap: zap (sugared) | 84 ns/op | +25% | 1 allocs/op |
| zerolog | 35 ns/op | -48% | 0 allocs/op |
| slog | 193 ns/op | +188% | 0 allocs/op |
| slog (LogAttrs) | 200 ns/op | +199% | 0 allocs/op |
| go-kit | 2460 ns/op | +3572% | 56 allocs/op |
| log15 | 9038 ns/op | +13390% | 70 allocs/op |
| apex/log | 9068 ns/op | +13434% | 53 allocs/op |
| logrus | 10521 ns/op | +15603% | 68 allocs/op |
Log a static string, without any context or printf-style templating:
| Package | Time | Time % to zap | Objects Allocated |
|---|---|---|---|
| :zap: zap | 63 ns/op | +0% | 0 allocs/op |
| :zap: zap (sugared) | 81 ns/op | +29% | 1 allocs/op |
| zerolog | 32 ns/op | -49% | 0 allocs/op |
| standard library | 124 ns/op | +97% | 1 allocs/op |
| slog | 196 ns/op | +211% | 0 allocs/op |
| slog (LogAttrs) | 200 ns/op | +217% | 0 allocs/op |
| go-kit | 213 ns/op | +238% | 9 allocs/op |
| apex/log | 771 ns/op | +1124% | 5 allocs/op |
| logrus | 1439 ns/op | +2184% | 23 allocs/op |
| log15 | 2069 ns/op | +3184% | 20 allocs/op |
Development Status: Stable
All APIs are finalized, and no breaking changes will be made in the 1.x series
of releases. Users of semver-aware dependency management systems should pin
zap to ^1.
Contributing
We encourage and support an active, healthy community of contributors —
including you! Details are in the contribution guide and
the code of conduct. The zap maintainers keep an eye on
issues and pull requests, but you can also report any negative conduct to
[email protected]. That email list is a private, safe space; even the zap
maintainers don't have access, so don't hesitate to hold us to a high
standard.
Released under the MIT License.
1 In particular, keep in mind that we may be
benchmarking against slightly older versions of other packages. Versions are
pinned in the benchmarks/go.mod file. β©
Overview (`vendor/google.golang.org/grpc/README.md`)
gRPC-Go
The Go implementation of gRPC: A high performance, open source, general
RPC framework that puts mobile and HTTP/2 first. For more information see the
Go gRPC docs, or jump directly into the quick start.
Prerequisites
Installation
Simply add the following import to your code, and then go [build|run|test]
will automatically fetch the necessary dependencies:
import "google.golang.org/grpc"Note: If you are trying to access
grpc-gofrom China, see the
FAQ below.
Learn more
- Go gRPC docs, which include a quick start and API
reference among other resources - Low-level technical docs from this repository
- Performance benchmark
- Examples
- Contribution guidelines
FAQ
I/O Timeout Errors
The golang.org domain may be blocked from some countries. go get usually
produces an error like the following when this happens:
$ go get -u google.golang.org/grpc
package google.golang.org/grpc: unrecognized import path "google.golang.org/grpc" (https fetch: Get https://google.golang.org/grpc?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)To build Go code, there are several options:
Set up a VPN and access google.golang.org through that.
With Go module support: it is possible to use the
replacefeature ofgo modto create aliases for golang.org packages. In your project's directory:shgo mod edit -replace=google.golang.org/grpc=github.com/grpc/grpc-go@latest go mod tidy go mod vendor go build -mod=vendorAgain, this will need to be done for all transitive dependencies hosted on
golang.org as well. For details, refer to golang/go issue
#28652.
Compiling error, undefined: grpc.SupportPackageIsVersion
Please update to the latest version of gRPC-Go usinggo get google.golang.org/grpc.
How to turn on logging
The default logger is controlled by environment variables. Turn everything on
like this:
$ export GRPC_GO_LOG_VERBOSITY_LEVEL=99
$ export GRPC_GO_LOG_SEVERITY_LEVEL=infoThe RPC failed with error `"code = Unavailable desc = transport is closing"`
This error means the connection the RPC is using was closed, and there are many
possible reasons, including:
- mis-configured transport credentials, connection failed on handshaking
- bytes disrupted, possibly by a proxy in between
- server shutdown
- Keepalive parameters caused connection shutdown, for example if you have
configured your server to terminate connections regularly to trigger DNS
lookups.
If this is the case, you may want to increase your
MaxConnectionAgeGrace,
to allow longer RPC calls to finish.
It can be tricky to debug this because the error happens on the client side but
the root cause of the connection being closed is on the server side. Turn on
logging on both client and server, and see if there are any transport
errors.
Overview (`vendor/gopkg.in/yaml.v2/README.md`)
YAML support for the Go language
Introduction
The yaml package enables Go programs to comfortably encode and decode YAML
values. It was developed within Canonical as
part of the juju project, and is based on a
pure Go port of the well-known libyaml
C library to parse and generate YAML data quickly and reliably.
Compatibility
The yaml package supports most of YAML 1.1 and 1.2, including support for
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
implemented, and base-60 floats from YAML 1.1 are purposefully not
supported since they're a poor design and are gone in YAML 1.2.
Installation and usage
The import path for the package is gopkg.in/yaml.v2.
To install it, run:
go get gopkg.in/yaml.v2API documentation
If opened in a browser, the import path itself leads to the API documentation:
API stability
The package API for yaml v2 will remain stable as described in gopkg.in.
License
The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
Example
package main
import (
"fmt"
"log"
"gopkg.in/yaml.v2"
)
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
t := T{}
err := yaml.Unmarshal([]byte(data), &t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t:\n%v\n\n", t)
d, err := yaml.Marshal(&t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t dump:\n%s\n\n", string(d))
m := make(map[interface{}]interface{})
err = yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)
d, err = yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))
}This example will generate the following output:
--- t:
{Easy! {2 [3 4]}}
--- t dump:
a: Easy!
b:
c: 2
d: [3, 4]
--- m:
map[a:Easy! b:map[c:2 d:[3 4]]]
--- m dump:
a: Easy!
b:
c: 2
d:
- 3
- 4Overview (`vendor/k8s.io/code-generator/README.md`)
β οΈ This is an automatically published staged repository for Kubernetes.
Contributions, including issues and pull requests, should be made to the main Kubernetes repository: https://github.com/kubernetes/kubernetes.
This repository is read-only for importing, and not used for direct contributions.
See CONTRIBUTING.md for more details.
code-generator
Golang code-generators used to implement Kubernetes-style API types.
Purpose
These code-generators can be used
- in the context of CustomResourceDefinition to build native, versioned clients,
informers and other helpers - in the context of User-provider API Servers to build conversions between internal and versioned types, defaulters, protobuf codecs,
internal and versioned clients and informers.
Resources
- The example sample controller shows a code example of a controller that uses the clients, listers and informers generated by this library.
- The article Kubernetes Deep Dive: Code Generation for CustomResources gives a step by step instruction on how to use this library.
Usage
The examples above are dated. The current recommended script to use is kube_codegen.sh.
Compatibility
HEAD of this repo will match HEAD of k8s.io/apiserver, k8s.io/apimachinery, and k8s.io/client-go.
Where does it come from?
code-generator is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/code-generator.
Code changes are made in that location, merged into k8s.io/kubernetes and later synced here.
Overview (`vendor/k8s.io/klog/README.md`)
klog
klog is a permanent fork of https://github.com/golang/glog.
Why was klog created?
The decision to create klog was one that wasn't made lightly, but it was necessary due to some
drawbacks that are present in glog. Ultimately, the fork was created due to glog not being under active development; this can be seen in the glog README:
The code in this repo [...] is not itself under development
This makes us unable to solve many use cases without a fork. The factors that contributed to needing feature development are listed below:
glogpresents a lot "gotchas" and introduces challenges in containerized environments, all of which aren't well documented.glogdoesn't provide an easy way to test logs, which detracts from the stability of software using it- A long term goal is to implement a logging interface that allows us to add context, change output format, etc.
Historical context is available here:
- https://github.com/kubernetes/kubernetes/issues/61006
- https://github.com/kubernetes/kubernetes/issues/70264
- https://groups.google.com/forum/#!msg/kubernetes-sig-architecture/wCWiWf3Juzs/hXRVBH90CgAJ
- https://groups.google.com/forum/#!msg/kubernetes-dev/7vnijOMhLS0/1oRiNtigBgAJ
How to use klog
- Replace imports for
github.com/golang/glogwithk8s.io/klog - Use
klog.InitFlags(nil)explicitly for initializing global flags as we no longer useinit()method to register the flags - You can now use
log-fileinstead oflog-dirfor logging to a single file (Seeexamples/log_file/usage_log_file.go) - If you want to redirect everything logged using klog somewhere else (say syslog!), you can use
klog.SetOutput()method and supply aio.Writer. (Seeexamples/set_output/usage_set_output.go) - For more logging conventions (See Logging Conventions)
Coexisting with glog
This package can be used side by side with glog. This example shows how to initialize and syncronize flags from the global flag.CommandLine FlagSet. In addition, the example makes use of stderr as combined output by setting alsologtostderr (or logtostderr) to true.
Community, discussion, contribution, and support
Learn how to engage with the Kubernetes community on the community page.
You can reach the maintainers of this project at:
Code of conduct
Participation in the Kubernetes community is governed by the Kubernetes Code of Conduct.
glog
Leveled execution logs for Go.
This is an efficient pure Go implementation of leveled logs in the
manner of the open source C++ package
https://github.com/google/glog
By binding methods to booleans it is possible to use the log package
without paying the expense of evaluating the arguments to the log.
Through the -vmodule flag, the package also provides fine-grained
control over logging at the file level.
The comment from glog.go introduces the ideas:
Package glog implements logging analogous to the Google-internal
C++ INFO/ERROR/V setup. It provides functions Info, Warning,
Error, Fatal, plus formatting variants such as Infof. It
also provides V-style logging controlled by the -v and
-vmodule=file=2 flags.
Basic examples:
glog.Info("Prepare to repel boarders")
glog.Fatalf("Initialization failed: %s", err)
See the documentation for the V function for an explanation
of these examples:
if glog.V(2) {
glog.Info("Starting transaction...")
}
glog.V(2).Infoln("Processed", nItems, "elements")The repository contains an open source version of the log package
used inside Google. The master copy of the source lives inside
Google, not here. The code in this repo is for export only and is not itself
under development. Feature requests will be ignored.
Send bug reports to [email protected].
Overview (`vendor/knative.dev/hack/README.md`)
knative.dev/hack
hack is a collection of scripts used to bootstrap CI processes and other vital
entrypoint functionality.
Contributing
If you are interested in contributing to Knative, take a look at CLOTRIBUTOR
for a list of help wanted issues across the project.
Using the `presubmit-tests.sh` helper script
This is a helper script to run the presubmit tests. To use it:
Source this script:
bashsource "$(go run knative.dev/hack/cmd/script presubmit-tests.sh)"[optional] Define the function
build_tests(). If you don't define this
function, the default action for running the build tests is to:- run
go buildon the entire repo - run
hack/verify-codegen.sh(if it exists) - check licenses in all go packages
- run
[optional] Customize the default build test runner, if you're using it. Set
the following environment variables if the default values don't fit your
needs:PRESUBMIT_TEST_FAIL_FAST: Fail the presubmit test immediately if a test
fails, defaults to 0 (false).
[optional] Define the functions
pre_build_tests()and/orpost_build_tests(). These functions will be called before or after the
build tests (either your custom one or the default action) and will cause the
test to fail if they don't return success.[optional] Define the function
unit_tests(). If you don't define this
function, the default action for running the unit tests is to run all go
tests in the repo.[optional] Define the functions
pre_unit_tests()and/orpost_unit_tests(). These functions will be called before or after the unit
tests (either your custom one or the default action) and will cause the test
to fail if they don't return success.[optional] Define the function
integration_tests(). If you don't define
this function, the default action for running the integration tests is to run
all run all./test/e2e-*tests.shscripts, in sequence.[optional] Define the functions
pre_integration_tests()and/orpost_integration_tests(). These functions will be called before or after
the integration tests (either your custom one or the default action) and will
cause the test to fail if they don't return success.Call the
main()function passing"$@"(with quotes).
Running the script without parameters, or with the --all-tests flag causes all
tests to be executed, in the right order (i.e., build, then unit, then
integration tests).
Use the flags --build-tests, --unit-tests and --integration-tests to run a
specific set of tests.
To run specific programs as a test, use the --run-test flag, and provide the
program as the argument. If arguments are required for the program, pass
everything as a single quotes argument. For example,./presubmit-tests.sh --run-test "test/my/test data". This flag can be used
repeatedly, and each one will be ran in sequential order.
The script will automatically skip all presubmit tests for PRs where all changed
files are exempt of tests (e.g., a PR changing only the OWNERS file).
Also, for PRs touching only markdown files, the unit and integration tests are
skipped.
Sample presubmit test script
source "$(go run knative.dev/hack/cmd/script presubmit-tests.sh)"
function post_build_tests() {
echo "Cleaning up after build tests"
rm -fr ./build-cache
}
function unit_tests() {
make -C tests test
}
function pre_integration_tests() {
echo "Cleaning up before integration tests"
rm -fr ./staging-area
}
# We use the default integration test runner.
main "$@"Using the `e2e-tests.sh` helper script
This is a helper script for Knative E2E test scripts. To use it:
[optional] Customize the test cluster. Pass the flags as described
here to theinitializefunction
call if the default values don't fit your needs.Source the script:
bashsource "$(go run knative.dev/hack/cmd/script e2e-tests.sh)"[optional] Write the
knative_setup()function, which will set up your
system under test (e.g., Knative Serving).[optional] Write the
knative_teardown()function, which will tear down your
system under test (e.g., Knative Serving).[optional] Write the
test_setup()function, which will set up the test
resources.[optional] Write the
test_teardown()function, which will tear down the
test resources.[optional] Write the
cluster_setup()function, which will set up any
resources before the test cluster is created.[optional] Write the
cluster_teardown()function, which will tear down any
resources after the test cluster is destroyed.[optional] Write the
dump_extra_cluster_state()function. It will be called
when a test fails, and can dump extra information about the current state of
the cluster (typically usingkubectl).[optional] Write the
on_successfunction. It will be called when a test succeeds[optional] Write the
on_failurefunction. It will be called when a test fails[optional] Write the
parse_flags()function. It will be called whenever an
unrecognized flag is passed to the script, allowing you to define your own
flags. The function must return 0 if the flag is unrecognized, or the number
of items to skip in the command line if the flag was parsed successfully. For
example, return 1 for a simple flag, and 2 for a flag with a parameter.Call the
initialize()function passing"$@".Write logic for the end-to-end tests. Run all go tests using
go_test_e2e()
(orreport_go_test()if you need a more fine-grained control) and callfail_test()orsuccess()if any of them failed. The environment variableKO_DOCKER_REPOandE2E_PROJECT_IDwill be set according to the test
cluster.
Notes:
Calling your script without arguments will create a new cluster in your
current GCP project and run the tests against it.Calling your script with
--run-testsand the variableKO_DOCKER_REPOset
will immediately start the tests against the cluster currently configured forkubectl.By default
knative_teardown()andtest_teardown()will be called after
the tests finish, use--skip-teardownsif you don't want them to be called.By default Google Kubernetes Engine telemetry to Cloud Logging and Monitoring is disabled.
This can be enabled by settingENABLE_GKE_TELEMETRYtotrue.By default Spot Worker nodes are disabled. This can be enabled by setting
ENABLE_PREEMPTIBLE_NODES
totrue.
Sample end-to-end test script
This script will test that the latest Knative Serving nightly release works. It
defines a special flag (--no-knative-wait) that causes the script not to wait
for Knative Serving to be up before running the tests. It also requires that the
test cluster is created in a specific region, us-west2.
source "$(go run knative.dev/hack/cmd/script e2e-tests.sh)"
function knative_setup() {
start_latest_knative_serving
if (( WAIT_FOR_KNATIVE )); then
wait_until_pods_running knative-serving || fail_test "Knative Serving not up"
fi
}
function parse_flags() {
if [[ "$1" == "--no-knative-wait" ]]; then
WAIT_FOR_KNATIVE=0
return 1
fi
return 0
}
WAIT_FOR_KNATIVE=1
# This test requires a cluster in LA
initialize $@ --region=us-west2
# TODO: use go_test_e2e to run the tests.
kubectl get pods || fail_test
successUsing the `performance-tests.sh` helper script
This is a helper script for Knative performance test scripts. In combination
with specific Prow jobs, it can automatically manage the environment for running
benchmarking jobs for each repo. To use it:
Source the script:
bashsource "$(go run knative.dev/hack/cmd/script performance-tests.sh)"[optional] Customize GCP project settings for the benchmarks. Set the
following environment variables if the default value doesn't fit your needs:PROJECT_NAME: GCP project name for keeping the clusters that run the
benchmarks. Defaults toknative-performance.SERVICE_ACCOUNT_NAME: Service account name for controlling GKE clusters
and interacting with Mako server. It MUST
haveKubernetes Engine AdminandStorage Adminrole, and be
allowed by
Mako admin. Defaults tomako-job.
[optional] Customize root path of the benchmarks. This root folder should
contain and only contain all benchmarks you want to run continuously. Set the
following environment variable if the default value doesn't fit your needs:BENCHMARK_ROOT_PATH: Benchmark root path, defaults totest/performance/benchmarks. Each repo can decide which folder to put its
benchmarks in, and override this environment variable to be the path of
that folder.
[optional] Write the
update_knativefunction, which will update your system
under test (e.g. Knative Serving).[optional] Write the
update_benchmarkfunction, which will update the
underlying resources for the benchmark (usually Knative resources and
Kubernetes cronjobs for benchmarking). This function accepts a parameter,
which is the benchmark name in the current repo.Call the
main()function with all parameters (e.g.$@).
Sample performance test script
This script will update Knative serving and the given benchmark.
source "$(go run knative.dev/hack/cmd/script performance-tests.sh)"
function update_knative() {
echo ">> Updating serving"
ko apply -f config/ || abort "failed to apply serving"
}
function update_benchmark() {
echo ">> Updating benchmark $1"
ko apply -f ${BENCHMARK_ROOT_PATH}/$1 || abort "failed to apply benchmark $1"
}
main $@Using the `release.sh` helper script
This is a helper script for Knative release scripts. To use it:
Source the script:
bashsource "$(go run knative.dev/hack/cmd/script release.sh)"[optional] By default, the release script will run
./test/presubmit-tests.shas the release validation tests. If you need to
run something else, set the environment variableVALIDATION_TESTSto the
executable to run.Write logic for building the release in a function named
build_release().
Set the environment variableARTIFACTS_TO_PUBLISHto the list of files
created, space separated. Use the following boolean (0 is false, 1 is true)
and string environment variables for the logic:RELEASE_VERSION: contains the release version if--versionwas passed.
This also overrides the value of theTAGvariable asv<version>.RELEASE_BRANCH: contains the release branch if--branchwas passed.
Otherwise it's empty andmainHEAD will be considered the release
branch.RELEASE_NOTES: contains the filename with the release notes if--release-noteswas passed. The release notes is a simple markdown file.RELEASE_GCS_BUCKET: contains the GCS bucket name to store the manifests
if--release-gcswas passed, otherwise the default valueknative-nightly/<repo>will be used. It is empty if--publishwas not
passed.RELEASE_DIR: contains the directory to store the manifests if--release-dirwas passed. Defaults to empty value, but if--nopublish
was passed then points to the repository root directory.BUILD_COMMIT_HASH: the commit short hash for the current repo. If the
current git tree is dirty, it will have-dirtyappended to it.BUILD_YYYYMMDD: current UTC date inYYYYMMDDformat.BUILD_TIMESTAMP: human-readable UTC timestamp inYYYY-MM-DD HH:MM:SS
format.BUILD_TAG: a tag in the formv$BUILD_YYYYMMDD-$BUILD_COMMIT_HASH.KO_DOCKER_REPO: contains the GCR to store the images if--release-gcr
was passed, otherwise the default valuegcr.io/knative-nightlywill be
used. It is set toko.localif--publishwas not passed.SKIP_TESTS: true if--skip-testswas passed. This is handled
automatically.TAG_RELEASE: true if--tag-releasewas passed. In this case, the
environment variableTAGwill contain the release tag in the formv$BUILD_TAG.PUBLISH_RELEASE: true if--publishwas passed. In this case, the
environment variableKO_FLAGSwill be updated with the-Loption andTAGwill contain the release tag in the formv$RELEASE_VERSION.PUBLISH_TO_GITHUB: true if--version,--branchand--publish-releasewere passed.
All boolean environment variables default to false for safety.
All environment variables above, except
KO_FLAGS, are marked read-only oncemain()is called (see below).Call the
main()function passing"$@"(with quotes).
Sample release script
source "$(go run knative.dev/hack/cmd/script release.sh)"
function build_release() {
# config/ contains the manifests
ko resolve ${KO_FLAGS} -f config/ > release.yaml
ARTIFACTS_TO_PUBLISH="release.yaml"
}
main "$@"Origins of `hack`
When Kubernetes was first getting started, someone was trying to introduce some
quick shell scripts and land them into the ./scripts folder. But there was one
that opposed this: Ville Aikas. The compromise was to put those quick scripts in
a folder called hack to remind users and developers that there is likely a
better way to perform the task you are attempting that is not using a shell
script, like a tested python script.
"I was like fine, put them in hack not scripts, cause they are hacks." - Ville Aikas
Overview (`vendor/sigs.k8s.io/json/README.md`)
sigs.k8s.io/json
Introduction
This library is a subproject of sig-api-machinery.
It provides case-sensitive, integer-preserving JSON unmarshaling functions based on encoding/json Unmarshal().
Compatibility
The UnmarshalCaseSensitivePreserveInts() function behaves like encoding/json#Unmarshal() with the following differences:
- JSON object keys are treated case-sensitively.
Object keys must exactly match json tag names (for tagged struct fields)
or struct field names (for untagged struct fields). - JSON integers are unmarshaled into
interface{}fields as anint64instead of afloat64when possible, falling back tofloat64on any parse or overflow error. - Syntax errors do not return an
encoding/json*SyntaxErrorerror.
Instead, they return an error which can be passed toSyntaxErrorOffset()to obtain an offset.
Additional capabilities
The UnmarshalStrict() function decodes identically to UnmarshalCaseSensitivePreserveInts(),
and also returns non-fatal strict errors encountered while decoding:
- Duplicate fields encountered
- Unknown fields encountered
Community, discussion, contribution, and support
You can reach the maintainers of this project via the
sig-api-machinery mailing list / channels.
Code of conduct
Participation in the Kubernetes community is governed by the Kubernetes Code of Conduct.
Overview (`vendor/sigs.k8s.io/randfill/README.md`)
randfill
randfill is a library for populating go objects with random values.
This is a fork of github.com/google/gofuzz, which was archived.
NOTE: This repo is supported only for use within Kubernetes. It is not our
intention to support general use. That said, if it works for you, that's
great! If you have a problem, please feel free to file an issue, but be aware
that it may not be a priority for us to fix it unless it is affecting
Kubernetes. PRs are welcome, within reason.
This is useful for testing:
- Do your project's objects really serialize/unserialize correctly in all cases?
- Is there an incorrectly formatted object that will cause your project to panic?
Import with import "sigs.k8s.io/randfill"
You can use it on single variables:
f := randfill.New()
var myInt int
f.Fill(&myInt) // myInt gets a random value.You can use it on maps:
f := randfill.New().NilChance(0).NumElements(1, 1)
var myMap map[ComplexKeyType]string
f.Fill(&myMap) // myMap will have exactly one element.Customize the chance of getting a nil pointer:
f := randfill.New().NilChance(.5)
var fancyStruct struct {
A, B, C, D *string
}
f.Fill(&fancyStruct) // About half the pointers should be set.You can even customize the randomization completely if needed:
type MyEnum string
const (
A MyEnum = "A"
B MyEnum = "B"
)
type MyInfo struct {
Type MyEnum
AInfo *string
BInfo *string
}
f := randfill.New().NilChance(0).Funcs(
func(e *MyInfo, c randfill.Continue) {
switch c.Intn(2) {
case 0:
e.Type = A
c.Fill(&e.AInfo)
case 1:
e.Type = B
c.Fill(&e.BInfo)
}
},
)
var myObject MyInfo
f.Fill(&myObject) // Type will correspond to whether A or B info is set.See more examples in example_test.go.
dvyukov/go-fuzz integration
You can use this library for easier go-fuzzing.
go-fuzz provides the user a byte-slice, which should be converted to different inputs
for the tested function. This library can help convert the byte slice. Consider for
example a fuzz test for a the function mypackage.MyFunc that takes an int arguments:
// +build gofuzz
package mypackage
import "sigs.k8s.io/randfill"
func Fuzz(data []byte) int {
var i int
randfill.NewFromGoFuzz(data).Fill(&i)
MyFunc(i)
return 0
}Happy testing!
Overview (`vendor/sigs.k8s.io/yaml/README.md`)
YAML marshaling and unmarshaling support for Go
kubernetes-sigs/yaml is a permanent fork of ghodss/yaml.
Introduction
A wrapper around go-yaml designed to enable a better way of handling YAML when marshaling to and from structs.
In short, this library first converts YAML to JSON using go-yaml and then uses json.Marshal and json.Unmarshal to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods MarshalJSON and UnmarshalJSON unlike go-yaml. For a detailed overview of the rationale behind this method, see this blog post.
Compatibility
This package uses go-yaml and therefore supports everything go-yaml supports.
Caveats
Caveat #1: When using yaml.Marshal and yaml.Unmarshal, binary data should NOT be preceded with the !!binary YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the !!binary tag and decode the base64 in your code (e.g. in the custom JSON methods MarshalJSON and UnmarshalJSON). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example:
BAD:
exampleKey: !!binary gIGC
GOOD:
exampleKey: gIGC
... and decode the base64 data in your code.Caveat #2: When using YAMLToJSON directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in Unmarshal as well since you can't unmarshal map keys anyways since struct fields can't be keys.
Installation and usage
To install, run:
$ go get sigs.k8s.io/yamlAnd import using:
import "sigs.k8s.io/yaml"Usage is very similar to the JSON library:
package main
import (
"fmt"
"sigs.k8s.io/yaml"
)
type Person struct {
Name string `json:"name"` // Affects YAML field names too.
Age int `json:"age"`
}
func main() {
// Marshal a Person struct to YAML.
p := Person{"John", 30}
y, err := yaml.Marshal(p)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(y))
/* Output:
age: 30
name: John
*/
// Unmarshal the YAML back into a Person struct.
var p2 Person
err = yaml.Unmarshal(y, &p2)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(p2)
/* Output:
{John 30}
*/
}yaml.YAMLToJSON and yaml.JSONToYAML methods are also available:
package main
import (
"fmt"
"sigs.k8s.io/yaml"
)
func main() {
j := []byte(`{"name": "John", "age": 30}`)
y, err := yaml.JSONToYAML(j)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(y))
/* Output:
age: 30
name: John
*/
j2, err := yaml.YAMLToJSON(y)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(j2))
/* Output:
{"age":30,"name":"John"}
*/
}Overview (`vendor/cloud.google.com/go/auth/README.md`)
Google Auth Library for Go
Install
go get cloud.google.com/go/auth@latestUsage
The most common way this library is used is transitively, by default, from any
of our Go client libraries.
Notable use-cases
- To create a credential directly please see examples in the
credentials
package. - To create a authenticated HTTP client please see examples in the
httptransport
package. - To create a authenticated gRPC connection please see examples in the
grpctransport
package. - To create an ID token please see examples in the
idtoken
package.
Contributing
Contributions are welcome. Please, see the
CONTRIBUTING
document for details.
Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms.
See Contributor Code of Conduct
for more information.
Overview (`vendor/cloud.google.com/go/iam/README.md`)
Identity and Access Management (IAM) API
Go Client Library for Identity and Access Management (IAM) API.
Install
go get cloud.google.com/go/iamStability
The stability of this module is indicated by SemVer.
However, a v1+ module may have breaking changes in two scenarios:
- Packages with
alphaorbetain the import path - The GoDoc has an explicit stability disclaimer (for example, for an experimental feature).
Which package to use?
Generated client library surfaces can be found in packages whose import path
ends in .../apivXXX. The XXX could be something like 1 or 2 in the case
of a stable service backend or may be like 1beta2 or 2beta in the case of a
more experimental service backend. Because of this fact, a given module can have
multiple clients for different service backends. In these cases it is generally
recommended to use clients with stable service backends, with import suffixes likeapiv1, unless you need to use features that are only present in a beta backend
or there is not yet a stable backend available.
Google Cloud Samples
To browse ready to use code samples check Google Cloud Samples.
Go Version Support
See the Go Versions Supported
section in the root directory's README.
Authorization
See the Authorization
section in the root directory's README.
Contributing
Contributions are welcome. Please, see the CONTRIBUTING
document for details.
Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms. See
Contributor Code of Conduct
for more information.
Overview (`vendor/cloud.google.com/go/longrunning/README.md`)
Long Running Operations API
Go Client Library for Long Running Operations API.
Install
go get cloud.google.com/go/longrunningStability
The stability of this module is indicated by SemVer.
However, a v1+ module may have breaking changes in two scenarios:
- Packages with
alphaorbetain the import path - The GoDoc has an explicit stability disclaimer (for example, for an experimental feature).
Which package to use?
Generated client library surfaces can be found in packages whose import path
ends in .../apivXXX. The XXX could be something like 1 or 2 in the case
of a stable service backend or may be like 1beta2 or 2beta in the case of a
more experimental service backend. Because of this fact, a given module can have
multiple clients for different service backends. In these cases it is generally
recommended to use clients with stable service backends, with import suffixes likeapiv1, unless you need to use features that are only present in a beta backend
or there is not yet a stable backend available.
Google Cloud Samples
To browse ready to use code samples check Google Cloud Samples.
Go Version Support
See the Go Versions Supported
section in the root directory's README.
Authorization
See the Authorization
section in the root directory's README.
Contributing
Contributions are welcome. Please, see the CONTRIBUTING
document for details.
Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms. See
Contributor Code of Conduct
for more information.
Overview (`vendor/github.com/42wim/httpsig/README.md`)
httpsig
Forked from https://github.com/go-fed/httpsig
HTTP Signatures made simple
go get github.com/42wim/httpsig
Implementation of HTTP Signatures.
Supports many different combinations of MAC, HMAC signing of hash, or RSA
signing of hash schemes. Its goals are:
- Have a very simple interface for signing and validating
- Support a variety of signing algorithms and combinations
- Support setting either headers (
AuthorizationorSignature) - Remaining flexible with headers included in the signing string
- Support both HTTP requests and responses
- Explicitly not support known-cryptographically weak algorithms
- Support automatic signing and validating Digest headers
How to use
import "github.com/42wim/httpsig"
Signing
Signing a request or response requires creating a new Signer and using it:
func sign(privateKey crypto.PrivateKey, pubKeyId string, r *http.Request) error {
prefs := []httpsig.Algorithm{httpsig.RSA_SHA512, httpsig.RSA_SHA256}
digestAlgorithm := DigestSha256
// The "Date" and "Digest" headers must already be set on r, as well as r.URL.
headersToSign := []string{httpsig.RequestTarget, "date", "digest"}
signer, chosenAlgo, err := httpsig.NewSigner(prefs, digestAlgorithm, headersToSign, httpsig.Signature)
if err != nil {
return err
}
// To sign the digest, we need to give the signer a copy of the body...
// ...but it is optional, no digest will be signed if given "nil"
body := ...
// If r were a http.ResponseWriter, call SignResponse instead.
return signer.SignRequest(privateKey, pubKeyId, r, body)
}Signers are not safe for concurrent use by goroutines, so be sure to guard
access:
type server struct {
signer httpsig.Signer
mu *sync.Mutex
}
func (s *server) handlerFunc(w http.ResponseWriter, r *http.Request) {
privateKey := ...
pubKeyId := ...
// Set headers and such on w
s.mu.Lock()
defer s.mu.Unlock()
// To sign the digest, we need to give the signer a copy of the response body...
// ...but it is optional, no digest will be signed if given "nil"
body := ...
err := s.signer.SignResponse(privateKey, pubKeyId, w, body)
if err != nil {
...
}
...
}The pubKeyId will be used at verification time.
Verifying
Verifying requires an application to use the pubKeyId to both retrieve the key
needed for verification as well as determine the algorithm to use. Use aVerifier:
func verify(r *http.Request) error {
verifier, err := httpsig.NewVerifier(r)
if err != nil {
return err
}
pubKeyId := verifier.KeyId()
var algo httpsig.Algorithm = ...
var pubKey crypto.PublicKey = ...
// The verifier will verify the Digest in addition to the HTTP signature
return verifier.Verify(pubKey, algo)
}Verifiers are not safe for concurrent use by goroutines, but since they are
constructed on a per-request or per-response basis it should not be a common
restriction.
Overview (`vendor/github.com/Masterminds/goutils/README.md`)
GoUtils
GoUtils provides users with utility functions to manipulate strings in various ways. It is a Go implementation of some
string manipulation libraries of Java Apache Commons. GoUtils includes the following Java Apache Commons classes:
- WordUtils
- RandomStringUtils
- StringUtils (partial implementation)
Installation
If you have Go set up on your system, from the GOPATH directory within the command line/terminal, enter this:
go get github.com/Masterminds/goutilsIf you do not have Go set up on your system, please follow the Go installation directions from the documenation, and then follow the instructions above to install GoUtils.
Documentation
GoUtils doc is available here:
Usage
The code snippets below show examples of how to use GoUtils. Some functions return errors while others do not. The first instance below, which does not return an error, is the Initials function (located within the wordutils.go file).
package main
import (
"fmt"
"github.com/Masterminds/goutils"
)
func main() {
// EXAMPLE 1: A goutils function which returns no errors
fmt.Println (goutils.Initials("John Doe Foo")) // Prints out "JDF"
}Some functions return errors mainly due to illegal arguements used as parameters. The code example below illustrates how to deal with function that returns an error. In this instance, the function is the Random function (located within the randomstringutils.go file).
package main
import (
"fmt"
"github.com/Masterminds/goutils"
)
func main() {
// EXAMPLE 2: A goutils function which returns an error
rand1, err1 := goutils.Random (-1, 0, 0, true, true)
if err1 != nil {
fmt.Println(err1) // Prints out error message because -1 was entered as the first parameter in goutils.Random(...)
} else {
fmt.Println(rand1)
}
}License
GoUtils is licensed under the Apache License, Version 2.0. Please check the LICENSE.txt file or visit http://www.apache.org/licenses/LICENSE-2.0 for a copy of the license.
Issue Reporting
Make suggestions or report issues using the Git issue tracker: https://github.com/Masterminds/goutils/issues
Website
Overview (`vendor/github.com/Microsoft/go-winio/README.md`)
go-winio [](https://github.com/microsoft/go-winio/actions/workflows/ci.yml)
This repository contains utilities for efficiently performing Win32 IO operations in
Go. Currently, this is focused on accessing named pipes and other file handles, and
for using named pipes as a net transport.
This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
newer operating systems. This is similar to the implementation of network sockets in Go's net
package.
Please see the LICENSE file for licensing information.
Contributing
This project welcomes contributions and suggestions.
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that
you have the right to, and actually do, grant us the rights to use your contribution.
For details, visit Microsoft CLA.
When you submit a pull request, a CLA-bot will automatically determine whether you need to
provide a CLA and decorate the PR appropriately (e.g., label, comment).
Simply follow the instructions provided by the bot.
You will only need to do this once across all repos using our CLA.
Additionally, the pull request pipeline requires the following steps to be performed before
mergining.
Code Sign-Off
We require that contributors sign their commits using git commit --signoff
to certify they either authored the work themselves or otherwise have permission to use it in this project.
A range of commits can be signed off using git rebase --signoff.
Please see the developer certificate for more info,
as well as to make sure that you can attest to the rules listed.
Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
Linting
Code must pass a linting stage, which uses golangci-lint.
The linting settings are stored in .golangci.yaml, and can be run
automatically with VSCode by adding the following to your workspace or folder settings:
"go.lintTool": "golangci-lint",
"go.lintOnSave": "package",Additional editor integrations options are also available.
Alternatively, golangci-lint can be installed locally and run from the repo root:
# use . or specify a path to only lint a package
# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0"
> golangci-lint run ./...Go Generate
The pipeline checks that auto-generated code, via go generate, are up to date.
This can be done for the entire repo:
> go generate ./...Code of Conduct
This project has adopted the Microsoft Open Source Code of Conduct.
For more information see the Code of Conduct FAQ or
contact [email protected] with any additional questions or comments.
Special Thanks
Thanks to natefinch for the inspiration for this library.
See npipe for another named pipe implementation.
Overview (`vendor/github.com/aws/smithy-go/README.md`)
Smithy Go
Smithy code generators for Go and the accompanying smithy-go runtime.
The smithy-go runtime requires a minimum version of Go 1.24.
WARNING: All interfaces are subject to change.
:warning: Client codegen is unstable
The client code generator in this repository powers the aws-sdk-go-v2.
Arbitrary client generation, while possible, is in an early stage of
development:
- Generated clients are missing certain features that were originally
implemented SDK-side (e.g. retries) - There may be bugs
- The public APIs of generated clients may be unstable
If you are interested in using the client code generators, we encourage you to
experiment and share any feedback with us in an issue.
Plugins
This repository implements the following Smithy build plugins:
| ID | GAV prefix | Description |
|---|---|---|
go-codegen |
software.amazon.smithy.go:smithy-go-codegen |
Implements Go client code generation for Smithy models. |
go-server-codegen |
software.amazon.smithy.go:smithy-go-codegen |
Implements Go server code generation for Smithy models. |
go-shape-codegen |
software.amazon.smithy.go:smithy-go-codegen |
Implements Go shape code generation (types only) for Smithy models. |
`go-codegen`
Configuration
GoSettings
contains all of the settings enabled from smithy-build.json and helper
methods and types. The up-to-date list of top-level properties enabled forgo-client-codegen can be found in GoSettings::from().
| Setting | Type | Required | Description |
|---|---|---|---|
service |
string | yes | The Shape ID of the service for which to generate the client. |
module |
string | yes | Name of the module in generated.json (and go.mod if generateGoMod is enabled) and doc.go. |
generateGoMod |
boolean | Whether to generate a default go.mod file. The default value is false. |
|
goDirective |
string | Go directive of the module. The default value is the minimum supported Go version. |
Supported protocols
The protocol a client uses is configured by the Protocol field on a client'sOptions. The SDK will configure a default based on the protocol traits
applied to the modeled service.
| Protocol | Notes |
|---|---|
smithy.protocols#rpcv2Cbor |
|
aws.protocols#restJson1 |
|
aws.protocols#restXml |
|
aws.protocols#awsJson1_0 |
|
aws.protocols#awsJson1_1 |
|
aws.protocols#awsQuery |
|
aws.protocols#ec2Query |
Example
This example applies the go-codegen build plugin to the Smithy quickstart
example created from smithy init:
{
"version": "1.0",
"sources": [
"models"
],
"maven": {
"dependencies": [
"software.amazon.smithy.go:smithy-go-codegen:[0.1.0,2.0)"
]
},
"plugins": {
"go-codegen": {
"service": "example.weather#Weather",
"module": "github.com/example/weather",
"generateGoMod": true,
"goDirective": "1.24"
}
}
}`go-server-codegen`
This plugin is a work-in-progress and is currently undocumented.
`go-shape-codegen`
This plugin is a work-in-progress and is currently undocumented.
License
This project is licensed under the Apache-2.0 License.
Overview (`vendor/github.com/blendle/zapdriver/README.md`)
:zap: Zapdriver
Blazing fast, Zap-based Stackdriver logging.
Usage
This package provides three building blocks to support the full array of
structured logging capabilities of Stackdriver:
- Special purpose logging fields
- Pre-configured Stackdriver-optimized encoder
- Custom Stackdriver Zap core
- Using Error Reporting
The above components can be used separately, but to start, you can create a new
Zap logger with all of the above included:
logger, err := zapdriver.NewProduction() // with sampling
logger, err := zapdriver.NewDevelopment() // with `development` set to `true`The above functions give back a pointer to a zap.Logger object, so you can use
Zap like you've always done, except that it now logs in the proper
Stackdriver format.
You can also create a configuration struct, and build your logger from there:
config := zapdriver.NewProductionConfig()
config := zapdriver.NewDevelopmentConfig()Or, get the Zapdriver encoder, and build your own configuration struct from
that:
encoder := zapdriver.NewProductionEncoderConfig()
encoder := zapdriver.NewDevelopmentEncoderConfig()Read on to learn more about the available Stackdriver-specific log fields, and
how to use the above-mentioned components.
Special purpose logging fields
You can use the following fields to add extra information to your log entries.
These fields are parsed by Stackdriver to make it easier to query your logs or
to use the log details in the Stackdriver monitoring interface.
HTTP
You can log HTTP request/response cycles using the following field:
HTTP(req *HTTPPayload) zap.FieldYou can either manually build the request payload:
req := &HTTPPayload{
RequestMethod: "GET",
RequestURL: "/",
Status: 200,
}Or, you can auto generate the struct, based on the available request and
response objects:
NewHTTP(req *http.Request, res *http.Response) *HTTPPayloadYou are free to pass in nil for either the request or response object, if one
of them is unavailable to you at the point of logging. Any field depending on
one or the other will be omitted if nil is passed in.
Note that there are some fields that are not populated by either the request or
response object, and need to be set manually:
ServerIP stringLatency stringCacheLookup boolCacheHit boolCacheValidatedWithOriginServer boolCacheFillBytes string
If you have no need for those fields, the quickest way to get started is like
so:
logger.Info("Request Received.", zapdriver.HTTP(zapdriver.NewHTTP(req, res)))Label
You can add a "label" to your payload as follows:
Label(key, value string) zap.FieldNote that underwater, this sets the key to labels.<key>. You need to be using
the zapdriver.Core core for this to be converted to the proper format for
Stackdriver to recognize the labels.
See "Custom Stackdriver Zap core" for more details.
If you have a reason not to use the provided Core, you can still wrap labels in
the right labels namespace by using the available function:
Labels(fields ...zap.Field) zap.FieldLike so:
logger.Info(
"Did something.",
zapdriver.Labels(
zapdriver.Label("hello", "world"),
zapdriver.Label("hi", "universe"),
),
)Again, wrapping the Label calls in Labels is not required if you use the
supplied Zap Core.
SourceLocation
You can add a source code location to your log lines to be picked up by
Stackdriver.
Note that you can set this manually, or use zapdriver.Core to automatically
add this. If you set it manually, and use zapdriver.Core, the manual call
stack will be preserved over the automated one.
SourceLocation(pc uintptr, file string, line int, ok bool) zap.FieldNote that the function signature equals that of the return values ofruntime.Caller(). This allows you to catch the stack frame at one location,
while logging it at a different location, like so:
pc, file, line, ok := runtime.Caller(0)
// do other stuff...
logger.Error("Something happened!", zapdriver.SourceLocation(pc, file, line, ok))If you use zapdriver.Core, the above use-case is the only use-case where you
would want to manually set the source location. In all other situations, you can
simply omit this field, and it will be added automatically, using the stack
frame at the location where the log line is triggered.
If you don't use zapdriver.Core, and still want to add the source location at
the frame of the triggered log line, you'd do it like this:
logger.Error("Something happened!", zapdriver.SourceLocation(runtime.Caller(0)))Operation
The Operation log field allows you to group log lines into a single
"operation" performed by the application:
Operation(id, producer string, first, last bool) zap.FieldFor a pair of logs that belong to the same operation, you should use the sameid between them. The producer is an arbitrary identifier that should be
globally unique amongst all the logs of all your applications (meaning it should
probably be the unique name of the current application). You should set first
to true for the first log in the operation, and last to true for the final log
of the operation.
logger.Info("Started.", zapdriver.Operation("3g4d3g", "my-app", true, false))
logger.Debug("Progressing.", zapdriver.Operation("3g4d3g", "my-app", false, false))
logger.Info("Done.", zapdriver.Operation("3g4d3g", "my-app", false, true))Instead of defining the "start" and "end" booleans, you can also use these three
convenience functions:
OperationStart(id, producer string) zap.Field
OperationCont(id, producer string) zap.Field
OperationEnd(id, producer string) zap.FieldTraceContext
You can add trace context information to your log lines to be picked up by
Stackdriver.
TraceContext(trace string, spanId string, sampled bool, projectName string) []zap.FieldLike so:
logger.Error("Something happened!", zapdriver.TraceContext("105445aa7843bc8bf206b120001000", "0", true, "my-project-name")...)Pre-configured Stackdriver-optimized encoder
The Stackdriver encoder maps all Zap log levels to the appropriate
Stackdriver-supported levels:
DEBUG (100) Debug or trace information.
INFO (200) Routine information, such as ongoing status or performance.
WARNING (400) Warning events might cause problems.
ERROR (500) Error events are likely to cause problems.
CRITICAL (600) Critical events cause more severe problems or outages.
ALERT (700) A person must take an action immediately.
EMERGENCY (800) One or more systems are unusable.
It also sets some of the default keys to use the right names, such astimestamp, severity, and message.
You can use this encoder if you want to build your Zap logger configuration
manually:
zapdriver.NewProductionEncoderConfig()For parity-sake, there's also zapdriver.NewDevelopmentEncoderConfig(), but it
returns the exact same encoder right now.
Custom Stackdriver Zap core
A custom Zap core is included in this package to support some special use-cases.
First of all, if you use zapdriver.NewProduction() (or NewDevelopment) , you
already have this core enabled, so everything just works β’.
There are two use-cases which require this core:
If you use
zapdriver.Label("hello", "world"), it will initially end up in
your log with the keylabels.helloand valueworld. Now if you have two
labels, you could also havelabels.hiwith valueuniverse. This works as-
is, but for this to be correctly parsed by Stackdriver as true "labels", you
need to use the Zapdriver core, so that both of these fields get rewritten,
to use the namespacelabels, and use the keyshelloandhiwithin that
namespace. This is done automatically.If you don't want to use
zapdriver.SourceLocation()on every log call, you
can use this core for the source location to be automatically added to
each log entry.
When building a logger, you can inject the Zapdriver core as follows:
config := &zap.Config{}
logger, err := config.Build(zapdriver.WrapCore())Using Error Reporting
To report errors using StackDriver's Error Reporting tool, a log line needs to follow a separate log format described in the Error Reporting documentation.
The simplest way to do this is by using NewProductionWithCore:
logger, err := zapdriver.NewProductionWithCore(zapdriver.WrapCore(
zapdriver.ReportAllErrors(true),
zapdriver.ServiceName("my service"),
))For parity-sake, there's also zapdriver.NewDevelopmentWithCore()
If you are building a custom logger, you can use WrapCore() to configure the driver core:
config := &zap.Config{}
logger, err := config.Build(zapdriver.WrapCore(
zapdriver.ReportAllErrors(true),
zapdriver.ServiceName("my service"),
))Configuring this way, every error log entry will be reported to Stackdriver's Error Reporting tool.
Reporting errors manually
If you do not want every error to be reported, you can attach ErrorReport() to log call manually:
logger.Error("An error to be reported!", zapdriver.ErrorReport(runtime.Caller(0)))
// Or get Caller details
pc, file, line, ok := runtime.Caller(0)
// do other stuff... and log elsewhere
logger.Error("Another error to be reported!", zapdriver.ErrorReport(pc, file, line, ok))Please keep in mind that ErrorReport needs a ServiceContext attached to the log
entry. If you did not configure this using WrapCore, error reports will
get attached using service name as unknown. To prevent this from happeneing,
either configure your core or attach service context before (or when) using
the logger:
logger.Error(
"An error to be reported!",
zapdriver.ErrorReport(runtime.Caller(0)),
zapdriver.ServiceContext("my service"),
)
// Or permanently attach it to your logger
logger = logger.With(zapdriver.ServiceContext("my service"))
// and then use it
logger.Error("An error to be reported!", zapdriver.ErrorReport(runtime.Caller(0)))Overview (`vendor/github.com/davidmz/go-pageant/README.md`)
Package pageant provides an interface to PyTTY pageant.exe utility.
This package is windows-only.
See documentation on GoDoc
License: MIT
Overview (`vendor/github.com/elastic/crd-ref-docs/README.md`)
CRD Reference Documentation Generator
Generates API reference documentation by scanning a source tree for exported CRD types.
This is a fresh implementation inspired by the https://github.com/ahmetb/gen-crd-api-reference-docs project. While trying to adopt the gen-crd-api-refernce-docs to generate documentation for Elastic Cloud on Kubernetes, we encountered a few shortcomings such as the lack of support for Go modules, slow scan times, and rendering logic that was hard to adapt to Asciidoc (our preferred documentation markup language). This project attempts to address those issues by re-implementing the type discovery logic and decoupling the rendering logic so that different markup formats can be supported.
Usage
Pre-built Linux binaries can be downloaded from the Github Releases tab. Alternatively, you can download and build the source with Go tooling:
go get -u github.com/elastic/crd-ref-docsThe tool can be invoked as follows to generate documentation:
crd-ref-docs \
--source-path=$GOPATH/src/github.com/elastic/cloud-on-k8s/pkg/apis \
--config=config.yamlBy default, documentation is rendered in Asciidoc format. In order to generate documentation in Markdown format, you will have to specify the markdown renderer:
crd-ref-docs \
--source-path=$GOPATH/src/github.com/elastic/cloud-on-k8s/pkg/apis \
--config=config.yaml \
--renderer=markdownDefault templates are embedded in the binary. You may provide your own templates by specifying the templates directory:
crd-ref-docs \
--source-path=$GOPATH/src/github.com/elastic/cloud-on-k8s/pkg/apis \
--config=config.yaml \
--renderer=asciidoctor \
--templates-dir=templates/asciidoctorDefault output mode writes all data to a single output file.
You can choose between single mode and group mode by specifying the output mode.
In group mode, separate files are created for each API group, ensuring that the specified output path is an existing directory.
crd-ref-docs \
--source-path=$GOPATH/src/github.com/elastic/cloud-on-k8s/pkg/apis \
--config=config.yaml \
--output-path=./docs \
--output-mode=groupConfiguration
Configuration options such as types and fields to exclude from the documentation can be specified using a YAML file.
processor:
# RE2 regular expressions describing types that should be excluded from the generated documentation.
ignoreTypes:
- "(Elasticsearch|Kibana|ApmServer)List$"
- "(Elasticsearch|Kibana|ApmServer)Health$"
- "(Elasticsearch|Kibana|ApmServer|Reconciler)Status$"
- "ElasticsearchSettings$"
- "Associa(ted|tor|tionStatus|tionConf)$"
# RE2 regular expressions describing type fields that should be excluded from the generated documentation.
ignoreFields:
- "status$"
- "TypeMeta$"
render:
# Version of Kubernetes to use when generating links to Kubernetes API documentation.
kubernetesVersion: 1.22
# Generate better link for known types
knownTypes:
- name: SecretObjectReference
package: sigs.k8s.io/gateway-api/apis/v1beta1
link: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.SecretObjectReferenceAdvanced Features
Custom Markers
You can add custom markers to your CRD types to provide additional information in the generated documentation.
For example, you can add a hidefromdoc marker to indicate that a type is hide from the documentation.
processor:
ignoreGroupVersions:
- "GVK"
ignoreTypes:
- "Embedded[2-4]$"
ignoreFields:
- "status$"
- "TypeMeta$"
customMarkers:
- name: "hidefromdoc"
target: field
render:
kubernetesVersion: 1.25
knownTypes:
- name: SecretObjectReference
package: sigs.k8s.io/gateway-api/apis/v1beta1
link: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.SecretObjectReferenceYou can then add the hidefromdoc marker to the field you want to hidden from the documentation. Markers can be added
to fields, types and packages. The target field in the configuration specifies the target of the marker (it can be eitherfield, type or package).
type Embedded1 struct {
Embedded2 `json:",inline"`
// +hidefromdoc
E string `json:"e,omitempty"`
EmbeddedX `json:",inline"`
}Then update the templates to render the custom markers. You can find an example here.
Overview (`vendor/github.com/felixge/httpsnoop/README.md`)
httpsnoop
Package httpsnoop provides an easy way to capture http related metrics (i.e.
response time, bytes written, and http status code) from your application's
http.Handlers.
Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
which is also exposed for users interested in a more low-level API.
Usage Example
// myH is your app's http handler, perhaps a http.ServeMux or similar.
var myH http.Handler
// wrappedH wraps myH in order to log every request.
wrappedH := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
m := httpsnoop.CaptureMetrics(myH, w, r)
log.Printf(
"%s %s (code=%d dt=%s written=%d)",
r.Method,
r.URL,
m.Code,
m.Duration,
m.Written,
)
})
http.ListenAndServe(":8080", wrappedH)Why this package exists
Instrumenting an application's http.Handler is surprisingly difficult.
However if you google for e.g. "capture ResponseWriter status code" you'll find
lots of advise and code examples that suggest it to be a fairly trivial
undertaking. Unfortunately everything I've seen so far has a high chance of
breaking your application.
The main problem is that a http.ResponseWriter often implements additional
interfaces such as http.Flusher, http.CloseNotifier, http.Hijacker, http.Pusher, andio.ReaderFrom. So the naive approach of just wrapping http.ResponseWriter
in your own struct that also implements the http.ResponseWriter interface
will hide the additional interfaces mentioned above. This has a high change of
introducing subtle bugs into any non-trivial application.
Another approach I've seen people take is to return a struct that implements
all of the interfaces above. However, that's also problematic, because it's
difficult to fake some of these interfaces behaviors when the underlyinghttp.ResponseWriter doesn't have an implementation. It's also dangerous,
because an application may choose to operate differently, merely because it
detects the presence of these additional interfaces.
This package solves this problem by checking which additional interfaces ahttp.ResponseWriter implements, returning a wrapped version implementing the
exact same set of interfaces.
Additionally this package properly handles edge cases such as WriteHeader not
being called, or called more than once, as well as concurrent calls tohttp.ResponseWriter methods, and even calls happening after the wrappedServeHTTP has already returned.
Unfortunately this package is not perfect either. It's possible that it is
still missing some interfaces provided by the go core (let me know if you find
one), and it won't work for applications adding their own interfaces into the
mix. You can however use httpsnoop.Unwrap(w) to access the underlyinghttp.ResponseWriter and type-assert the result to its other interfaces.
However, hopefully the explanation above has sufficiently scared you of rolling
your own solution to this problem. httpsnoop may still break your application,
but at least it tries to avoid it as much as possible.
Anyway, the real problem here is that smuggling additional interfaces insidehttp.ResponseWriter is a problematic design choice, but it probably goes as
deep as the Go language specification itself. But that's okay, I still prefer
Go over the alternatives ;).
Performance
BenchmarkBaseline-8 20000 94912 ns/op
BenchmarkCaptureMetrics-8 20000 95461 ns/opAs you can see, using CaptureMetrics on a vanilla http.Handler introduces an
overhead of ~500 ns per http request on my machine. However, the margin of
error appears to be larger than that, therefor it should be reasonable to
assume that the overhead introduced by CaptureMetrics is absolutely
negligible.
License
MIT
Overview (`vendor/github.com/go-fed/httpsig/README.md`)
httpsig
go get github.com/go-fed/httpsig
Implementation of HTTP Signatures.
Supports many different combinations of MAC, HMAC signing of hash, or RSA
signing of hash schemes. Its goals are:
- Have a very simple interface for signing and validating
- Support a variety of signing algorithms and combinations
- Support setting either headers (
AuthorizationorSignature) - Remaining flexible with headers included in the signing string
- Support both HTTP requests and responses
- Explicitly not support known-cryptographically weak algorithms
- Support automatic signing and validating Digest headers
How to use
import "github.com/go-fed/httpsig"
Signing
Signing a request or response requires creating a new Signer and using it:
func sign(privateKey crypto.PrivateKey, pubKeyId string, r *http.Request) error {
prefs := []httpsig.Algorithm{httpsig.RSA_SHA512, httpsig.RSA_SHA256}
digestAlgorithm := DigestSha256
// The "Date" and "Digest" headers must already be set on r, as well as r.URL.
headersToSign := []string{httpsig.RequestTarget, "date", "digest"}
signer, chosenAlgo, err := httpsig.NewSigner(prefs, digestAlgorithm, headersToSign, httpsig.Signature)
if err != nil {
return err
}
// To sign the digest, we need to give the signer a copy of the body...
// ...but it is optional, no digest will be signed if given "nil"
body := ...
// If r were a http.ResponseWriter, call SignResponse instead.
return signer.SignRequest(privateKey, pubKeyId, r, body)
}Signers are not safe for concurrent use by goroutines, so be sure to guard
access:
type server struct {
signer httpsig.Signer
mu *sync.Mutex
}
func (s *server) handlerFunc(w http.ResponseWriter, r *http.Request) {
privateKey := ...
pubKeyId := ...
// Set headers and such on w
s.mu.Lock()
defer s.mu.Unlock()
// To sign the digest, we need to give the signer a copy of the response body...
// ...but it is optional, no digest will be signed if given "nil"
body := ...
err := s.signer.SignResponse(privateKey, pubKeyId, w, body)
if err != nil {
...
}
...
}The pubKeyId will be used at verification time.
Verifying
Verifying requires an application to use the pubKeyId to both retrieve the key
needed for verification as well as determine the algorithm to use. Use aVerifier:
func verify(r *http.Request) error {
verifier, err := httpsig.NewVerifier(r)
if err != nil {
return err
}
pubKeyId := verifier.KeyId()
var algo httpsig.Algorithm = ...
var pubKey crypto.PublicKey = ...
// The verifier will verify the Digest in addition to the HTTP signature
return verifier.Verify(pubKey, algo)
}Verifiers are not safe for concurrent use by goroutines, but since they are
constructed on a per-request or per-response basis it should not be a common
restriction.
Overview (`vendor/github.com/go-logr/logr/README.md`)
A minimal logging API for Go
logr offers an(other) opinion on how Go programs and libraries can do logging
without becoming coupled to a particular logging implementation. This is not
an implementation of logging - it is an API. In fact it is two APIs with two
different sets of users.
The Logger type is intended for application and library authors. It provides
a relatively small API which can be used everywhere you want to emit logs. It
defers the actual act of writing logs (to files, to stdout, or whatever) to theLogSink interface.
The LogSink interface is intended for logging library implementers. It is a
pure interface which can be implemented by logging frameworks to provide the actual logging
functionality.
This decoupling allows application and library developers to write code in
terms of logr.Logger (which has very low dependency fan-out) while the
implementation of logging is managed "up stack" (e.g. in or near main().)
Application developers can then switch out implementations as necessary.
Many people assert that libraries should not be logging, and as such efforts
like this are pointless. Those people are welcome to convince the authors of
the tens-of-thousands of libraries that DO write logs that they are all
wrong. In the meantime, logr takes a more practical approach.
Typical usage
Somewhere, early in an application's life, it will make a decision about which
logging library (implementation) it actually wants to use. Something like:
func main() {
// ... other setup code ...
// Create the "root" logger. We have chosen the "logimpl" implementation,
// which takes some initial parameters and returns a logr.Logger.
logger := logimpl.New(param1, param2)
// ... other setup code ...Most apps will call into other libraries, create structures to govern the flow,
etc. The logr.Logger object can be passed to these other libraries, stored
in structs, or even used as a package-global variable, if needed. For example:
app := createTheAppObject(logger)
app.Run()Outside of this early setup, no other packages need to know about the choice of
implementation. They write logs in terms of the logr.Logger that they
received:
type appObject struct {
// ... other fields ...
logger logr.Logger
// ... other fields ...
}
func (app *appObject) Run() {
app.logger.Info("starting up", "timestamp", time.Now())
// ... app code ...Background
If the Go standard library had defined an interface for logging, this project
probably would not be needed. Alas, here we are.
When the Go developers started developing such an interface with
slog, they adopted some of the
logr design but also left out some parts and changed others:
| Feature | logr | slog |
|---|---|---|
| High-level API | Logger (passed by value) |
Logger (passed by pointer) |
| Low-level API | LogSink |
Handler |
| Stack unwinding | done by LogSink |
done by Logger |
| Skipping helper functions | WithCallDepth, WithCallStackHelper |
not supported by Logger |
| Generating a value for logging on demand | Marshaler |
LogValuer |
| Log levels | >= 0, higher meaning "less important" | positive and negative, with 0 for "info" and higher meaning "more important" |
| Error log entries | always logged, don't have a verbosity level | normal log entries with level >= LevelError |
| Passing logger via context | NewContext, FromContext |
no API |
| Adding a name to a logger | WithName |
no API |
| Modify verbosity of log entries in a call chain | V |
no API |
| Grouping of key/value pairs | not supported | WithGroup, GroupValue |
| Pass context for extracting additional values | no API | API variants like InfoCtx |
The high-level slog API is explicitly meant to be one of many different APIs
that can be layered on top of a shared slog.Handler. logr is one such
alternative API, with interoperability provided by
some conversion functions.
Inspiration
Before you consider this package, please read this blog post by the
inimitable Dave Cheney. We really appreciate what
he has to say, and it largely aligns with our own experiences.
Differences from Dave's ideas
The main differences are:
- Dave basically proposes doing away with the notion of a logging API in favor
offmt.Printf(). We disagree, especially when you consider things like output
locations, timestamps, file and line decorations, and structured logging. This
package restricts the logging API to just 2 types of logs: info and error.
Info logs are things you want to tell the user which are not errors. Error
logs are, well, errors. If your code receives an error from a subordinate
function call and is logging that error and not returning it, use error
logs.
- Verbosity-levels on info logs. This gives developers a chance to indicate
arbitrary grades of importance for info logs, without assigning names with
semantic meaning such as "warning", "trace", and "debug." Superficially this
may feel very similar, but the primary difference is the lack of semantics.
Because verbosity is a numerical value, it's safe to assume that an app running
with higher verbosity means more (and less important) logs will be generated.
Implementations (non-exhaustive)
There are implementations for the following logging libraries:
- a function (can bridge to non-structured libraries): funcr
- a testing.T (for use in Go tests, with JSON-like output): testr
- github.com/google/glog: glogr
- k8s.io/klog (for Kubernetes): klogr
- a testing.T (with klog-like text output): ktesting
- go.uber.org/zap: zapr
- log (the Go standard library logger): stdr
- github.com/sirupsen/logrus: logrusr
- github.com/wojas/genericr: genericr (makes it easy to implement your own backend)
- logfmt (Heroku style logging): logfmtr
- github.com/rs/zerolog: zerologr
- github.com/go-kit/log: gokitlogr (also compatible with github.com/go-kit/kit/log since v0.12.0)
- bytes.Buffer (writing to a buffer): bufrlogr (useful for ensuring values were logged, like during testing)
slog interoperability
Interoperability goes both ways, using the logr.Logger API with a slog.Handler
and using the slog.Logger API with a logr.LogSink. FromSlogHandler andToSlogHandler convert between a logr.Logger and a slog.Handler.
As usual, slog.New can be used to wrap such a slog.Handler in the high-level
slog API.
Using a `logr.LogSink` as backend for slog
Ideally, a logr sink implementation should support both logr and slog by
implementing both the normal logr interface(s) and SlogSink. Because
of a conflict in the parameters of the common Enabled method, it is not
possible to implement both slog.Handler and logr.Sink in the same
type.
If both are supported, log calls can go from the high-level APIs to the backend
without the need to convert parameters. FromSlogHandler and ToSlogHandler can
convert back and forth without adding additional wrappers, with one exception:
when Logger.V was used to adjust the verbosity for a slog.Handler, thenToSlogHandler has to use a wrapper which adjusts the verbosity for future
log calls.
Such an implementation should also support values that implement specific
interfaces from both packages for logging (logr.Marshaler, slog.LogValuer,slog.GroupValue). logr does not convert those.
Not supporting slog has several drawbacks:
- Recording source code locations works correctly if the handler gets called
throughslog.Logger, but may be wrong in other cases. That's because alogr.Sinkdoes its own stack unwinding instead of using the program counter
provided by the high-level API. - slog levels <= 0 can be mapped to logr levels by negating the level without a
loss of information. But all slog levels > 0 (e.g.slog.LevelWarningas
used byslog.Logger.Warn) must be mapped to 0 before calling the sink
because logr does not support "more important than info" levels. - The slog group concept is supported by prefixing each key in a key/value
pair with the group names, separated by a dot. For structured output like
JSON it would be better to group the key/value pairs inside an object. - Special slog values and interfaces don't work as expected.
- The overhead is likely to be higher.
These drawbacks are severe enough that applications using a mixture of slog and
logr should switch to a different backend.
Using a `slog.Handler` as backend for logr
Using a plain slog.Handler without support for logr works better than the
other direction:
- All logr verbosity levels can be mapped 1:1 to their corresponding slog level
by negating them. - Stack unwinding is done by the
SlogSinkand the resulting program
counter is passed to theslog.Handler. - Names added via
Logger.WithNameare gathered and recorded in an additional
attribute withloggeras key and the names separated by slash as value. Logger.Erroris turned into a log record withslog.LevelErroras level
and an additional attribute witherras key, if an error was provided.
The main drawback is that logr.Marshaler will not be supported. Types should
ideally support both logr.Marshaler and slog.Valuer. If compatibility
with logr implementations without slog support is not important, thenslog.Valuer is sufficient.
Context support for slog
Storing a logger in a context.Context is not supported by
slog. NewContextWithSlogLogger and FromContextAsSlogLogger can be
used to fill this gap. They store and retrieve a slog.Logger pointer
under the same context key that is also used by NewContext andFromContext for logr.Logger value.
When NewContextWithSlogLogger is followed by FromContext, the latter will
automatically convert the slog.Logger to alogr.Logger. FromContextAsSlogLogger does the same for the other direction.
With this approach, binaries which use either slog or logr are as efficient as
possible with no unnecessary allocations. This is also why the API stores aslog.Logger pointer: when storing a slog.Handler, creating a slog.Logger
on retrieval would need to allocate one.
The downside is that switching back and forth needs more allocations. Because
logr is the API that is already in use by different packages, in particular
Kubernetes, the recommendation is to use the logr.Logger API in code which
uses contextual logging.
An alternative to adding values to a logger and storing that logger in the
context is to store the values in the context and to configure a logging
backend to extract those values when emitting log entries. This only works when
log calls are passed the context, which is not supported by the logr API.
With the slog API, it is possible, but not
required. https://github.com/veqryn/slog-context is a package for slog which
provides additional support code for this approach. It also contains wrappers
for the context functions in logr, so developers who prefer to not use the logr
APIs directly can use those instead and the resulting code will still be
interoperable with logr.
FAQ
Conceptual
Why structured logging?
Structured logs are more easily queryable: Since you've got
key-value pairs, it's much easier to query your structured logs for
particular values by filtering on the contents of a particular key --
think searching request logs for error codes, Kubernetes reconcilers for
the name and namespace of the reconciled object, etc.Structured logging makes it easier to have cross-referenceable logs:
Similarly to searchability, if you maintain conventions around your
keys, it becomes easy to gather all log lines related to a particular
concept.Structured logs allow better dimensions of filtering: if you have
structure to your logs, you've got more precise control over how much
information is logged -- you might choose in a particular configuration
to log certain keys but not others, only log lines where a certain key
matches a certain value, etc., instead of just having v-levels and names
to key off of.Structured logs better represent structured data: sometimes, the
data that you want to log is inherently structured (think tuple-link
objects.) Structured logs allow you to preserve that structure when
outputting.
Why V-levels?
V-levels give operators an easy way to control the chattiness of log
operations. V-levels provide a way for a given package to distinguish
the relative importance or verbosity of a given log message. Then, if
a particular logger or package is logging too many messages, the user
of the package can simply change the v-levels for that library.
Why not named levels, like Info/Warning/Error?
Read Dave Cheney's post. Then read Differences
from Dave's ideas.
Why not allow format strings, too?
Format strings negate many of the benefits of structured logs:
They're not easily searchable without resorting to fuzzy searching,
regular expressions, etc.They don't store structured data well, since contents are flattened into
a string.They're not cross-referenceable.
They don't compress easily, since the message is not constant.
(Unless you turn positional parameters into key-value pairs with numerical
keys, at which point you've gotten key-value logging with meaningless
keys.)
Practical
Why key-value pairs, and not a map?
Key-value pairs are much easier to optimize, especially around
allocations. Zap (a structured logger that inspired logr's interface) has
performance measurements
that show this quite nicely.
While the interface ends up being a little less obvious, you get
potentially better performance, plus avoid making users typemap[string]string{} every time they want to log.
What if my V-levels differ between libraries?
That's fine. Control your V-levels on a per-logger basis, and use theWithName method to pass different loggers to different libraries.
Generally, you should take care to ensure that you have relatively
consistent V-levels within a given logger, however, as this makes deciding
on what verbosity of logs to request easier.
But I really want to use a format string!
That's not actually a question. Assuming your question is "how do
I convert my mental model of logging with format strings to logging with
constant messages":
Figure out what the error actually is, as you'd write in a TL;DR style,
and use that as a message.For every place you'd write a format specifier, look to the word before
it, and add that as a key value pair.
For instance, consider the following examples (all taken from spots in the
Kubernetes codebase):
klog.V(4).Infof("Client is returning errors: code %v, error %v", responseCode, err)becomeslogger.Error(err, "client returned an error", "code", responseCode)klog.V(4).Infof("Got a Retry-After %ds response for attempt %d to %v", seconds, retries, url)becomeslogger.V(4).Info("got a retry-after response when requesting url", "attempt", retries, "after seconds", seconds, "url", url)
If you really must use a format string, use it in a key's value, and
call fmt.Sprintf yourself. For instance: log.Printf("unable to reflect over type %T") becomes logger.Info("unable to reflect over type", "type", fmt.Sprintf("%T")). In general though, the cases where
this is necessary should be few and far between.
How do I choose my V-levels?
This is basically the only hard constraint: increase V-levels to denote
more verbose or more debug-y logs.
Otherwise, you can start out with 0 as "you always want to see this",1 as "common logging that you might possibly want to turn off", and10 as "I would like to performance-test your log collection stack."
Then gradually choose levels in between as you need them, working your way
down from 10 (for debug and trace style logs) and up from 1 (for chattier
info-type logs). For reference, slog pre-defines -4 for debug logs
(corresponds to 4 in logr), which matches what is
recommended for Kubernetes.
How do I choose my keys?
Keys are fairly flexible, and can hold more or less any string
value. For best compatibility with implementations and consistency
with existing code in other projects, there are a few conventions you
should consider.
- Make your keys human-readable.
- Constant keys are generally a good idea.
- Be consistent across your codebase.
- Keys should naturally match parts of the message string.
- Use lower case for simple keys and
lowerCamelCase for
more complex ones. Kubernetes is one example of a project that has
adopted that
convention.
While key names are mostly unrestricted (and spaces are acceptable),
it's generally a good idea to stick to printable ascii characters, or at
least match the general character set of your log lines.
Why should keys be constant values?
The point of structured logging is to make later log processing easier. Your
keys are, effectively, the schema of each log message. If you use different
keys across instances of the same log line, you will make your structured logs
much harder to use. Sprintf() is for values, not for keys!
Why is this not a pure interface?
The Logger type is implemented as a struct in order to allow the Go compiler to
optimize things like high-V Info logs that are not triggered. Not all of
these implementations are implemented yet, but this structure was suggested as
a way to ensure they can be implemented. All of the real work is behind theLogSink interface.
Overview (`vendor/github.com/go-logr/stdr/README.md`)
Minimal Go logging using logr and Go's standard library
This package implements the logr interface
in terms of Go's standard log package(https://pkg.go.dev/log).
Overview (`vendor/github.com/go-logr/zapr/README.md`)
Zapr :zap:
A logr implementation using
Zap. Can also be used as
slog handler.
Usage
Via logr:
package main
import (
"fmt"
"go.uber.org/zap"
"github.com/go-logr/logr"
"github.com/go-logr/zapr"
)
func main() {
var log logr.Logger
zapLog, err := zap.NewDevelopment()
if err != nil {
panic(fmt.Sprintf("who watches the watchmen (%v)?", err))
}
log = zapr.NewLogger(zapLog)
log.Info("Logr in action!", "the answer", 42)
}Via slog:
package main
import (
"fmt"
"log/slog"
"github.com/go-logr/logr/slogr"
"github.com/go-logr/zapr"
"go.uber.org/zap"
)
func main() {
var log *slog.Logger
zapLog, err := zap.NewDevelopment()
if err != nil {
panic(fmt.Sprintf("who watches the watchmen (%v)?", err))
}
log = slog.New(slogr.NewSlogHandler(zapr.NewLogger(zapLog)))
log.Info("Logr in action!", "the answer", 42)
}Increasing Verbosity
Zap uses semantically named levels for logging (DebugLevel, InfoLevel,WarningLevel, ...). Logr uses arbitrary numeric levels. By default logr'sV(0) is zap's InfoLevel and V(1) is zap's DebugLevel (which is
numerically -1). Zap does not have named levels that are more verbose thanDebugLevel, but it's possible to fake it.
As of zap v1.19.0 you can do something like the following in your setup code:
zc := zap.NewProductionConfig()
zc.Level = zap.NewAtomicLevelAt(zapcore.Level(-2))
z, err := zc.Build()
if err != nil {
// ...
}
log := zapr.NewLogger(z)Zap's levels get more verbose as the number gets smaller and more important and
the number gets larger (DebugLevel is -1, InfoLevel is 0, WarnLevel is 1,
and so on).
The -2 in the above snippet means that log.V(2).Info() calls will be active.-3 would enable log.V(3).Info(), etc. Note that zap's levels are int8
which means the most verbose level you can give it is -128. The zapr
implementation will cap V() levels greater than 127 to 127, so setting the
zap level to -128 really means "activate all logs".
Implementation Details
For the most part, concepts in Zap correspond directly with those in logr.
Unlike Zap, all fields must be in the form of sugared fields --
it's illegal to pass a strongly-typed Zap field in a key position to any
of the logging methods (Log, Error).
The zapr logr.LogSink implementation also implements logr.SlogHandler. That
enables slogr.NewSlogHandler to provide a slog.Handler which just passes
parameters through to zapr. zapr handles special slog values (Group,
LogValuer), regardless of which front-end API is used.
Overview (`vendor/github.com/go-openapi/jsonpointer/README.md`)
jsonpointer
An implementation of JSON Pointer for golang, which supports go struct.
Announcements
2026-07-07 : landing v1.0.0
- stable API pledge
2026-06-29 : reinsourced external dependency to swag (v0.24.0)
- module
github.com/go-openapi/swag/jsonnameis source directly here, so we no longer have any external dependency jsonnamewas never really used by any other package, so it makes sense to deprecate it away from theswagfamily
and retrofit its functionality here.jsonpointerno longer get external dependencies, besides test dependencies.
- module
2026-04-15 : added support for trailing "-" for arrays (v0.23.0)
- this brings full support of RFC6901
- this is supported for types relying on the reflection-based implemented
- API semantics remain essentially unaltered. Exception:
Pointer.Set(document any,value any) (document any, err error)
can only perform a best-effort to mutate the input document in place. In the case of adding elements to an array with a
trailing "-", either pass a mutable array (*[]T) as the input document, or use the returned updated document instead. - types that implement the
JSONSetableinterface may not implement the mutation implied by the trailing "-"
2026-04-15 : added support for optional alternate JSON name providers
- for struct support the defaults might not suit all situations: there are known limitations
when it comes to handle untagged fields or embedded types. - the default name provider in use is not fully aligned with go JSON stdlib
- exposed an option (or global setting) to change the provider that resolves a struct into json keys
- the default behavior is not altered
- for struct support the defaults might not suit all situations: there are known limitations
Status
API is stable and feature-complete.
The project continues to receive regular updates, bug fixes and hygiene maintenance (CI, linting, etc).
Import this library in your project
go get github.com/go-openapi/jsonpointerBasic usage
See also some examples
Retrieving a value
import (
"github.com/go-openapi/jsonpointer"
)
var doc any
...
pointer, err := jsonpointer.New("/foo/1")
if err != nil {
... // error: e.g. invalid JSON pointer specification
}
value, kind, err := pointer.Get(doc)
if err != nil {
... // error: e.g. key not found, index out of bounds, etc.
}
...Setting a value
...
var doc any
...
pointer, err := jsonpointer.New("/foo/1")
if err != nil {
... // error: e.g. invalid JSON pointer specification
}
doc, err = p.Set(doc, "value")
if err != nil {
... // error: e.g. key not found, index out of bounds, etc.
}Change log
See https://github.com/go-openapi/jsonpointer/releases
References
https://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
also known as RFC6901.
Licensing
This library ships under the SPDX-License-Identifier: Apache-2.0.
See the license NOTICE, which recalls the licensing terms of all the pieces of software
on top of which it has been built.
Limitations
- RFC6901 is now fully supported, including trailing "-" semantics for arrays (for
Setoperations). - Default behavior: JSON name detection in go
structs- Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored.
- anonymous fields are not traversed if untagged
- the above limitations may be overcome by calling
UseGoNameProvider()at initialization time. - alternatively, users may inject the desired custom behavior for naming fields as an option.
Other documentation
Cutting a new release
Maintainers can cut a new release by either:
- running this workflow
- or pushing a semver tag
- signed tags are preferred
- The tag message is prepended to release notes
Overview (`vendor/github.com/go-openapi/jsonreference/README.md`)
jsonreference
An implementation of JSON Reference for golang.
Announcements
- 2026-07-07 : landing v1.0.0
- stable API pledge
Status
API is stable.
Import this library in your project
go get github.com/go-openapi/jsonreferenceDependencies
Basic usage
// Creating a new reference
ref, err := jsonreference.New("http://example.com/doc.json#/definitions/Pet")
// Fragment-only reference
fragRef := jsonreference.MustCreateRef("#/definitions/Pet")
// Resolving references
parent, _ := jsonreference.New("http://example.com/base.json")
child, _ := jsonreference.New("#/definitions/Pet")
resolved, _ := parent.Inherits(child)
// Result: "http://example.com/base.json#/definitions/Pet"Change log
See https://github.com/go-openapi/jsonreference/releases
References
- http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
- http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
Licensing
This library ships under the SPDX-License-Identifier: Apache-2.0.
See the license NOTICE, which recalls the licensing terms of all the pieces of software
on top of which it has been built.
Other documentation
Cutting a new release
Maintainers can cut a new release by either:
- running this workflow
- or pushing a semver tag
- signed tags are preferred
- The tag message is prepended to release notes
Overview (`vendor/github.com/go-openapi/swag/README.md`)
Swag
A bunch of helper functions for go-openapi and go-swagger projects.
You may also use it standalone for your projects.
NOTE
swagis one of the foundational building blocks of the go-openapi initiative.Most repositories in
github.com/go-openapi/...depend on it in some way.
And so does our CLI toolgithub.com/go-swagger/go-swagger,
as well as the code generated by this tool.
Announcements
- 2025-12-19 : new community chat on discord
- a new discord community channel is available to be notified of changes and support users
You may join the discord community by clicking the invite link on the discord badge (also above).
Status
API is stable.
Import this library in your project
go get github.com/go-openapi/swag/{module}Or for backward compatibility:
go get github.com/go-openapi/swagContents
go-openapi/swag exposes a collection of relatively independent modules.
Moving forward, no additional feature will be added to the swag API directly at the root package level,
which remains there for backward-compatibility purposes. All exported top-level features are now deprecated.
Child modules will continue to evolve and some new ones may be added in the future.
| Module | Content | Main features |
|---|---|---|
cmdutils |
utilities to work with CLIs | |
conv |
type conversion utilities | convert between values and pointers for any typesconvert from string to builtin types (wraps strconv)require ./typeutils (test dependency) |
fileutils |
file utilities | |
jsonname |
JSON utilities (deprecated) | infer JSON names from go propertiesuse github.com/go-openapi/jsonpointer/jsonname instead |
jsonutils |
JSON utilities | fast json concatenationread and write JSON from and to dynamic go data structuresgithub.com/mailru/easyjson |
loading |
file loading | load from file or httprequire ./yamlutils |
mangling |
safe name generation | name mangling for go |
netutils |
networking utilities | host, port from address |
pools |
utilities to work with sync.Pools | |
stringutils |
string utilities |
search in slice (with case-insensitive)split/join query parameters as arrays |
typeutils |
go types utilities |
check the zero value for any typesafe check for a nil value |
yamlutils |
YAML utilities | converting YAML to JSONloading YAML into a dynamic YAML documentmaintaining the original order of keys in YAML objectsrequire ./jsonutils~require github.com/mailru/easyjson~require go.yaml.in/yaml/v3 |
Dependencies
The root module github.com/go-openapi/swag at the repo level maintains a few
dependencies outside of the standard library.
- YAML utilities depend on
go.yaml.in/yaml/v3 - JSON utilities depend on their registered adapter module:
- by default, only the standard library is used
github.com/mailru/easyjsonis now only a dependency for modulegithub.com/go-openapi/swag/jsonutils/adapters/easyjson/json,
for users willing to import that module.- integration tests and benchmarks use all the dependencies are published as their own module
- other dependencies are test dependencies drawn from
github.com/stretchr/testify
Usage
How to explicitly register a dependency at runtime?
The following would maintain how JSON utilities proposed by swag used work, up to v0.24.1.
import (
"github.com/go-openapi/swag/jsonutils/adapters"
easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
)
func init() {
easyjson.Register(adapters.Registry)
}Subsequent calls to jsonutils.ReadJSON() or jsonutils.WriteJSON() will switch to easyjson
whenever the passed data structures implement the easyjson.Unmarshaler or easyjson.Marshaler respectively,
or fallback to the standard library.
For more details, you may also look at our
integration tests.
Note to contributors
All kinds of contributions are welcome.
This repo is a go mono-repo. See docs.
More general guidelines are available here.
Roadmap
See the current TODO list
Change log
See https://github.com/go-openapi/swag/releases
For pre-v0.26.0 releases, see release notes.
What coming next?
Moving forward, we want to :
- provide an implementation of the JSON adapter based on
encoding/json/v2, forgo1.25builds. - provide similar implementations for
goccy/go-jsonandjsoniterator/go, and perhaps some other
similar libraries may be interesting too.
Licensing
This library ships under the SPDX-License-Identifier: Apache-2.0.
Other documentation
Cutting a new release
Maintainers can cut a new release by either:
- running this workflow
- or pushing a semver tag
- signed tags are preferred
- The tag message is prepended to release notes
Overview (`vendor/github.com/gobuffalo/flect/README.md`)
Flect
This is a new inflection engine to replace https://github.com/markbates/inflect designed to be more modular, more readable, and easier to fix issues on than the original.
Flect provides word inflection features such as Singularize and Pluralize
for English nouns and text utility features such as Camelize, Capitalize,Humanize, and more.
Due to the flexibly-complex nature of English noun inflection, it is almost
impossible to cover all exceptions (such as identical/irregular plural).
With this reason along with the main purpose of Flect, which is to make it
easy to develop web application in Go, Flect has limitations with its own
rules.
- It covers regular rule (adding -s or -es and of the word)
- It covers well-known irregular rules (such as -is to -es, -f to -ves, etc)
- It covers well-known irregular words (such as children, men, etc)
- If a word can be countable and uncountable like milk or time, it will be
treated as countable. - If a word has more than one plural forms, which means it has at least one
irregular plural, we tried to find most popular one. (The selected plural
could be odd to you, please feel free to open an issue with back data)- For example, we selected "stadiums" over "stadia", "dwarfs" over "dwarves"
- One or combination of en.wiktionary.org, britannica.com, and
trends.google.com are used to check the recent usage trends.
- However, we cannot cover all cases and some of our cases could not fit with
your situation. You can override the default with functions such asInsertPlural(),InsertSingular(), orLoadInfrections(). - If you have a json file named
inflections.jsonin your application root,
the file will be automatically loaded as your custom inflection dictionary.
Installation
$ go get github.com/gobuffalo/flectPackages
`github.com/gobuffalo/flect`
The github.com/gobuffalo/flect package contains "basic" inflection tools, like pluralization, singularization, etc...
The `Ident` Type
In addition to helpful methods that take in a string and return a string, there is an Ident type that can be used to create new, custom, inflection rules.
The Ident type contains two fields.
Original- This is the originalstringthat was used to create theIdentParts- This is a[]stringthat represents all of the "parts" of the string, that have been split apart, making the segments easier to work with
Examples of creating new inflection rules using Ident can be found in the github.com/gobuffalo/flect/name package.
`github.com/gobuffalo/flect/name`
The github.com/gobuffalo/flect/name package contains more "business" inflection rules like creating proper names, table names, etc...
Overview (`vendor/github.com/goccy/go-yaml/README.md`)
YAML support for the Go language
This library has **NO** relation to the go-yaml/yaml library
[!IMPORTANT]
This library is developed from scratch to replacego-yaml/yaml.
If you're looking for a better YAML library, this one should be helpful.
Why a new library?
As of this writing, there already exists a de facto standard library for YAML processing for Go: https://github.com/go-yaml/yaml. However, we believe that a new YAML library is necessary for the following reasons:
- Not actively maintained
go-yaml/yamlhas ported the libyaml written in C to Go, so the source code is not written in Go style- There is a lot of content that cannot be parsed
- YAML is often used for configuration, and it is common to include validation along with it. However, the errors in
go-yaml/yamlare not intuitive, and it is difficult to provide meaningful validation errors - When creating tools that use YAML, there are cases where reversible transformation of YAML is required. However, to perform reversible transformations of content that includes Comments or Anchors/Aliases, manipulating the AST is the only option
- Non-intuitive Marshaler / Unmarshaler
By the way, libraries such as ghodss/yaml and sigs.k8s.io/yaml also depend on go-yaml/yaml, so if you are using these libraries, the same issues apply: they cannot parse things that go-yaml/yaml cannot parse, and they inherit many of the problems that go-yaml/yaml has.
Features
- No dependencies
- A better parser than
go-yaml/yaml.- Support recursive processing
- Higher coverage in the YAML Test Suite
- YAML Test Suite consists of 402 cases in total, of which
gopkg.in/yaml.v3passes295. In addition to passing all those test cases,goccy/go-yamlsuccessfully passes nearly 60 additional test cases ( 2024/12/15 ) - The test code is here
- YAML Test Suite consists of 402 cases in total, of which
- Ease and sustainability of maintenance
- The main maintainer is @goccy, but we are also building a system to develop as a team with trusted developers
- Since it is written from scratch, the code is easy to read for Gophers
- An API structure that allows the use of not only
Encoder/Decoderbut alsoTokenizerandParserfunctionalities. - Filtering, replacing, and merging YAML content using YAML Path
- Reversible transformation without using the AST for YAML that includes Anchors, Aliases, and Comments
- Customize the Marshal/Unmarshal behavior for primitive types and third-party library types (RegisterCustomMarshaler, RegisterCustomUnmarshaler)
- Respects
encoding/jsonbehavior- Accept the
jsontag. Note that not all options from thejsontag will have significance when parsing YAML documents. If both tags exist,yamltag will take precedence. - json.Marshaler style marshaler
- json.Unmarshaler style unmarshaler
- Options for using
MarshalJSONandUnmarshalJSON(UseJSONMarshaler, UseJSONUnmarshaler)
- Accept the
- Pretty format for error notifications
- Smart validation processing combined with go-playground/validator
- Allow referencing elements declared in another file via anchors
Users
The repositories that use goccy/go-yaml are listed here.
The source data is here.
It is already being used in many repositories. Now it's your turn π
Playground
The Playground visualizes how go-yaml processes YAML text. Use it to assist with your debugging or issue reporting.
https://goccy.github.io/go-yaml
Installation
go get github.com/goccy/go-yamlSynopsis
1. Simple Encode/Decode
Has an interface like go-yaml/yaml using reflect
var v struct {
A int
B string
}
v.A = 1
v.B = "hello"
bytes, err := yaml.Marshal(v)
if err != nil {
//...
}
fmt.Println(string(bytes)) // "a: 1\nb: hello\n"yml := `
%YAML 1.2
---
a: 1
b: c
`
var v struct {
A int
B string
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
//...
}To control marshal/unmarshal behavior, you can use the yaml tag.
yml := `---
foo: 1
bar: c
`
var v struct {
A int `yaml:"foo"`
B string `yaml:"bar"`
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
//...
}For convenience, we also accept the json tag. Note that not all options from
the json tag will have significance when parsing YAML documents. If both
tags exist, yaml tag will take precedence.
yml := `---
foo: 1
bar: c
`
var v struct {
A int `json:"foo"`
B string `json:"bar"`
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
//...
}For custom marshal/unmarshaling, implement either Bytes or Interface variant of marshaler/unmarshaler. The difference is that while BytesMarshaler/BytesUnmarshaler behaves like encoding/json and InterfaceMarshaler/InterfaceUnmarshaler behaves like gopkg.in/yaml.v2.
Semantically both are the same, but they differ in performance. Because indentation matters in YAML, you cannot simply accept a valid YAML fragment from a Marshaler, and expect it to work when it is attached to the parent container's serialized form. Therefore when we receive use the BytesMarshaler, which returns []byte, we must decode it once to figure out how to make it work in the given context. If you use the InterfaceMarshaler, we can skip the decoding.
If you are repeatedly marshaling complex objects, the latter is always better
performance wise. But if you are, for example, just providing a choice between
a config file format that is read only once, the former is probably easier to
code.
2. Reference elements declared in another file
testdata directory contains anchor.yml file:
βββ testdata
Β Β βββ anchor.ymlAnd anchor.yml is defined as follows:
a: &a
b: 1
c: helloThen, if yaml.ReferenceDirs("testdata") option is passed to yaml.Decoder,
Decoder tries to find the anchor definition from YAML files the under testdata directory.
buf := bytes.NewBufferString("a: *a\n")
dec := yaml.NewDecoder(buf, yaml.ReferenceDirs("testdata"))
var v struct {
A struct {
B int
C string
}
}
if err := dec.Decode(&v); err != nil {
//...
}
fmt.Printf("%+v\n", v) // {A:{B:1 C:hello}}3. Encode with `Anchor` and `Alias`
3.1. Explicitly declared `Anchor` name and `Alias` name
If you want to use anchor, you can define it as a struct tag.
If the value specified for an anchor is a pointer type and the same address as the pointer is found, the value is automatically set to alias.
If an explicit alias name is specified, an error is raised if its value is different from the value specified in the anchor.
type T struct {
A int
B string
}
var v struct {
C *T `yaml:"c,anchor=x"`
D *T `yaml:"d,alias=x"`
}
v.C = &T{A: 1, B: "hello"}
v.D = v.C
bytes, err := yaml.Marshal(v)
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
/*
c: &x
a: 1
b: hello
d: *x
*/3.2. Implicitly declared `Anchor` and `Alias` names
If you do not explicitly declare the anchor name, the default behavior is to
use the equivalent of strings.ToLower($FieldName) as the name of the anchor.
If the value specified for an anchor is a pointer type and the same address as the pointer is found, the value is automatically set to alias.
type T struct {
I int
S string
}
var v struct {
A *T `yaml:"a,anchor"`
B *T `yaml:"b,anchor"`
C *T `yaml:"c"`
D *T `yaml:"d"`
}
v.A = &T{I: 1, S: "hello"}
v.B = &T{I: 2, S: "world"}
v.C = v.A // C has same pointer address to A
v.D = v.B // D has same pointer address to B
bytes, err := yaml.Marshal(v)
if err != nil {
//...
}
fmt.Println(string(bytes))
/*
a: &a
i: 1
s: hello
b: &b
i: 2
s: world
c: *a
d: *b
*/3.3 MergeKey and Alias
Merge key and alias ( <<: *alias ) can be used by embedding a structure with the inline,alias tag.
type Person struct {
*Person `yaml:",omitempty,inline,alias"` // embed Person type for default value
Name string `yaml:",omitempty"`
Age int `yaml:",omitempty"`
}
defaultPerson := &Person{
Name: "John Smith",
Age: 20,
}
people := []*Person{
{
Person: defaultPerson, // assign default value
Name: "Ken", // override Name property
Age: 10, // override Age property
},
{
Person: defaultPerson, // assign default value only
},
}
var doc struct {
Default *Person `yaml:"default,anchor"`
People []*Person `yaml:"people"`
}
doc.Default = defaultPerson
doc.People = people
bytes, err := yaml.Marshal(doc)
if err != nil {
//...
}
fmt.Println(string(bytes))
/*
default: &default
name: John Smith
age: 20
people:
- <<: *default
name: Ken
age: 10
- <<: *default
*/4. Pretty Formatted Errors
Error values produced during parsing have two extra features over regular
error values.
First, by default, they contain extra information on the location of the error
from the source YAML document, to make it easier to find the error location.
Second, the error messages can optionally be colorized.
If you would like to control exactly how the output looks like, consider
using yaml.FormatError, which accepts two boolean values to
control turning these features on or off.
5. Use YAMLPath
yml := `
store:
book:
- author: john
price: 10
- author: ken
price: 12
bicycle:
color: red
price: 19.95
`
path, err := yaml.PathString("$.store.book[*].author")
if err != nil {
//...
}
var authors []string
if err := path.Read(strings.NewReader(yml), &authors); err != nil {
//...
}
fmt.Println(authors)
// [john ken]5.1 Print customized error with YAML source code
package main
import (
"fmt"
"github.com/goccy/go-yaml"
)
func main() {
yml := `
a: 1
b: "hello"
`
var v struct {
A int
B string
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
panic(err)
}
if v.A != 2 {
// output error with YAML source
path, err := yaml.PathString("$.a")
if err != nil {
panic(err)
}
source, err := path.AnnotateSource([]byte(yml), true)
if err != nil {
panic(err)
}
fmt.Printf("a value expected 2 but actual %d:\n%s\n", v.A, string(source))
}
}output result is the following:
Tools
ycat
print yaml file with color
Installation
git clone https://github.com/goccy/go-yaml.git
cd go-yaml/cmd/ycat && go install .For Developers
[!NOTE]
In this project, we manage such test code under thetestdatadirectory to avoid adding dependencies on libraries that are only needed for testing to the topgo.modfile. Therefore, if you want to add test cases that use 3rd party libraries, please add the test code to thetestdatadirectory.
Looking for Sponsors
I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a sponsor. I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free.
License
MIT
Overview (`vendor/github.com/goccy/kpoward/README.md`)
kpoward
Kubernetes Port Fowarding utility library in Go
If you specify the name and port number of the pod on which the server is running, port forwarding will be performed using a free port in your local system.
Install
go get github.com/goccy/kpowardSynopsis
Create a Kpoward instance with rest.Config and the name and port number of the pod. If necessary, use the Setter method to change a value such as Namespace and then call Run will call back the local bound free port. You can send any request to this port in the callback. Upon exiting the callback, port forwarding will automatically end and the port will be released.
var (
restCfg *rest.Config
targetPodName = "pod-xxx-yyy"
targetPort = 8080
)
kpow := kpoward.New(restCfg, targetPodName, targetPort)
if err := kpow.Run(context.Background(), func(ctx context.Context, localPort uint16) error {
log.Printf("localPort: %d", localPort)
resp, err := http.Get(fmt.Sprintf("http://localhost:%d", localPort))
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}); err != nil {
panic(err)
}License
MIT
Overview (`vendor/github.com/google/s2a-go/README.md`)
Secure Session Agent Client Libraries
The Secure Session Agent is a service that enables a workload to offload select
operations from the mTLS handshake and protects a workload's private key
material from exfiltration. Specifically, the workload asks the Secure Session
Agent for the TLS configuration to use during the handshake, to perform private
key operations, and to validate the peer certificate chain. The Secure Session
Agent's client libraries enable applications to communicate with the Secure
Session Agent during the TLS handshake, and to encrypt traffic to the peer
after the TLS handshake is complete.
This repository contains the source code for the Secure Session Agent's Go
client libraries, which allow gRPC and HTTP Go applications to use the Secure Session
Agent.
Overview (`vendor/github.com/google/uuid/README.md`)
uuid
The uuid package generates and inspects UUIDs based on
RFC 4122
and DCE 1.1: Authentication and Security Services.
This package is based on the github.com/pborman/uuid package (previously named
code.google.com/p/go-uuid). It differs from these earlier packages in that
a UUID is a 16 byte array rather than a byte slice. One loss due to this
change is the ability to represent an invalid UUID (vs a NIL UUID).
Install
go get github.com/google/uuidDocumentation
Full go doc style documentation for the package can be viewed online without
installing this package by using the GoDoc site here:
http://pkg.go.dev/github.com/google/uuid
Overview (`vendor/github.com/gorilla/websocket/README.md`)
Gorilla WebSocket
Gorilla WebSocket is a Go implementation of the
WebSocket protocol.
Documentation
Status
The Gorilla WebSocket package provides a complete and tested implementation of
the WebSocket protocol. The
package API is stable.
Installation
go get github.com/gorilla/websocketProtocol Compliance
The Gorilla WebSocket package passes the server tests in the Autobahn Test
Suite using the application in the examples/autobahn
subdirectory.
Overview (`vendor/github.com/hashicorp/errwrap/README.md`)
errwrap
errwrap is a package for Go that formalizes the pattern of wrapping errors
and checking if an error contains another error.
There is a common pattern in Go of taking a returned error value and
then wrapping it (such as with fmt.Errorf) before returning it. The problem
with this pattern is that you completely lose the original error structure.
Arguably the correct approach is that you should make a custom structure
implementing the error interface, and have the original error as a field
on that structure, such as this example.
This is a good approach, but you have to know the entire chain of possible
rewrapping that happens, when you might just care about one.
errwrap formalizes this pattern (it doesn't matter what approach you use
above) by giving a single interface for wrapping errors, checking if a specific
error is wrapped, and extracting that error.
Installation and Docs
Install using go get github.com/hashicorp/errwrap.
Full documentation is available at
http://godoc.org/github.com/hashicorp/errwrap
Usage
Basic Usage
Below is a very basic example of its usage:
// A function that always returns an error, but wraps it, like a real
// function might.
func tryOpen() error {
_, err := os.Open("/i/dont/exist")
if err != nil {
return errwrap.Wrapf("Doesn't exist: {{err}}", err)
}
return nil
}
func main() {
err := tryOpen()
// We can use the Contains helpers to check if an error contains
// another error. It is safe to do this with a nil error, or with
// an error that doesn't even use the errwrap package.
if errwrap.Contains(err, "does not exist") {
// Do something
}
if errwrap.ContainsType(err, new(os.PathError)) {
// Do something
}
// Or we can use the associated `Get` functions to just extract
// a specific error. This would return nil if that specific error doesn't
// exist.
perr := errwrap.GetType(err, new(os.PathError))
}Custom Types
If you're already making custom types that properly wrap errors, then
you can get all the functionality of errwraps.Contains and such by
implementing the Wrapper interface with just one function. Example:
type AppError {
Code ErrorCode
Err error
}
func (e *AppError) WrappedErrors() []error {
return []error{e.Err}
}Now this works:
err := &AppError{Err: fmt.Errorf("an error")}
if errwrap.ContainsType(err, fmt.Errorf("")) {
// This will work!
}Overview (`vendor/github.com/hashicorp/go-cleanhttp/README.md`)
cleanhttp
Functions for accessing "clean" Go http.Client values
The Go standard library contains a default http.Client calledhttp.DefaultClient. It is a common idiom in Go code to start withhttp.DefaultClient and tweak it as necessary, and in fact, this is
encouraged; from the http package documentation:
The Client's Transport typically has internal state (cached TCP connections),
so Clients should be reused instead of created as needed. Clients are safe for
concurrent use by multiple goroutines.
Unfortunately, this is a shared value, and it is not uncommon for libraries to
assume that they are free to modify it at will. With enough dependencies, it
can be very easy to encounter strange problems and race conditions due to
manipulation of this shared value across libraries and goroutines (clients are
safe for concurrent use, but writing values to the client struct itself is not
protected).
Making things worse is the fact that a bare http.Client will use a defaulthttp.Transport called http.DefaultTransport, which is another global value
that behaves the same way. So it is not simply enough to replacehttp.DefaultClient with &http.Client{}.
This repository provides some simple functions to get a "clean" http.Client
-- one that uses the same default values as the Go standard library, but
returns a client that does not share any state with other clients.
Overview (`vendor/github.com/hashicorp/go-multierror/README.md`)
go-multierror
go-multierror is a package for Go that provides a mechanism for
representing a list of error values as a single error.
This allows a function in Go to return an error that might actually
be a list of errors. If the caller knows this, they can unwrap the
list and access the errors. If the caller doesn't know, the error
formats to a nice human-readable format.
go-multierror is fully compatible with the Go standard library
errors package, including the
functions As, Is, and Unwrap. This provides a standardized approach
for introspecting on error values.
Installation and Docs
Install using go get github.com/hashicorp/go-multierror.
Full documentation is available at
https://pkg.go.dev/github.com/hashicorp/go-multierror
Requires go version 1.13 or newer
go-multierror requires go version 1.13 or newer. Go 1.13 introduced
error wrapping, which
this library takes advantage of.
If you need to use an earlier version of go, you can use the
v1.0.0
tag, which doesn't rely on features in go 1.13.
If you see compile errors that look like the below, it's likely that
you're on an older version of go:
/go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As
/go/src/github.com/hashicorp/go-multierror/multierror.go:117:9: undefined: errors.IsUsage
go-multierror is easy to use and purposely built to be unobtrusive in
existing Go applications/libraries that may not be aware of it.
Building a list of errors
The Append function is used to create a list of errors. This function
behaves a lot like the Go built-in append function: it doesn't matter
if the first argument is nil, a multierror.Error, or any other error,
the function behaves as you would expect.
var result error
if err := step1(); err != nil {
result = multierror.Append(result, err)
}
if err := step2(); err != nil {
result = multierror.Append(result, err)
}
return resultCustomizing the formatting of the errors
By specifying a custom ErrorFormat, you can customize the format
of the Error() string function:
var result *multierror.Error
// ... accumulate errors here, maybe using Append
if result != nil {
result.ErrorFormat = func([]error) string {
return "errors!"
}
}Accessing the list of errors
multierror.Error implements error so if the caller doesn't know about
multierror, it will work just fine. But if you're aware a multierror might
be returned, you can use type switches to access the list of errors:
if err := something(); err != nil {
if merr, ok := err.(*multierror.Error); ok {
// Use merr.Errors
}
}You can also use the standard errors.Unwrap
function. This will continue to unwrap into subsequent errors until none exist.
Extracting an error
The standard library errors.As
function can be used directly with a multierror to extract a specific error:
// Assume err is a multierror value
err := somefunc()
// We want to know if "err" has a "RichErrorType" in it and extract it.
var errRich RichErrorType
if errors.As(err, &errRich) {
// It has it, and now errRich is populated.
}Checking for an exact error value
Some errors are returned as exact errors such as the ErrNotExist
error in the os package. You can check if this error is present by using
the standard errors.Is function.
// Assume err is a multierror value
err := somefunc()
if errors.Is(err, os.ErrNotExist) {
// err contains os.ErrNotExist
}Returning a multierror only if there are errors
If you build a multierror.Error, you can use the ErrorOrNil function
to return an error implementation only if there are errors to return:
var result *multierror.Error
// ... accumulate errors here
// Return the `error` only if errors were added to the multierror, otherwise
// return nil since there are no errors.
return result.ErrorOrNil()Overview (`vendor/github.com/hashicorp/go-retryablehttp/README.md`)
go-retryablehttp
The retryablehttp package provides a familiar HTTP client interface with
automatic retries and exponential backoff. It is a thin wrapper over the
standard net/http client library and exposes nearly the same public API. This
makes retryablehttp very easy to drop into existing programs.
retryablehttp performs automatic retries under certain conditions. Mainly, if
an error is returned by the client (connection errors, etc.), or if a 500-range
response code is received (except 501), then a retry is invoked after a wait
period. Otherwise, the response is returned and left to the caller to
interpret.
The main difference from net/http is that requests which take a request body
(POST/PUT et. al) can have the body provided in a number of ways (some more or
less efficient) that allow "rewinding" the request body if the initial request
fails so that the full request can be attempted again. See the
godoc for more
details.
Version 0.6.0 and before are compatible with Go prior to 1.12. From 0.6.1 onward, Go 1.12+ is required.
From 0.6.7 onward, Go 1.13+ is required.
Example Use
Using this library should look almost identical to what you would do withnet/http. The most simple example of a GET request is shown below:
resp, err := retryablehttp.Get("/foo")
if err != nil {
panic(err)
}The returned response object is an *http.Response, the same thing you would
usually get from net/http. Had the request failed one or more times, the above
call would block and retry with exponential backoff.
Getting a stdlib `*http.Client` with retries
It's possible to convert a *retryablehttp.Client directly to a *http.Client.
This makes use of retryablehttp broadly applicable with minimal effort. Simply
configure a *retryablehttp.Client as you wish, and then call StandardClient():
retryClient := retryablehttp.NewClient()
retryClient.RetryMax = 10
standardClient := retryClient.StandardClient() // *http.ClientFor more usage and examples see the
pkg.go.dev.
Overview (`vendor/github.com/hashicorp/go-rootcerts/README.md`)
rootcerts
Functions for loading root certificates for TLS connections.
Go's standard library crypto/tls provides a common mechanism for configuring
TLS connections in tls.Config. The RootCAs field on this struct is a pool
of certificates for the client to use as a trust store when verifying server
certificates.
This library contains utility functions for loading certificates destined for
that field, as well as one other important thing:
When the RootCAs field is nil, the standard library attempts to load the
host's root CA set. This behavior is OS-specific, and the Darwin
implementation contains a bug that prevents trusted certificates from the
System and Login keychains from being loaded. This library contains
Darwin-specific behavior that works around that bug.
Example Usage
Here's a snippet demonstrating how this library is meant to be used:
func httpClient() (*http.Client, error)
tlsConfig := &tls.Config{}
err := rootcerts.ConfigureTLS(tlsConfig, &rootcerts.Config{
CAFile: os.Getenv("MYAPP_CAFILE"),
CAPath: os.Getenv("MYAPP_CAPATH"),
Certificate: os.Getenv("MYAPP_CERTIFICATE"),
})
if err != nil {
return nil, err
}
c := cleanhttp.DefaultClient()
t := cleanhttp.DefaultTransport()
t.TLSClientConfig = tlsConfig
c.Transport = t
return c, nil
}Overview (`vendor/github.com/hashicorp/go-sockaddr/README.md`)
go-sockaddr
`sockaddr` Library
Socket address convenience functions for Go. go-sockaddr is a convenience
library that makes doing the right thing with IP addresses easy. go-sockaddr
is loosely modeled after the UNIX sockaddr_t and creates a union of the family
of sockaddr_t types (see below for an ascii diagram). Library documentation
is available
at
https://godoc.org/github.com/hashicorp/go-sockaddr.
The primary intent of the library was to make it possible to define heuristics
for selecting the correct IP addresses when a configuration is evaluated at
runtime. See
the
docs,template package,
tests,
and
CLI utility
for details and hints as to how to use this library.
For example, with this library it is possible to find an IP address that:
- is attached to a default route
(GetDefaultInterfaces()) - is contained within a CIDR block (
IfByNetwork()) - is an RFC1918 address
(IfByRFC("1918")) - is ordered
(OrderedIfAddrBy(args)whereargsincludes, but is not limited
to,AscIfType,AscNetworkSize) - excludes all IPv6 addresses
(IfByType("^(IPv4)$")) - is larger than a
/32
(IfByMaskSize(32)) - is not on a
downinterface
(ExcludeIfs("flags", "down")) - preferences an IPv6 address over an IPv4 address
(SortIfByType()+ReverseIfAddrs()); and - excludes any IP in RFC6890 address
(IfByRFC("6890"))
Or any combination or variation therein.
There are also a few simple helper functions such as GetPublicIP andGetPrivateIP which both return strings and select the first public or private
IP address on the default interface, respectively. Similarly, there is also a
helper function called GetInterfaceIP which returns the first usable IP
address on the named interface.
`sockaddr` CLI
Given the possible complexity of the sockaddr library, there is a CLI utility
that accompanies the library, also
calledsockaddr.
Thesockaddr
utility exposes nearly all of the functionality of the library and can be used
either as an administrative tool or testing tool. To install
thesockaddr,
run:
$ go install github.com/hashicorp/go-sockaddr/cmd/sockaddr@latestIf you're familiar with UNIX's sockaddr struct's, the following diagram
mapping the C sockaddr (top) to go-sockaddr structs (bottom) and
interfaces will be helpful:
+-------------------------------------------------------+
| |
| sockaddr |
| SockAddr |
| |
| +--------------+ +----------------------------------+ |
| | sockaddr_un | | | |
| | SockAddrUnix | | sockaddr_in{,6} | |
| +--------------+ | IPAddr | |
| | | |
| | +-------------+ +--------------+ | |
| | | sockaddr_in | | sockaddr_in6 | | |
| | | IPv4Addr | | IPv6Addr | | |
| | +-------------+ +--------------+ | |
| | | |
| +----------------------------------+ |
| |
+-------------------------------------------------------+Inspiration and Design
There were many subtle inspirations that led to this design, but the most direct
inspiration for the filtering syntax was
OpenBSD'spf.conf(5) firewall
syntax that lets you select the first IP address on a given named interface.
The original problem stemmed from:
- needing to create immutable images using Packer that
ran the Consul process (Consul can only use one IP
address at a time); - images that may or may not have multiple interfaces or IP addresses at
runtime; and - we didn't want to rely on configuration management to render out the correct
IP address if the VM image was being used in an auto-scaling group.
Instead we needed some way to codify a heuristic that would correctly select the
right IP address but the input parameters were not known when the image was
created.
Overview (`vendor/github.com/hashicorp/go-version/README.md`)
Versioning Library for Go
go-version is a library for parsing versions and version constraints,
and verifying versions against a set of constraints. go-version
can sort a collection of versions properly, handles prerelease/beta
versions, can increment versions, etc.
Versions used with go-version must follow SemVer.
Installation and Usage
Package documentation can be found on
Go Reference.
Installation can be done with a normal go get:
$ go get github.com/hashicorp/go-versionVersion Parsing and Comparison
v1, err := version.NewVersion("1.2")
v2, err := version.NewVersion("1.5+metadata")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}Version Parsing and Comparison with Prefixes
The library also supports parsing versions with a custom prefix.
Using the WithPrefix option, you can specify a prefix to strip
before parsing the version.
Use WithPrefix when your input strings carry a known release prefix such asdeployment-, controller-, etc.
After parsing, the prefix is not part of the canonical version value. This
means the regular comparison methods such as Compare, LessThan, Equal,
and GreaterThan compare only the stripped version. If you compare versions
from different prefixes with these methods, the prefixes are ignored. If you
need to reject cross-prefix comparisons, inspect the parsed prefixes before
comparing the versions.
v1, _ := version.NewVersion("deployment-v1.2.3-beta+metadata", version.WithPrefix("deployment-"))
v2, _ := version.NewVersion("deployment-v1.2.4", version.WithPrefix("deployment-"))
if v1.LessThan(v2) {
fmt.Printf("%s (%s) is less than %s (%s)\n", v1, v1.Original(), v2, v2.Original())
// Outputs: 1.2.3-beta+metadata (deployment-v1.2.3-beta+metadata) is less than 1.2.4 (deployment-v1.2.4)
}Version Constraints
v1, err := version.NewVersion("1.2")
// Constraints example.
constraints, err := version.NewConstraint(">= 1.0, < 1.4")
if constraints.Check(v1) {
fmt.Printf("%s satisfies constraints %s", v1, constraints)
}Version Sorting
versionsRaw := []string{"1.1", "0.7.1", "1.4-beta", "1.4", "2"}
versions := make([]*version.Version, len(versionsRaw))
for i, raw := range versionsRaw {
v, _ := version.NewVersion(raw)
versions[i] = v
}
// After this, the versions are properly sorted
sort.Sort(version.Collection(versions))Issues and Contributing
If you find an issue with this library, please report an issue. If you'd
like, we welcome any contributions. Fork this library and submit a pull
request.
Overview (`vendor/github.com/hashicorp/golang-lru/README.md`)
golang-lru
Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will
not be updated anymore. The v2 version supports generics and is faster; old code
can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for
backwards compatibility.
Overview (`vendor/github.com/hashicorp/hcl/README.md`)
HCL
HCL (HashiCorp Configuration Language) is a configuration language built
by HashiCorp. The goal of HCL is to build a structured configuration language
that is both human and machine friendly for use with command-line tools, but
specifically targeted towards DevOps tools, servers, etc.
HCL is also fully JSON compatible. That is, JSON can be used as completely
valid input to a system expecting HCL. This helps makes systems
interoperable with other systems.
HCL is heavily inspired by
libucl,
nginx configuration, and others similar.
Why?
A common question when viewing HCL is to ask the question: why not
JSON, YAML, etc.?
Prior to HCL, the tools we built at HashiCorp
used a variety of configuration languages from full programming languages
such as Ruby to complete data structure languages such as JSON. What we
learned is that some people wanted human-friendly configuration languages
and some people wanted machine-friendly languages.
JSON fits a nice balance in this, but is fairly verbose and most
importantly doesn't support comments. With YAML, we found that beginners
had a really hard time determining what the actual structure was, and
ended up guessing more often than not whether to use a hyphen, colon, etc.
in order to represent some configuration key.
Full programming languages such as Ruby enable complex behavior
a configuration language shouldn't usually allow, and also forces
people to learn some set of Ruby.
Because of this, we decided to create our own configuration language
that is JSON-compatible. Our configuration language (HCL) is designed
to be written and modified by humans. The API for HCL allows JSON
as an input so that it is also machine-friendly (machines can generate
JSON instead of trying to generate HCL).
Our goal with HCL is not to alienate other configuration languages.
It is instead to provide HCL as a specialized language for our tools,
and JSON as the interoperability layer.
Syntax
For a complete grammar, please see the parser itself. A high-level overview
of the syntax and grammar is listed here.
Single line comments start with
#or//Multi-line comments are wrapped in
/*and*/. Nested block comments
are not allowed. A multi-line comment (also known as a block comment)
terminates at the first*/found.Values are assigned with the syntax
key = value(whitespace doesn't
matter). The value can be any primitive: a string, number, boolean,
object, or list.Strings are double-quoted and can contain any UTF-8 characters.
Example:"Hello, World"Multi-line strings start with
<<EOFat the end of a line, and end
withEOFon its own line (here documents).
Any text may be used in place ofEOF. Example:
<<FOO
hello
world
FOONumbers are assumed to be base 10. If you prefix a number with 0x,
it is treated as a hexadecimal. If it is prefixed with 0, it is
treated as an octal. Numbers can be in scientific notation: "1e10".Boolean values:
true,falseArrays can be made by wrapping it in
[]. Example:["foo", "bar", 42]. Arrays can contain primitives,
other arrays, and objects. As an alternative, lists
of objects can be created with repeated blocks, using
this structure:hclservice { key = "value" } service { key = "value" }
Objects and nested objects are created using the structure shown below:
variable "ami" {
description = "the AMI to use"
}This would be equivalent to the following json:
{
"variable": {
"ami": {
"description": "the AMI to use"
}
}
}Thanks
Thanks to:
@vstakhov - The original libucl parser
and syntax that HCL was based off of.@fatih - The rewritten HCL parser
in pure Go (no goyacc) and support for a printer.
Overview (`vendor/github.com/huandu/xstrings/README.md`)
xstrings
Go package xstrings is a collection of string functions, which are widely used in other languages but absent in Go package strings.
All functions are well tested and carefully tuned for performance.
Propose a new function
Please review contributing guideline and create new issue to state why it should be included.
Install
Use go get to install this library.
go get github.com/huandu/xstringsAPI document
See GoDoc for full document.
Function list
Go functions have a unique naming style. One, who has experience in other language but new in Go, may have difficulties to find out right string function to use.
Here is a list of functions in strings and xstrings with enough extra information about how to map these functions to their friends in other languages. Hope this list could be helpful for fresh gophers.
Package `xstrings` functions
Keep this table sorted by Function in ascending order.
| Function | Friends | # |
|---|---|---|
| Center | str.center in Python; String#center in Ruby |
#30 |
| Count | String#count in Ruby |
#16 |
| Delete | String#delete in Ruby |
#17 |
| ExpandTabs | str.expandtabs in Python |
#27 |
| FirstRuneToLower | lcfirst in PHP or Perl |
#15 |
| FirstRuneToUpper | String#capitalize in Ruby; ucfirst in PHP or Perl |
#15 |
| Insert | String#insert in Ruby |
#18 |
| LastPartition | str.rpartition in Python; String#rpartition in Ruby |
#19 |
| LeftJustify | str.ljust in Python; String#ljust in Ruby |
#28 |
| Len | mb_strlen in PHP |
#23 |
| Partition | str.partition in Python; String#partition in Ruby |
#10 |
| Reverse | String#reverse in Ruby; strrev in PHP; reverse in Perl |
#7 |
| RightJustify | str.rjust in Python; String#rjust in Ruby |
#29 |
| RuneWidth | - | #27 |
| Scrub | String#scrub in Ruby |
#20 |
| Shuffle | str_shuffle in PHP |
#13 |
| ShuffleSource | str_shuffle in PHP |
#13 |
| Slice | mb_substr in PHP |
#9 |
| Squeeze | String#squeeze in Ruby |
#11 |
| Successor | String#succ or String#next in Ruby |
#22 |
| SwapCase | str.swapcase in Python; String#swapcase in Ruby |
#12 |
| ToCamelCase | String#camelize in RoR |
#1 |
| ToKebab | - | #41 |
| ToPascalCase | - | #1 |
| ToSnakeCase | String#underscore in RoR |
#1 |
| Translate | str.translate in Python; String#tr in Ruby; strtr in PHP; tr/// in Perl |
#21 |
| Width | mb_strwidth in PHP |
#26 |
| WordCount | str_word_count in PHP |
#14 |
| WordSplit | - | #14 |
Package `strings` functions
Keep this table sorted by Function in ascending order.
| Function | Friends |
|---|---|
| Contains | String#include? in Ruby |
| ContainsAny | - |
| ContainsRune | - |
| Count | str.count in Python; substr_count in PHP |
| EqualFold | stricmp in PHP; String#casecmp in Ruby |
| Fields | str.split in Python; split in Perl; String#split in Ruby |
| FieldsFunc | - |
| HasPrefix | str.startswith in Python; String#start_with? in Ruby |
| HasSuffix | str.endswith in Python; String#end_with? in Ruby |
| Index | str.index in Python; String#index in Ruby; strpos in PHP; index in Perl |
| IndexAny | - |
| IndexByte | - |
| IndexFunc | - |
| IndexRune | - |
| Join | str.join in Python; Array#join in Ruby; implode in PHP; join in Perl |
| LastIndex | str.rindex in Python; String#rindex; strrpos in PHP; rindex in Perl |
| LastIndexAny | - |
| LastIndexFunc | - |
| Map | String#each_codepoint in Ruby |
| Repeat | operator * in Python and Ruby; str_repeat in PHP |
| Replace | str.replace in Python; String#sub in Ruby; str_replace in PHP |
| Split | str.split in Python; String#split in Ruby; explode in PHP; split in Perl |
| SplitAfter | - |
| SplitAfterN | - |
| SplitN | str.split in Python; String#split in Ruby; explode in PHP; split in Perl |
| Title | str.title in Python |
| ToLower | str.lower in Python; String#downcase in Ruby; strtolower in PHP; lc in Perl |
| ToLowerSpecial | - |
| ToTitle | - |
| ToTitleSpecial | - |
| ToUpper | str.upper in Python; String#upcase in Ruby; strtoupper in PHP; uc in Perl |
| ToUpperSpecial | - |
| Trim | str.strip in Python; String#strip in Ruby; trim in PHP |
| TrimFunc | - |
| TrimLeft | str.lstrip in Python; String#lstrip in Ruby; ltrim in PHP |
| TrimLeftFunc | - |
| TrimPrefix | - |
| TrimRight | str.rstrip in Python; String#rstrip in Ruby; rtrim in PHP |
| TrimRightFunc | - |
| TrimSpace | str.strip in Python; String#strip in Ruby; trim in PHP |
| TrimSuffix | String#chomp in Ruby; chomp in Perl |
License
This library is licensed under MIT license. See LICENSE for details.
Overview (`vendor/github.com/inconshreveable/mousetrap/README.md`)
mousetrap
mousetrap is a tiny library that answers a single question.
On a Windows machine, was the process invoked by someone double clicking on
the executable file while browsing in explorer?
Motivation
Windows developers unfamiliar with command line tools will often "double-click"
the executable for a tool. Because most CLI tools print the help and then exit
when invoked without arguments, this is often very frustrating for those users.
mousetrap provides a way to detect these invocations so that you can provide
more helpful behavior and instructions on how to run the CLI tool. To see what
this looks like, both from an organizational and a technical perspective, see
https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/
The interface
The library exposes a single interface:
func StartedByExplorer() (bool)Overview (`vendor/github.com/json-iterator/go/README.md`)
A high-performance 100% compatible drop-in replacement of "encoding/json"
Benchmark
Raw Result (easyjson requires static code generation)
| ns/op | allocation bytes | allocation times | |
|---|---|---|---|
| std decode | 35510 ns/op | 1960 B/op | 99 allocs/op |
| easyjson decode | 8499 ns/op | 160 B/op | 4 allocs/op |
| jsoniter decode | 5623 ns/op | 160 B/op | 3 allocs/op |
| std encode | 2213 ns/op | 712 B/op | 5 allocs/op |
| easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op |
| jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op |
Always benchmark with your own workload.
The result depends heavily on the data input.
Usage
100% compatibility with standard lib
Replace
import "encoding/json"
json.Marshal(&data)with
import jsoniter "github.com/json-iterator/go"
var json = jsoniter.ConfigCompatibleWithStandardLibrary
json.Marshal(&data)Replace
import "encoding/json"
json.Unmarshal(input, &data)with
import jsoniter "github.com/json-iterator/go"
var json = jsoniter.ConfigCompatibleWithStandardLibrary
json.Unmarshal(input, &data)How to get
go get github.com/json-iterator/goContribution Welcomed !
Contributors
Report issue or pull request, or email [email protected], or
Overview (`vendor/github.com/kelseyhightower/envconfig/README.md`)
envconfig
import "github.com/kelseyhightower/envconfig"Documentation
See godoc
Usage
Set some environment variables:
export MYAPP_DEBUG=false
export MYAPP_PORT=8080
export MYAPP_USER=Kelsey
export MYAPP_RATE="0.5"
export MYAPP_TIMEOUT="3m"
export MYAPP_USERS="rob,ken,robert"
export MYAPP_COLORCODES="red:1,green:2,blue:3"Write some code:
package main
import (
"fmt"
"log"
"time"
"github.com/kelseyhightower/envconfig"
)
type Specification struct {
Debug bool
Port int
User string
Users []string
Rate float32
Timeout time.Duration
ColorCodes map[string]int
}
func main() {
var s Specification
err := envconfig.Process("myapp", &s)
if err != nil {
log.Fatal(err.Error())
}
format := "Debug: %v\nPort: %d\nUser: %s\nRate: %f\nTimeout: %s\n"
_, err = fmt.Printf(format, s.Debug, s.Port, s.User, s.Rate, s.Timeout)
if err != nil {
log.Fatal(err.Error())
}
fmt.Println("Users:")
for _, u := range s.Users {
fmt.Printf(" %s\n", u)
}
fmt.Println("Color codes:")
for k, v := range s.ColorCodes {
fmt.Printf(" %s: %d\n", k, v)
}
}Results:
Debug: false
Port: 8080
User: Kelsey
Rate: 0.500000
Timeout: 3m0s
Users:
rob
ken
robert
Color codes:
red: 1
green: 2
blue: 3Struct Tag Support
Envconfig supports the use of struct tags to specify alternate, default, and required
environment variables.
For example, consider the following struct:
type Specification struct {
ManualOverride1 string `envconfig:"manual_override_1"`
DefaultVar string `default:"foobar"`
RequiredVar string `required:"true"`
IgnoredVar string `ignored:"true"`
AutoSplitVar string `split_words:"true"`
RequiredAndAutoSplitVar string `required:"true" split_words:"true"`
}Envconfig has automatic support for CamelCased struct elements when thesplit_words:"true" tag is supplied. Without this tag, AutoSplitVar above
would look for an environment variable called MYAPP_AUTOSPLITVAR. With the
setting applied it will look for MYAPP_AUTO_SPLIT_VAR. Note that numbers
will get globbed into the previous word. If the setting does not do the
right thing, you may use a manual override.
Envconfig will process value for ManualOverride1 by populating it with the
value for MYAPP_MANUAL_OVERRIDE_1. Without this struct tag, it would have
instead looked up MYAPP_MANUALOVERRIDE1. With the split_words:"true" tag
it would have looked up MYAPP_MANUAL_OVERRIDE1.
export MYAPP_MANUAL_OVERRIDE_1="this will be the value"
# export MYAPP_MANUALOVERRIDE1="and this will not"If envconfig can't find an environment variable value for MYAPP_DEFAULTVAR,
it will populate it with "foobar" as a default value.
If envconfig can't find an environment variable value for MYAPP_REQUIREDVAR,
it will return an error when asked to process the struct. IfMYAPP_REQUIREDVAR is present but empty, envconfig will not return an error.
If envconfig can't find an environment variable in the form PREFIX_MYVAR, and there
is a struct tag defined, it will try to populate your variable with an environment
variable that directly matches the envconfig tag in your struct definition:
export SERVICE_HOST=127.0.0.1
export MYAPP_DEBUG=truetype Specification struct {
ServiceHost string `envconfig:"SERVICE_HOST"`
Debug bool
}Envconfig won't process a field with the "ignored" tag set to "true", even if a corresponding
environment variable is set.
Supported Struct Field Types
envconfig supports these struct field types:
- string
- int8, int16, int32, int64
- bool
- float32, float64
- slices of any supported type
- maps (keys and values of any supported type)
- encoding.TextUnmarshaler
- encoding.BinaryUnmarshaler
- time.Duration
Embedded structs using these fields are also supported.
Custom Decoders
Any field whose type (or pointer-to-type) implements envconfig.Decoder can
control its own deserialization:
export DNS_SERVER=8.8.8.8type IPDecoder net.IP
func (ipd *IPDecoder) Decode(value string) error {
*ipd = IPDecoder(net.ParseIP(value))
return nil
}
type DNSConfig struct {
Address IPDecoder `envconfig:"DNS_SERVER"`
}Also, envconfig will use a Set(string) error method like from the
flag.Value interface if implemented.
Overview (`vendor/github.com/klauspost/compress/README.md`)
compress
This package provides various compression algorithms.
- zstandard compression and decompression in pure Go.
- S2 is a high performance replacement for Snappy.
- Optimized deflate packages which can be used as a dropin replacement for gzip, zip and zlib.
- snappy is a drop-in replacement for
github.com/golang/snappyoffering better compression and concurrent streams. - huff0 and FSE implementations for raw entropy encoding.
- gzhttp Provides client and server wrappers for handling gzipped/zstd HTTP requests efficiently.
- pgzip is a separate package that provides a very fast parallel gzip implementation.
package usage
Use go get github.com/klauspost/compress@latest to add it to your project.
This package will support the current Go version and 2 versions back.
- Use the
nounsafetag to disable all use of the "unsafe" package. - Use the
noasmtag to disable all assembly across packages.
Use the links above for more information on each.
changelog
Jul 1st, 2026 1.19.0
- zstd: Add true concurrent stream encodingin https://github.com/klauspost/compress/pull/1136
- zstd: arm64 decoder asm by @lizthegrey in https://github.com/klauspost/compress/pull/1160
- flate: Add inflate checkpoints in https://github.com/klauspost/compress/pull/1154
- zstd: avoid unused BuildDict encoder allocation by @snissn in https://github.com/klauspost/compress/pull/1147
- snappy/s2: Limit length of varint in
decodedLenby @eustas in https://github.com/klauspost/compress/pull/1148 - gzhttp: match qvalue parameter case-insensitively (RFC 7231) by @z9z in https://github.com/klauspost/compress/pull/1149
- zip: add NameDecoder callback for legacy encoding rewrite by @SAY-5 in https://github.com/klauspost/compress/pull/1150
- huff0: Allow building tables from histogram in https://github.com/klauspost/compress/pull/1155
- huff0: Allow building table from oversized histogram in https://github.com/klauspost/compress/pull/1156
- s2sx: Clean symlink targets in https://github.com/klauspost/compress/pull/1163
Feb 9th, 2026 1.18.4
- gzhttp: Add zstandard to server handler wrapper https://github.com/klauspost/compress/pull/1121
- zstd: Add ResetWithOptions to encoder/decoder https://github.com/klauspost/compress/pull/1122
- gzhttp: preserve qvalue when extra parameters follow in Accept-Encoding by @analytically in https://github.com/klauspost/compress/pull/1116
Jan 16th, 2026 1.18.3
- Downstream CVE-2025-61728. See golang/go#77102.
Dec 1st, 2025 - 1.18.2
- flate: Fix invalid encoding on level 9 with single value input in https://github.com/klauspost/compress/pull/1115
- flate: reduce stateless allocations by @RXamzin in https://github.com/klauspost/compress/pull/1106
Oct 20, 2025 - 1.18.1 - RETRACTED
- zstd: Add simple zstd EncodeTo/DecodeTo functions https://github.com/klauspost/compress/pull/1079
- zstd: Fix incorrect buffer size in dictionary encodes https://github.com/klauspost/compress/pull/1059
- s2: check for cap, not len of buffer in EncodeBetter/Best by @vdarulis in https://github.com/klauspost/compress/pull/1080
- zlib: Avoiding extra allocation in zlib.reader.Reset by @travelpolicy in https://github.com/klauspost/compress/pull/1086
- gzhttp: remove redundant err check in zstdReader by @ryanfowler in https://github.com/klauspost/compress/pull/1090
- flate: Faster load+store https://github.com/klauspost/compress/pull/1104
- flate: Simplify matchlen https://github.com/klauspost/compress/pull/1101
- flate: Use exact sizes for huffman tables https://github.com/klauspost/compress/pull/1103
Feb 19th, 2025 - 1.18.0
Add unsafe little endian loaders https://github.com/klauspost/compress/pull/1036
fix: check
r.err != nilbut return a nil value errorerrby @alingse in https://github.com/klauspost/compress/pull/1028flate: Simplify L4-6 loading https://github.com/klauspost/compress/pull/1043
flate: Simplify matchlen (remove asm) https://github.com/klauspost/compress/pull/1045
s2: Improve small block compression speed w/o asm https://github.com/klauspost/compress/pull/1048
flate: Fix matchlen L5+L6 https://github.com/klauspost/compress/pull/1049
flate: Cleanup & reduce casts https://github.com/klauspost/compress/pull/1050
See changes to v1.17.x
Oct 11th, 2024 - 1.17.11
- zstd: Fix extra CRC written with multiple Close calls https://github.com/klauspost/compress/pull/1017
- s2: Don't use stack for index tables https://github.com/klauspost/compress/pull/1014
- gzhttp: No content-type on no body response code by @juliens in https://github.com/klauspost/compress/pull/1011
- gzhttp: Do not set the content-type when response has no body by @kevinpollet in https://github.com/klauspost/compress/pull/1013
Sep 23rd, 2024 - 1.17.10
- gzhttp: Add TransportAlwaysDecompress option. https://github.com/klauspost/compress/pull/978
- gzhttp: Add supported decompress request body by @mirecl in https://github.com/klauspost/compress/pull/1002
- s2: Add EncodeBuffer buffer recycling callback https://github.com/klauspost/compress/pull/982
- zstd: Improve memory usage on small streaming encodes https://github.com/klauspost/compress/pull/1007
- flate: read data written with partial flush by @vajexal in https://github.com/klauspost/compress/pull/996
Jun 12th, 2024 - 1.17.9
- s2: Reduce ReadFrom temporary allocations https://github.com/klauspost/compress/pull/949
- flate, zstd: Shave some bytes off amd64 matchLen by @greatroar in https://github.com/klauspost/compress/pull/963
- Upgrade zip/zlib to 1.22.4 upstream https://github.com/klauspost/compress/pull/970 https://github.com/klauspost/compress/pull/971
- zstd: BuildDict fails with RLE table https://github.com/klauspost/compress/pull/951
Apr 9th, 2024 - 1.17.8
- zstd: Reject blocks where reserved values are not 0 https://github.com/klauspost/compress/pull/885
- zstd: Add RLE detection+encoding https://github.com/klauspost/compress/pull/938
Feb 21st, 2024 - 1.17.7
- s2: Add AsyncFlush method: Complete the block without flushing by @Jille in https://github.com/klauspost/compress/pull/927
- s2: Fix literal+repeat exceeds dst crash https://github.com/klauspost/compress/pull/930
Feb 5th, 2024 - 1.17.6
- zstd: Fix incorrect repeat coding in best mode https://github.com/klauspost/compress/pull/923
- s2: Fix DecodeConcurrent deadlock on errors https://github.com/klauspost/compress/pull/925
Jan 26th, 2024 - v1.17.5
- flate: Fix reset with dictionary on custom window encodes https://github.com/klauspost/compress/pull/912
- zstd: Add Frame header encoding and stripping https://github.com/klauspost/compress/pull/908
- zstd: Limit better/best default window to 8MB https://github.com/klauspost/compress/pull/913
- zstd: Speed improvements by @greatroar in https://github.com/klauspost/compress/pull/896 https://github.com/klauspost/compress/pull/910
- s2: Fix callbacks for skippable blocks and disallow 0xfe (Padding) by @Jille in https://github.com/klauspost/compress/pull/916 https://github.com/klauspost/compress/pull/917
https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/compress/pull/918
Dec 1st, 2023 - v1.17.4
- huff0: Speed up symbol counting by @greatroar in https://github.com/klauspost/compress/pull/887
- huff0: Remove byteReader by @greatroar in https://github.com/klauspost/compress/pull/886
- gzhttp: Allow overriding decompression on transport https://github.com/klauspost/compress/pull/892
- gzhttp: Clamp compression level https://github.com/klauspost/compress/pull/890
- gzip: Error out if reserved bits are set https://github.com/klauspost/compress/pull/891
Nov 15th, 2023 - v1.17.3
- fse: Fix max header size https://github.com/klauspost/compress/pull/881
- zstd: Improve better/best compression https://github.com/klauspost/compress/pull/877
- gzhttp: Fix missing content type on Close https://github.com/klauspost/compress/pull/883
Oct 22nd, 2023 - v1.17.2
- zstd: Fix rare CORRUPTION output in "best" mode. See https://github.com/klauspost/compress/pull/876
Oct 14th, 2023 - v1.17.1
- s2: Fix S2 "best" dictionary wrong encoding https://github.com/klauspost/compress/pull/871
- flate: Reduce allocations in decompressor and minor code improvements by @fakefloordiv in https://github.com/klauspost/compress/pull/869
- s2: Fix EstimateBlockSize on 6&7 length input https://github.com/klauspost/compress/pull/867
Sept 19th, 2023 - v1.17.0
- Add experimental dictionary builder https://github.com/klauspost/compress/pull/853
- Add xerial snappy read/writer https://github.com/klauspost/compress/pull/838
- flate: Add limited window compression https://github.com/klauspost/compress/pull/843
- s2: Do 2 overlapping match checks https://github.com/klauspost/compress/pull/839
- flate: Add amd64 assembly matchlen https://github.com/klauspost/compress/pull/837
- gzip: Copy bufio.Reader on Reset by @thatguystone in https://github.com/klauspost/compress/pull/860
See changes to v1.16.x
July 1st, 2023 - v1.16.7
- zstd: Fix default level first dictionary encode https://github.com/klauspost/compress/pull/829
- s2: add GetBufferCapacity() method by @GiedriusS in https://github.com/klauspost/compress/pull/832
June 13, 2023 - v1.16.6
- zstd: correctly ignore WithEncoderPadding(1) by @ianlancetaylor in https://github.com/klauspost/compress/pull/806
- zstd: Add amd64 match length assembly https://github.com/klauspost/compress/pull/824
- gzhttp: Handle informational headers by @rtribotte in https://github.com/klauspost/compress/pull/815
- s2: Improve Better compression slightly https://github.com/klauspost/compress/pull/663
Apr 16, 2023 - v1.16.5
- zstd: readByte needs to use io.ReadFull by @jnoxon in https://github.com/klauspost/compress/pull/802
- gzip: Fix WriterTo after initial read https://github.com/klauspost/compress/pull/804
Apr 5, 2023 - v1.16.4
- zstd: Improve zstd best efficiency by @greatroar and @klauspost in https://github.com/klauspost/compress/pull/784
- zstd: Respect WithAllLitEntropyCompression https://github.com/klauspost/compress/pull/792
- zstd: Fix amd64 not always detecting corrupt data https://github.com/klauspost/compress/pull/785
- zstd: Various minor improvements by @greatroar in https://github.com/klauspost/compress/pull/788 https://github.com/klauspost/compress/pull/794 https://github.com/klauspost/compress/pull/795
- s2: Fix huge block overflow https://github.com/klauspost/compress/pull/779
- s2: Allow CustomEncoder fallback https://github.com/klauspost/compress/pull/780
- gzhttp: Support ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799
Mar 13, 2023 - v1.16.1
- zstd: Speed up + improve best encoder by @greatroar in https://github.com/klauspost/compress/pull/776
- gzhttp: Add optional BREACH mitigation. https://github.com/klauspost/compress/pull/762 https://github.com/klauspost/compress/pull/768 https://github.com/klauspost/compress/pull/769 https://github.com/klauspost/compress/pull/770 https://github.com/klauspost/compress/pull/767
- s2: Add Intel LZ4s converter https://github.com/klauspost/compress/pull/766
- zstd: Minor bug fixes https://github.com/klauspost/compress/pull/771 https://github.com/klauspost/compress/pull/772 https://github.com/klauspost/compress/pull/773
- huff0: Speed up compress1xDo by @greatroar in https://github.com/klauspost/compress/pull/774
Feb 26, 2023 - v1.16.0
- s2: Add Dictionary support. https://github.com/klauspost/compress/pull/685
- s2: Add Compression Size Estimate. https://github.com/klauspost/compress/pull/752
- s2: Add support for custom stream encoder. https://github.com/klauspost/compress/pull/755
- s2: Add LZ4 block converter. https://github.com/klauspost/compress/pull/748
- s2: Support io.ReaderAt in ReadSeeker. https://github.com/klauspost/compress/pull/747
- s2c/s2sx: Use concurrent decoding. https://github.com/klauspost/compress/pull/746
See changes to v1.15.x
Jan 21st, 2023 (v1.15.15)
- deflate: Improve level 7-9 https://github.com/klauspost/compress/pull/739
- zstd: Add delta encoding support by @greatroar in https://github.com/klauspost/compress/pull/728
- zstd: Various speed improvements by @greatroar https://github.com/klauspost/compress/pull/741 https://github.com/klauspost/compress/pull/734 https://github.com/klauspost/compress/pull/736 https://github.com/klauspost/compress/pull/744 https://github.com/klauspost/compress/pull/743 https://github.com/klauspost/compress/pull/745
- gzhttp: Add SuffixETag() and DropETag() options to prevent ETag collisions on compressed responses by @willbicks in https://github.com/klauspost/compress/pull/740
Jan 3rd, 2023 (v1.15.14)
- flate: Improve speed in big stateless blocks https://github.com/klauspost/compress/pull/718
- zstd: Minor speed tweaks by @greatroar in https://github.com/klauspost/compress/pull/716 https://github.com/klauspost/compress/pull/720
- export NoGzipResponseWriter for custom ResponseWriter wrappers by @harshavardhana in https://github.com/klauspost/compress/pull/722
- s2: Add example for indexing and existing stream https://github.com/klauspost/compress/pull/723
Dec 11, 2022 (v1.15.13)
- zstd: Add MaxEncodedSize to encoder https://github.com/klauspost/compress/pull/691
- zstd: Various tweaks and improvements https://github.com/klauspost/compress/pull/693 https://github.com/klauspost/compress/pull/695 https://github.com/klauspost/compress/pull/696 https://github.com/klauspost/compress/pull/701 https://github.com/klauspost/compress/pull/702 https://github.com/klauspost/compress/pull/703 https://github.com/klauspost/compress/pull/704 https://github.com/klauspost/compress/pull/705 https://github.com/klauspost/compress/pull/706 https://github.com/klauspost/compress/pull/707 https://github.com/klauspost/compress/pull/708
Oct 26, 2022 (v1.15.12)
- zstd: Tweak decoder allocs. https://github.com/klauspost/compress/pull/680
- gzhttp: Always delete
HeaderNoCompressionhttps://github.com/klauspost/compress/pull/683
Sept 26, 2022 (v1.15.11)
- flate: Improve level 1-3 compression https://github.com/klauspost/compress/pull/678
- zstd: Improve "best" compression by @nightwolfz in https://github.com/klauspost/compress/pull/677
- zstd: Fix+reduce decompression allocations https://github.com/klauspost/compress/pull/668
- zstd: Fix non-effective noescape tag https://github.com/klauspost/compress/pull/667
Sept 16, 2022 (v1.15.10)
- zstd: Add WithDecodeAllCapLimit https://github.com/klauspost/compress/pull/649
- Add Go 1.19 - deprecate Go 1.16 https://github.com/klauspost/compress/pull/651
- flate: Improve level 5+6 compression https://github.com/klauspost/compress/pull/656
- zstd: Improve "better" compression https://github.com/klauspost/compress/pull/657
- s2: Improve "best" compression https://github.com/klauspost/compress/pull/658
- s2: Improve "better" compression. https://github.com/klauspost/compress/pull/635
- s2: Slightly faster non-assembly decompression https://github.com/klauspost/compress/pull/646
- Use arrays for constant size copies https://github.com/klauspost/compress/pull/659
July 21, 2022 (v1.15.9)
- zstd: Fix decoder crash on amd64 (no BMI) on invalid input https://github.com/klauspost/compress/pull/645
- zstd: Disable decoder extended memory copies (amd64) due to possible crashes https://github.com/klauspost/compress/pull/644
- zstd: Allow single segments up to "max decoded size" https://github.com/klauspost/compress/pull/643
July 13, 2022 (v1.15.8)
- gzip: fix stack exhaustion bug in Reader.Read https://github.com/klauspost/compress/pull/641
- s2: Add Index header trim/restore https://github.com/klauspost/compress/pull/638
- zstd: Optimize seqdeq amd64 asm by @greatroar in https://github.com/klauspost/compress/pull/636
- zstd: Improve decoder memcopy https://github.com/klauspost/compress/pull/637
- huff0: Pass a single bitReader pointer to asm by @greatroar in https://github.com/klauspost/compress/pull/634
- zstd: Branchless getBits for amd64 w/o BMI2 by @greatroar in https://github.com/klauspost/compress/pull/640
- gzhttp: Remove header before writing https://github.com/klauspost/compress/pull/639
June 29, 2022 (v1.15.7)
- s2: Fix absolute forward seeks https://github.com/klauspost/compress/pull/633
- zip: Merge upstream https://github.com/klauspost/compress/pull/631
- zip: Re-add zip64 fix https://github.com/klauspost/compress/pull/624
- zstd: translate fseDecoder.buildDtable into asm by @WojciechMula in https://github.com/klauspost/compress/pull/598
- flate: Faster histograms https://github.com/klauspost/compress/pull/620
- deflate: Use compound hcode https://github.com/klauspost/compress/pull/622
June 3, 2022 (v1.15.6)
- s2: Improve coding for long, close matches https://github.com/klauspost/compress/pull/613
- s2c: Add Snappy/S2 stream recompression https://github.com/klauspost/compress/pull/611
- zstd: Always use configured block size https://github.com/klauspost/compress/pull/605
- zstd: Fix incorrect hash table placement for dict encoding in default https://github.com/klauspost/compress/pull/606
- zstd: Apply default config to ZipDecompressor without options https://github.com/klauspost/compress/pull/608
- gzhttp: Exclude more common archive formats https://github.com/klauspost/compress/pull/612
- s2: Add ReaderIgnoreCRC https://github.com/klauspost/compress/pull/609
- s2: Remove sanity load on index creation https://github.com/klauspost/compress/pull/607
- snappy: Use dedicated function for scoring https://github.com/klauspost/compress/pull/614
- s2c+s2d: Use official snappy framed extension https://github.com/klauspost/compress/pull/610
May 25, 2022 (v1.15.5)
- s2: Add concurrent stream decompression https://github.com/klauspost/compress/pull/602
- s2: Fix final emit oob read crash on amd64 https://github.com/klauspost/compress/pull/601
- huff0: asm implementation of Decompress1X by @WojciechMula https://github.com/klauspost/compress/pull/596
- zstd: Use 1 less goroutine for stream decoding https://github.com/klauspost/compress/pull/588
- zstd: Copy literal in 16 byte blocks when possible https://github.com/klauspost/compress/pull/592
- zstd: Speed up when WithDecoderLowmem(false) https://github.com/klauspost/compress/pull/599
- zstd: faster next state update in BMI2 version of decode by @WojciechMula in https://github.com/klauspost/compress/pull/593
- huff0: Do not check max size when reading table. https://github.com/klauspost/compress/pull/586
- flate: Inplace hashing for level 7-9 https://github.com/klauspost/compress/pull/590
May 11, 2022 (v1.15.4)
May 5, 2022 (v1.15.3)
Apr 26, 2022 (v1.15.2)
Mar 11, 2022 (v1.15.1)
Mar 3, 2022 (v1.15.0)
Both compression and decompression now supports "synchronous" stream operations. This means that whenever "concurrency" is set to 1, they will operate without spawning goroutines.
Stream decompression is now faster on asynchronous, since the goroutine allocation much more effectively splits the workload. On typical streams this will typically use 2 cores fully for decompression. When a stream has finished decoding no goroutines will be left over, so decoders can now safely be pooled and still be garbage collected.
While the release has been extensively tested, it is recommended to testing when upgrading.
See changes to v1.14.xFeb 22, 2022 (v1.14.4)
Feb 17, 2022 (v1.14.3)
Jan 25, 2022 (v1.14.2)
Jan 11, 2022 (v1.14.1)
- s2: Add stream index in #462
- flate: Speed and efficiency improvements in #439 #461 #455 #452 #458
- zstd: Performance improvement in #420 #456 #437 #467 #468
- zstd: add arm64 xxhash assembly in #464
- Add garbled for binaries for s2 in #445
See changes to v1.13.x
Aug 30, 2021 (v1.13.5)
Aug 12, 2021 (v1.13.4)
- Add snappy replacement package.
- zstd: Fix incorrect encoding in "best" mode #415
Aug 3, 2021 (v1.13.3)
Jun 14, 2021 (v1.13.1)
- s2: Add full Snappy output support #396
- zstd: Add configurable Decoder window size #394
- gzhttp: Add header to skip compression #389
- s2: Improve speed with bigger output margin #395
Jun 3, 2021 (v1.13.0)
- Added gzhttp which allows wrapping HTTP servers and clients with GZIP compressors.
- zstd: Detect short invalid signatures #382
- zstd: Spawn decoder goroutine only if needed. #380
See changes to v1.12.x
May 25, 2021 (v1.12.3)
Apr 27, 2021 (v1.12.2)
Apr 14, 2021 (v1.12.1)
- snappy package removed. Upstream added as dependency.
- s2: Better compression in "best" mode #353
- s2sx: Add stdin input and detect pre-compressed from signature #352
- s2c/s2d: Add http as possible input #348
- s2c/s2d/s2sx: Always truncate when writing files #352
- zstd: Reduce memory usage further when using WithLowerEncoderMem #346
- s2: Fix potential problem with amd64 assembly and profilers #349
See changes to v1.11.x
Mar 26, 2021 (v1.11.13)
Mar 5, 2021 (v1.11.12)
- s2: Add
s2sxbinary that creates self extracting archives. - s2: Speed up decompression on non-assembly platforms #328
- s2: Add
Mar 1, 2021 (v1.11.9)
Feb 25, 2021 (v1.11.8)
Jan 14, 2021 (v1.11.7)
Jan 7, 2021 (v1.11.6)
Dec 20, 2020 (v1.11.4)
Nov 15, 2020 (v1.11.3)
Oct 11, 2020 (v1.11.2)
- s2: Fix out of bounds read in "better" block compression #291
Oct 1, 2020 (v1.11.1)
- zstd: Set allLitEntropy true in default configuration #286
Sept 8, 2020 (v1.11.0)
- zstd: Add experimental compression dictionaries #281
- zstd: Fix mixed Write and ReadFrom calls #282
- inflate/gz: Limit variable shifts, ~5% faster decompression #274
See changes to v1.10.x
July 8, 2020 (v1.10.11)
June 23, 2020 (v1.10.10)
- zstd: Skip entropy compression in fastest mode when no matches. #270
June 16, 2020 (v1.10.9):
June 5, 2020 (v1.10.8):
- 1.15x faster zstd block decompression. #265
June 1, 2020 (v1.10.7):
- Added zstd decompression dictionary support
- Increase zstd decompression speed up to 1.19x. #259
- Remove internal reset call in zstd compression and reduce allocations. #263
May 21, 2020: (v1.10.6)
April 12, 2020: (v1.10.5)
- s2-commands: Flush output when receiving SIGINT. #239
Apr 8, 2020: (v1.10.4)
Mar 11, 2020: (v1.10.3)
Feb 27, 2020: (v1.10.2)
Feb 18, 2020: (v1.10.1)
Feb 4, 2020: (v1.10.0)
- Add optional dictionary to stateless deflate. Breaking change, send
nilfor previous behaviour. #216 - Fix buffer overflow on repeated small block deflate. #218
- Allow copying content from an existing ZIP file without decompressing+compressing. #214
- Added S2 AMD64 assembler and various optimizations. Stream speed >10GB/s. #186
See changes prior to v1.10.0
- Add optional dictionary to stateless deflate. Breaking change, send
Jan 20,2020 (v1.9.8) Optimize gzip/deflate with better size estimates and faster table generation. #207 by luyu6056, #206.
Jan 11, 2020: S2 Encode/Decode will use provided buffer if capacity is big enough. #204
Jan 5, 2020: (v1.9.7) Fix another zstd regression in v1.9.5 - v1.9.6 removed.
Jan 4, 2020: (v1.9.6) Regression in v1.9.5 fixed causing corrupt zstd encodes in rare cases.
Jan 4, 2020: Faster IO in s2c + s2d commandline tools compression/decompression. #192
Dec 29, 2019: Removed v1.9.5 since fuzz tests showed a compatibility problem with the reference zstandard decoder.
Dec 29, 2019: (v1.9.5) zstd: 10-20% faster block compression. #199
Dec 29, 2019: zip package updated with latest Go features
Dec 29, 2019: zstd: Single segment flag condintions tweaked. #197
Dec 18, 2019: s2: Faster compression when ReadFrom is used. #198
Dec 10, 2019: s2: Fix repeat length output when just above at 16MB limit.
Dec 10, 2019: zstd: Add function to get decoder as io.ReadCloser. #191
Dec 3, 2019: (v1.9.4) S2: limit max repeat length. #188
Dec 3, 2019: Add WithNoEntropyCompression to zstd #187
Dec 3, 2019: Reduce memory use for tests. Check for leaked goroutines.
Nov 28, 2019 (v1.9.3) Less allocations in stateless deflate.
Nov 28, 2019: 5-20% Faster huff0 decode. Impacts zstd as well. #184
Nov 12, 2019 (v1.9.2) Added Stateless Compression for gzip/deflate.
Nov 12, 2019: Fixed zstd decompression of large single blocks. #180
Nov 11, 2019: Set default s2c block size to 4MB.
Nov 11, 2019: Reduce inflate memory use by 1KB.
Nov 10, 2019: Less allocations in deflate bit writer.
Nov 10, 2019: Fix inconsistent error returned by zstd decoder.
Oct 28, 2019 (v1.9.1) ztsd: Fix crash when compressing blocks. #174
Oct 24, 2019 (v1.9.0) zstd: Fix rare data corruption #173
Oct 24, 2019 zstd: Fix huff0 out of buffer write #171 and always return errors #172
Oct 10, 2019: Big deflate rewrite, 30-40% faster with better compression #105
See changes prior to v1.9.0
Oct 10, 2019: (v1.8.6) zstd: Allow partial reads to get flushed data. #169
Oct 3, 2019: Fix inconsistent results on broken zstd streams.
Sep 25, 2019: Added
-rm(remove source files) and-q(no output except errors) tos2cands2dcommandsSep 16, 2019: (v1.8.4) Add
s2cands2dcommandline tools.Sep 10, 2019: (v1.8.3) Fix s2 decoder Skip.
Sep 7, 2019: zstd: Added WithWindowSize, contributed by ianwilkes.
Sep 5, 2019: (v1.8.2) Add WithZeroFrames which adds full zero payload block encoding option.
Sep 5, 2019: Lazy initialization of zstandard predefined en/decoder tables.
Aug 26, 2019: (v1.8.1) S2: 1-2% compression increase in "better" compression mode.
Aug 26, 2019: zstd: Check maximum size of Huffman 1X compressed literals while decoding.
Aug 24, 2019: (v1.8.0) Added S2 compression, a high performance replacement for Snappy.
Aug 21, 2019: (v1.7.6) Fixed minor issues found by fuzzer. One could lead to zstd not decompressing.
Aug 18, 2019: Add fuzzit continuous fuzzing.
Aug 14, 2019: zstd: Skip incompressible data 2x faster. #147
Aug 4, 2019 (v1.7.5): Better literal compression. #146
July 15, 2019 (v1.7.4): Fix double EOF block in rare cases on zstd encoder.
July 15, 2019 (v1.7.3): Minor speedup/compression increase in default zstd encoder.
July 14, 2019: zstd decoder: Fix decompression error on multiple uses with mixed content.
July 7, 2019 (v1.7.2): Snappy update, zstd decoder potential race fix.
June 17, 2019: zstd decompression bugfix.
June 17, 2019: fix 32 bit builds.
June 17, 2019: Easier use in modules (less dependencies).
June 9, 2019: New stronger "default" zstd compression mode. Matches zstd default compression ratio.
June 5, 2019: 20-40% throughput in zstandard compression and better compression.
June 5, 2019: deflate/gzip compression: Reduce memory usage of lower compression levels.
June 2, 2019: Added zstandard compression!
May 25, 2019: deflate/gzip: 10% faster bit writer, mostly visible in lower levels.
Apr 22, 2019: zstd decompression added.
Aug 1, 2018: Added huff0 README.
Jul 8, 2018: Added Performance Update 2018 below.
Jun 23, 2018: Merged Go 1.11 inflate optimizations. Go 1.9 is now required. Backwards compatible version tagged with v1.3.0.
Apr 2, 2018: Added huff0 en/decoder. Experimental for now, API may change.
Mar 4, 2018: Added FSE Entropy en/decoder. Experimental for now, API may change.
Nov 3, 2017: Add compression Estimate function.
May 28, 2017: Reduce allocations when resetting decoder.
Apr 02, 2017: Change back to official crc32, since changes were merged in Go 1.7.
Jan 14, 2017: Reduce stack pressure due to array copies. See Issue #18625.
Oct 25, 2016: Level 2-4 have been rewritten and now offers significantly better performance than before.
Oct 20, 2016: Port zlib changes from Go 1.7 to fix zlib writer issue. Please update.
Oct 16, 2016: Go 1.7 changes merged. Apples to apples this package is a few percent faster, but has a significantly better balance between speed and compression per level.
Mar 24, 2016: Always attempt Huffman encoding on level 4-7. This improves base 64 encoded data compression.
Mar 24, 2016: Small speedup for level 1-3.
Feb 19, 2016: Faster bit writer, level -2 is 15% faster, level 1 is 4% faster.
Feb 19, 2016: Handle small payloads faster in level 1-3.
Feb 19, 2016: Added faster level 2 + 3 compression modes.
Feb 19, 2016: Rebalanced compression levels, so there is a more even progression in terms of compression. New default level is 5.
Feb 14, 2016: Snappy: Merge upstream changes.
Feb 14, 2016: Snappy: Fix aggressive skipping.
Feb 14, 2016: Snappy: Update benchmark.
Feb 13, 2016: Deflate: Fixed assembler problem that could lead to sub-optimal compression.
Feb 12, 2016: Snappy: Added AMD64 SSE 4.2 optimizations to matching, which makes easy to compress material run faster. Typical speedup is around 25%.
Feb 9, 2016: Added Snappy package fork. This version is 5-7% faster, much more on hard to compress content.
Jan 30, 2016: Optimize level 1 to 3 by not considering static dictionary or storing uncompressed. ~4-5% speedup.
Jan 16, 2016: Optimization on deflate level 1,2,3 compression.
Jan 8 2016: Merge CL 18317: fix reading, writing of zip64 archives.
Dec 8 2015: Make level 1 and -2 deterministic even if write size differs.
Dec 8 2015: Split encoding functions, so hashing and matching can potentially be inlined. 1-3% faster on AMD64. 5% faster on other platforms.
Dec 8 2015: Fixed rare one byte out-of bounds read. Please update!
Nov 23 2015: Optimization on token writer. ~2-4% faster. Contributed by @dsnet.
Nov 20 2015: Small optimization to bit writer on 64 bit systems.
Nov 17 2015: Fixed out-of-bound errors if the underlying Writer returned an error. See #15.
Nov 12 2015: Added io.WriterTo support to gzip/inflate.
Nov 11 2015: Merged CL 16669: archive/zip: enable overriding (de)compressors per file
Oct 15 2015: Added skipping on uncompressible data. Random data speed up >5x.
deflate usage
The packages are drop-in replacements for standard library deflate, gzip, zip, and zlib. Simply replace the import path to use them:
Typical speed is about 2x of the standard library packages.
| old import | new import | Documentation |
|---|---|---|
compress/gzip |
github.com/klauspost/compress/gzip |
gzip |
compress/zlib |
github.com/klauspost/compress/zlib |
zlib |
archive/zip |
github.com/klauspost/compress/zip |
zip |
compress/flate |
github.com/klauspost/compress/flate |
flate |
You may also be interested in pgzip, which is a drop-in replacement for gzip, which support multithreaded compression on big files and the optimized crc32 package used by these packages.
The packages implement the same API as the standard library, so you can use the original godoc documentation: gzip, zip, zlib, flate.
Currently there is only minor speedup on decompression (mostly CRC32 calculation).
Memory usage is typically 1MB for a Writer. stdlib is in the same range.
If you expect to have a lot of concurrently allocated Writers consider using
the stateless compression described below.
For compression performance, see: this spreadsheet.
To disable all assembly add -tags=noasm. This works across all packages.
Stateless compression
This package offers stateless compression as a special option for gzip/deflate.
It will do compression but without maintaining any state between Write calls.
This means there will be no memory kept between Write calls, but compression and speed will be suboptimal.
This is only relevant in cases where you expect to run many thousands of compressors concurrently,
but with very little activity. This is not intended for regular web servers serving individual requests.
Because of this, the size of actual Write calls will affect output size.
In gzip, specify level -3 / gzip.StatelessCompression to enable.
For direct deflate use, NewStatelessWriter and StatelessDeflate are available. See documentation
A bufio.Writer can of course be used to control write sizes. For example, to use a 4KB buffer:
// replace 'ioutil.Discard' with your output.
gzw, err := gzip.NewWriterLevel(ioutil.Discard, gzip.StatelessCompression)
if err != nil {
return err
}
defer gzw.Close()
w := bufio.NewWriterSize(gzw, 4096)
defer w.Flush()
// Write to 'w'This will only use up to 4KB in memory when the writer is idle.
Compression is almost always worse than the fastest compression level
and each write will allocate (a little) memory.
Other packages
Here are other packages of good quality and pure Go (no cgo wrappers or autoconverted code):
- github.com/pierrec/lz4 - strong multithreaded LZ4 compression.
- github.com/cosnicolaou/pbzip2 - multithreaded bzip2 decompression.
- github.com/dsnet/compress - brotli decompression, bzip2 writer.
- github.com/ronanh/intcomp - Integer compression.
- github.com/spenczar/fpc - Float compression.
- github.com/minio/zipindex - External ZIP directory index.
- github.com/ybirader/pzip - Fast concurrent zip archiver and extractor.
license
This code is licensed under the same conditions as the original Go code. See LICENSE file.
Overview (`vendor/github.com/mitchellh/copystructure/README.md`)
copystructure
copystructure is a Go library for deep copying values in Go.
This allows you to copy Go values that may contain reference values
such as maps, slices, or pointers, and copy their data as well instead
of just their references.
Installation
Standard go get:
$ go get github.com/mitchellh/copystructureUsage & Example
For usage and examples see the Godoc.
The Copy function has examples associated with it there.
Overview (`vendor/github.com/mitchellh/go-homedir/README.md`)
go-homedir
This is a Go library for detecting the user's home directory without
the use of cgo, so the library can be used in cross-compilation environments.
Usage is incredibly simple, just call homedir.Dir() to get the home directory
for a user, and homedir.Expand() to expand the ~ in a path to the home
directory.
Why not just use os/user? The built-in os/user package requires
cgo on Darwin systems. This means that any Go code that uses that package
cannot cross compile. But 99% of the time the use for os/user is just to
retrieve the home directory, which we can do for the current user without
cgo. This library does that, enabling cross-compilation.
Overview (`vendor/github.com/mitchellh/mapstructure/README.md`)
mapstructure [](https://godoc.org/github.com/mitchellh/mapstructure)
mapstructure is a Go library for decoding generic map values to structures
and vice versa, while providing helpful error handling.
This library is most useful when decoding values from some data stream (JSON,
Gob, etc.) where you don't quite know the structure of the underlying data
until you read a part of it. You can therefore read a map[string]interface{}
and use this library to decode it into the proper underlying native Go
structure.
Installation
Standard go get:
$ go get github.com/mitchellh/mapstructureUsage & Example
For usage and examples see the Godoc.
The Decode function has examples associated with it there.
But Why?!
Go offers fantastic standard libraries for decoding formats such as JSON.
The standard method is to have a struct pre-created, and populate that struct
from the bytes of the encoded format. This is great, but the problem is if
you have configuration or an encoding that changes slightly depending on
specific fields. For example, consider this JSON:
{
"type": "person",
"name": "Mitchell"
}Perhaps we can't populate a specific structure without first reading
the "type" field from the JSON. We could always do two passes over the
decoding of the JSON (reading the "type" first, and the rest later).
However, it is much simpler to just decode this into a map[string]interface{}
structure, read the "type" key, then use something like this library
to decode it into the proper structure.
Overview (`vendor/github.com/mitchellh/reflectwalk/README.md`)
reflectwalk
reflectwalk is a Go library for "walking" a value in Go using reflection,
in the same way a directory tree can be "walked" on the filesystem. Walking
a complex structure can allow you to do manipulations on unknown structures
such as those decoded from JSON.
Overview (`vendor/github.com/moby/spdystream/README.md`)
SpdyStream
A multiplexed stream library using spdy
Usage
Client example (connecting to mirroring server without auth)
package main
import (
"fmt"
"github.com/moby/spdystream"
"net"
"net/http"
)
func main() {
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
panic(err)
}
spdyConn, err := spdystream.NewConnection(conn, false)
if err != nil {
panic(err)
}
go spdyConn.Serve(spdystream.NoOpStreamHandler)
stream, err := spdyConn.CreateStream(http.Header{}, nil, false)
if err != nil {
panic(err)
}
stream.Wait()
fmt.Fprint(stream, "Writing to stream")
buf := make([]byte, 25)
stream.Read(buf)
fmt.Println(string(buf))
stream.Close()
}Server example (mirroring server without auth)
package main
import (
"github.com/moby/spdystream"
"net"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8080")
if err != nil {
panic(err)
}
for {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
spdyConn, err := spdystream.NewConnection(conn, true)
if err != nil {
panic(err)
}
go spdyConn.Serve(spdystream.MirrorStreamHandler)
}
}Copyright and license
Copyright 2013-2021 Docker, inc. Released under the Apache 2.0 license.
Overview (`vendor/github.com/modern-go/concurrent/README.md`)
concurrent
- concurrent.Map: backport sync.Map for go below 1.9
- concurrent.Executor: goroutine with explicit ownership and cancellable
concurrent.Map
because sync.Map is only available in go 1.9, we can use concurrent.Map to make code portable
m := concurrent.NewMap()
m.Store("hello", "world")
elem, found := m.Load("hello")
// elem will be "world"
// found will be trueconcurrent.Executor
executor := concurrent.NewUnboundedExecutor()
executor.Go(func(ctx context.Context) {
everyMillisecond := time.NewTicker(time.Millisecond)
for {
select {
case <-ctx.Done():
fmt.Println("goroutine exited")
return
case <-everyMillisecond.C:
// do something
}
}
})
time.Sleep(time.Second)
executor.StopAndWaitForever()
fmt.Println("executor stopped")attach goroutine to executor instance, so that we can
- cancel it by stop the executor with Stop/StopAndWait/StopAndWaitForever
- handle panic by callback: the default behavior will no longer crash your application
Overview (`vendor/github.com/modern-go/reflect2/README.md`)
reflect2
reflect api that avoids runtime reflect.Value cost
- reflect get/set interface{}, with type checking
- reflect get/set unsafe.Pointer, without type checking
reflect2.TypeByNameworks likeClass.forNamefound in java
json-iterator use this package to save runtime dispatching cost.
This package is designed for low level libraries to optimize reflection performance.
General application should still use reflect standard library.
reflect2.TypeByName
// given package is github.com/your/awesome-package
type MyStruct struct {
// ...
}
// will return the type
reflect2.TypeByName("awesome-package.MyStruct")
// however, if the type has not been used
// it will be eliminated by compiler, so we can not get it in runtimereflect2 get/set interface{}
valType := reflect2.TypeOf(1)
i := 1
j := 10
valType.Set(&i, &j)
// i will be 10to get set type, always use its pointer *type
reflect2 get/set unsafe.Pointer
valType := reflect2.TypeOf(1)
i := 1
j := 10
valType.UnsafeSet(unsafe.Pointer(&i), unsafe.Pointer(&j))
// i will be 10to get set type, always use its pointer *type
benchmark
Benchmark is not necessary for this package. It does nothing actually.
As it is just a thin wrapper to make go runtime public.
Both reflect2 and reflect call same function
provided by runtime package exposed by go language.
unsafe safety
Instead of casting []byte to sliceHeader in your application using unsafe.
We can use reflect2 instead. This way, if sliceHeader changes in the future,
only reflect2 need to be upgraded.
reflect2 tries its best to keep the implementation same as reflect (by testing).
Overview (`vendor/github.com/natefinch/atomic/README.md`)
atomic
import "github.com/natefinch/atomic"atomic is a go package for atomic file writing
By default, writing to a file in go (and generally any language) can fail
partway through... you then have a partially written file, which probably was
truncated when the write began, and bam, now you've lost data.
This go package avoids this problem, by writing first to a temp file, and then
overwriting the target file in an atomic way. This is easy on linux, os.Rename
just is atomic. However, on Windows, os.Rename is not atomic, and so bad things
can happen. By wrapping the windows API moveFileEx, we can ensure that the move
is atomic, and we can be safe in knowing that either the move succeeds entirely,
or neither file will be modified.
func ReplaceFile
func ReplaceFile(source, destination string) errorReplaceFile atomically replaces the destination file or directory with the
source. It is guaranteed to either replace the target file entirely, or not
change either file.
func WriteFile
func WriteFile(filename string, r io.Reader) (err error)WriteFile atomically writes the contents of r to the specified filepath. If
an error occurs, the target file is guaranteed to be either fully written, or
not written at all. WriteFile overwrites any file that exists at the
location (but only if the write fully succeeds, otherwise the existing file
is unmodified).
Overview (`vendor/github.com/opencontainers/go-digest/README.md`)
go-digest
Common digest package used across the container ecosystem.
Please see the godoc for more information.
What is a digest?
A digest is just a hash.
The most common use case for a digest is to create a content identifier for use in Content Addressable Storage systems:
id := digest.FromBytes([]byte("my content"))In the example above, the id can be used to uniquely identify the byte slice "my content".
This allows two disparate applications to agree on a verifiable identifier without having to trust one another.
An identifying digest can be verified, as follows:
if id != digest.FromBytes([]byte("my content")) {
return errors.New("the content has changed!")
}A Verifier type can be used to handle cases where an io.Reader makes more sense:
rd := getContent()
verifier := id.Verifier()
io.Copy(verifier, rd)
if !verifier.Verified() {
return errors.New("the content has changed!")
}Using Merkle DAGs, this can power a rich, safe, content distribution system.
Usage
While the godoc is considered the best resource, a few important items need to be called out when using this package.
Make sure to import the hash implementations into your application or the package will panic.
You should have something like the following in the main (or other entrypoint) of your application:goimport ( _ "crypto/sha256" _ "crypto/sha512" )This may seem inconvenient but it allows you replace the hash
implementations with others, such as https://github.com/stevvooe/resumable.Even though
digest.Digestmay be assemblable as a string, always verify your input withdigest.Parseor useDigest.Validatewhen accepting untrusted input.
While there are measures to avoid common problems, this will ensure you have valid digests in the rest of your application.While alternative encodings of hash values (digests) are possible (for example, base64), this package deals exclusively with hex-encoded digests.
Stability
The Go API, at this stage, is considered stable, unless otherwise noted.
As always, before using a package export, read the godoc.
Contributing
This package is considered fairly complete.
It has been in production in thousands (millions?) of deployments and is fairly battle-hardened.
New additions will be met with skepticism.
If you think there is a missing feature, please file a bug clearly describing the problem and the alternatives you tried before submitting a PR.
Code of Conduct
Participation in the OpenContainers community is governed by OpenContainer's Code of Conduct.
Security
If you find an issue, please follow the security protocol to report it.
Copyright and license
Copyright Β© 2019, 2020 OCI Contributors
Copyright Β© 2016 Docker, Inc.
All rights reserved, except as follows.
Code is released under the Apache 2.0 license.
This README.md file and the CONTRIBUTING.md file are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file LICENSE.docs.
You may obtain a duplicate copy of the same license, titled CC BY-SA 4.0, at http://creativecommons.org/licenses/by-sa/4.0/.
Overview (`vendor/github.com/pkg/browser/README.md`)
browser
import "github.com/pkg/browser"Package browser provides helpers to open files, readers, and urls in a browser window.
The choice of which browser is started is entirely client dependant.
Variables
var Stderr io.Writer = os.StderrStderr is the io.Writer to which executed commands write standard error.
var Stdout io.Writer = os.StdoutStdout is the io.Writer to which executed commands write standard output.
func OpenFile
func OpenFile(path string) errorOpenFile opens new browser window for the file path.
func OpenReader
func OpenReader(r io.Reader) errorOpenReader consumes the contents of r and presents the
results in a new browser window.
func OpenURL
func OpenURL(url string) errorOpenURL opens a new browser window pointing to url.
Generated by godoc2md
Overview (`vendor/github.com/pkg/errors/README.md`)
errors [](https://travis-ci.org/pkg/errors) [](https://ci.appveyor.com/project/davecheney/errors/branch/master) [](http://godoc.org/github.com/pkg/errors) [](https://goreportcard.com/report/github.com/pkg/errors) [](https://sourcegraph.com/github.com/pkg/errors?badge)
Package errors provides simple error handling primitives.
go get github.com/pkg/errors
The traditional error handling idiom in Go is roughly akin to
if err != nil {
return err
}which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
Adding context to an error
The errors.Wrap function returns a new error that adds context to the original error. For example
_, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrap(err, "read failed")
}Retrieving the cause of an error
Using errors.Wrap constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by errors.Cause.
type causer interface {
Cause() error
}errors.Cause will recursively retrieve the topmost error which does not implement causer, which is assumed to be the original cause. For example:
switch err := errors.Cause(err).(type) {
case *MyError:
// handle specifically
default:
// unknown error
}Read the package documentation for more information.
Roadmap
With the upcoming Go2 error proposals this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows:
- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible)
- 1.0. Final release.
Contributing
Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports.
Before sending a PR, please discuss your change by raising an issue.
License
BSD-2-Clause
Overview (`vendor/github.com/prometheus/otlptranslator/README.md`)
OTLP Prometheus Translator
A Go library for converting OpenTelemetry Protocol (OTLP) metric and attribute names to Prometheus-compliant formats. This is an internal library for both Prometheus and Open Telemetry, without any stability guarantees for external usage.
Part of the Prometheus ecosystem, following the OpenTelemetry to Prometheus compatibility specification.
Features
- Metric Name and Label Translation: Convert OTLP metric names and attributes to Prometheus-compliant format
- Unit Handling: Translate OTLP units to Prometheus unit conventions
- Type-Aware Suffixes: Optionally append
_total,_ratiobased on metric type - Namespace Support: Add configurable namespace prefixes
- UTF-8 Support: Choose between Prometheus legacy scheme compliant metric/label names (
[a-zA-Z0-9:_]) or untranslated metric/label names - Translation Strategy Configuration: Select a translation strategy with a standard set of strings.
Installation
go get github.com/prometheus/otlptranslatorQuick Start
package main
import (
"fmt"
"github.com/prometheus/otlptranslator"
)
func main() {
// Create a metric namer using traditional Prometheus name translation, with suffixes added and UTF-8 disallowed.
strategy := otlptranslator.UnderscoreEscapingWithSuffixes
namer := otlptranslator.NewMetricNamer("myapp", strategy)
// Translate OTLP metric to Prometheus format
metric := otlptranslator.Metric{
Name: "http.server.request.duration",
Unit: "s",
Type: otlptranslator.MetricTypeHistogram,
}
fmt.Println(namer.Build(metric)) // Output: myapp_http_server_request_duration_seconds
// Translate label names
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: false}
fmt.Println(labelNamer.Build("http.method")) // Output: http_method
}Usage Examples
Metric Name Translation
namer := otlptranslator.MetricNamer{WithMetricSuffixes: true, UTF8Allowed: false}
// Counter gets _total suffix
counter := otlptranslator.Metric{
Name: "requests.count", Unit: "1", Type: otlptranslator.MetricTypeMonotonicCounter,
}
fmt.Println(namer.Build(counter)) // requests_count_total
// Gauge with unit conversion
gauge := otlptranslator.Metric{
Name: "memory.usage", Unit: "By", Type: otlptranslator.MetricTypeGauge,
}
fmt.Println(namer.Build(gauge)) // memory_usage_bytes
// Dimensionless gauge gets _ratio suffix
ratio := otlptranslator.Metric{
Name: "cpu.utilization", Unit: "1", Type: otlptranslator.MetricTypeGauge,
}
fmt.Println(namer.Build(ratio)) // cpu_utilization_ratioLabel Translation
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: false}
labelNamer.Build("http.method") // http_method
labelNamer.Build("123invalid") // key_123invalid
labelNamer.Build("_private") // key_private
labelNamer.Build("__reserved__") // __reserved__ (preserved)
labelNamer.Build("label@with$symbols") // label_with_symbolsUnit Translation
unitNamer := otlptranslator.UnitNamer{UTF8Allowed: false}
unitNamer.Build("s") // seconds
unitNamer.Build("By") // bytes
unitNamer.Build("requests/s") // requests_per_second
unitNamer.Build("1") // "" (dimensionless)Configuration Options
// Prometheus-compliant mode - supports [a-zA-Z0-9:_]
compliantNamer := otlptranslator.MetricNamer{UTF8Allowed: false, WithMetricSuffixes: true}
// Transparent pass-through mode, aka "NoTranslation"
utf8Namer := otlptranslator.MetricNamer{UTF8Allowed: true, WithMetricSuffixes: false}
utf8Namer = otlptranslator.NewMetricNamer("", otlpTranslator.NoTranslation)
// With namespace and suffixes
productionNamer := otlptranslator.MetricNamer{
Namespace: "myservice",
WithMetricSuffixes: true,
UTF8Allowed: false,
}License
Licensed under the Apache License 2.0 - see the LICENSE file for details.
Overview (`vendor/github.com/prometheus/procfs/README.md`)
procfs
This package provides functions to retrieve system, kernel, and process
metrics from the pseudo-filesystems /proc and /sys.
WARNING: This package is a work in progress. Its API may still break in
backwards-incompatible ways without warnings. Use it at your own risk.
Usage
The procfs library is organized by packages based on whether the gathered data is coming from
/proc, /sys, or both. Each package contains an FS type which represents the path to either /proc,
/sys, or both. For example, cpu statistics are gathered from/proc/stat and are available via the root procfs package. First, the proc filesystem mount
point is initialized, and then the stat information is read.
fs, err := procfs.NewFS("/proc")
stats, err := fs.Stat()Some sub-packages such as blockdevice, require access to both the proc and sys filesystems.
fs, err := blockdevice.NewFS("/proc", "/sys")
stats, err := fs.ProcDiskstats()Package Organization
The packages in this project are organized according to (1) whether the data comes from the /proc or/sys filesystem and (2) the type of information being retrieved. For example, most process information
can be gathered from the functions in the root procfs package. Information about block devices such as disk drives
is available in the blockdevices sub-package.
Building and Testing
The procfs library is intended to be built as part of another application, so there are no distributable binaries.
However, most of the API includes unit tests which can be run with make test.
Updating Test Fixtures
The procfs library includes a set of test fixtures which include many example files from
the /proc and /sys filesystems. These fixtures are included as a ttar file
which is extracted automatically during testing. To add/update the test fixtures, first
ensure the testdata/fixtures directory is up to date by removing the existing directory and then
extracting the ttar file using make testdata/fixtures/.unpacked or just make test.
rm -rf testdata/fixtures
make testNext, make the required changes to the extracted files in the testdata/fixtures directory. When
the changes are complete, run make update_fixtures to create a new fixtures.ttar file
based on the updated fixtures directory. And finally, verify the changes usinggit diff testdata/fixtures.ttar.
Overview (`vendor/github.com/ryanuber/go-glob/README.md`)
String globbing in golang [](https://travis-ci.org/ryanuber/go-glob)
go-glob is a single-function library implementing basic string glob support.
Globs are an extremely user-friendly way of supporting string matching without
requiring knowledge of regular expressions or Go's particular regex engine. Most
people understand that if you put a * character somewhere in a string, it is
treated as a wildcard. Surprisingly, this functionality isn't found in Go's
standard library, except for path.Match, which is intended to be used while
comparing paths (not arbitrary strings), and contains specialized logic for this
use case. A better solution might be a POSIX basic (non-ERE) regular expression
engine for Go, which doesn't exist currently.
Example
package main
import "github.com/ryanuber/go-glob"
func main() {
glob.Glob("*World!", "Hello, World!") // true
glob.Glob("Hello,*", "Hello, World!") // true
glob.Glob("*ello,*", "Hello, World!") // true
glob.Glob("World!", "Hello, World!") // false
glob.Glob("/home/*", "/home/ryanuber/.bashrc") // true
}Overview (`vendor/github.com/shopspring/decimal/README.md`)
decimal
Arbitrary-precision fixed-point decimal numbers in go.
Note: Decimal library can "only" represent numbers with a maximum of 2^31 digits after the decimal point.
Features
- The zero-value is 0, and is safe to use without initialization
- Addition, subtraction, multiplication with no loss of precision
- Division with specified precision
- Database/sql serialization/deserialization
- JSON and XML serialization/deserialization
Install
Run go get github.com/shopspring/decimal
Requirements
Decimal library requires Go version >=1.10
Documentation
http://godoc.org/github.com/shopspring/decimal
Usage
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main() {
price, err := decimal.NewFromString("136.02")
if err != nil {
panic(err)
}
quantity := decimal.NewFromInt(3)
fee, _ := decimal.NewFromString(".035")
taxRate, _ := decimal.NewFromString(".08875")
subtotal := price.Mul(quantity)
preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1)))
total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1)))
fmt.Println("Subtotal:", subtotal) // Subtotal: 408.06
fmt.Println("Pre-tax:", preTax) // Pre-tax: 422.3421
fmt.Println("Taxes:", total.Sub(preTax)) // Taxes: 37.482861375
fmt.Println("Total:", total) // Total: 459.824961375
fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
}Alternative libraries
When working with decimal numbers, you might face problems this library is not perfectly suited for.
Fortunately, thanks to the wonderful community we have a dozen other libraries that you can choose from.
Explore other alternatives to find the one that best fits your needs :)
- cockroachdb/apd - arbitrary precision, mutable and rich API similar to
big.Int, more performant than this library - alpacahq/alpacadecimal - high performance, low precision (12 digits), fully compatible API with this library
- govalues/decimal - high performance, zero-allocation, low precision (19 digits)
- greatcloak/decimal - fork focusing on billing and e-commerce web application related use cases, includes out-of-the-box BSON marshaling support
FAQ
Why don't you just use float64?
Because float64 (or any binary floating point type, actually) can't represent
numbers such as 0.1 exactly.
Consider this code: http://play.golang.org/p/TQBd4yJe6B You might expect that
it prints out 10, but it actually prints 9.999999999999831. Over time,
these small errors can really add up!
Why don't you just use big.Rat?
big.Rat is fine for representing rational numbers, but Decimal is better for
representing money. Why? Here's a (contrived) example:
Let's say you use big.Rat, and you have two numbers, x and y, both
representing 1/3, and you have z = 1 - x - y = 1/3. If you print each one
out, the string output has to stop somewhere (let's say it stops at 3 decimal
digits, for simplicity), so you'll get 0.333, 0.333, and 0.333. But where did
the other 0.001 go?
Here's the above example as code: http://play.golang.org/p/lCZZs0w9KE
With Decimal, the strings being printed out represent the number exactly. So,
if you have x = y = 1/3 (with precision 3), they will actually be equal to
0.333, and when you do z = 1 - x - y, z will be equal to .334. No money is
unaccounted for!
You still have to be careful. If you want to split a number N 3 ways, you
can't just send N/3 to three different people. You have to pick one to sendN - (2/3*N) to. That person will receive the fraction of a penny remainder.
But, it is much easier to be careful with Decimal than with big.Rat.
Why isn't the API similar to big.Int's?
big.Int's API is built to reduce the number of memory allocations for maximal
performance. This makes sense for its use-case, but the trade-off is that the
API is awkward and easy to misuse.
For example, to add two big.Ints, you do: z := new(big.Int).Add(x, y). A
developer unfamiliar with this API might try to do z := a.Add(a, b). This
modifies a and sets z as an alias for a, which they might not expect. It
also modifies any other aliases to a.
Here's an example of the subtle bugs you can introduce with big.Int's API:
https://play.golang.org/p/x2R_78pa8r
In contrast, it's difficult to make such mistakes with decimal. Decimals
behave like other go numbers types: even though a = b will not deep copyb into a, it is impossible to modify a Decimal, since all Decimal methods
return new Decimals and do not modify the originals. The downside is that
this causes extra allocations, so Decimal is less performant. My assumption
is that if you're using Decimals, you probably care more about correctness
than performance.
License
The MIT License (MIT)
This is a heavily modified fork of fpd.Decimal, which was also released under the MIT License.
Overview (`vendor/github.com/shurcooL/githubv4/README.md`)
githubv4
Package githubv4 is a client library for accessing GitHub GraphQL API v4 (https://developer.github.com/v4/).
If you're looking for a client library for GitHub REST API v3, the recommended package is github.com/google/go-github/github.
Status: In research and development. The API will change when opportunities for improvement are discovered; it is not yet frozen.
Focus
- Friendly, simple and powerful API.
- Correctness, high performance and efficiency.
- Support all of GitHub GraphQL API v4 via code generation from schema.
Installation
githubv4 requires Go version 1.8 or later.
go get -u github.com/shurcooL/githubv4Usage
Authentication
GitHub GraphQL API v4 requires authentication. The githubv4 package does not directly handle authentication. Instead, when creating a new client, you're expected to pass an http.Client that performs authentication. The easiest and recommended way to do this is to use the golang.org/x/oauth2 package. You'll need an OAuth token from GitHub (for example, a personal API token) with the right scopes. Then:
import "golang.org/x/oauth2"
func main() {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
)
httpClient := oauth2.NewClient(context.Background(), src)
client := githubv4.NewClient(httpClient)
// Use client...
}Simple Query
To make a query, you need to define a Go type that corresponds to the GitHub GraphQL schema, and contains the fields you're interested in querying. You can look up the GitHub GraphQL schema at https://developer.github.com/v4/query/.
For example, to make the following GraphQL query:
query {
viewer {
login
createdAt
}
}You can define this variable:
var query struct {
Viewer struct {
Login githubv4.String
CreatedAt githubv4.DateTime
}
}Then call client.Query, passing a pointer to it:
err := client.Query(context.Background(), &query, nil)
if err != nil {
// Handle error.
}
fmt.Println(" Login:", query.Viewer.Login)
fmt.Println("CreatedAt:", query.Viewer.CreatedAt)
// Output:
// Login: gopher
// CreatedAt: 2017-05-26 21:17:14 +0000 UTCScalar Types
For each scalar in the GitHub GraphQL schema listed at https://developer.github.com/v4/scalar/, there is a corresponding Go type in package githubv4.
You can use these types when writing queries:
var query struct {
Viewer struct {
Login githubv4.String
CreatedAt githubv4.DateTime
IsBountyHunter githubv4.Boolean
BioHTML githubv4.HTML
WebsiteURL githubv4.URI
}
}
// Call client.Query() and use results in query...However, depending on how you're planning to use the results of your query, it's often more convenient to use other Go types.
The encoding/json rules are used for converting individual JSON-encoded fields from a GraphQL response into Go values. See https://godoc.org/encoding/json#Unmarshal for details. The json.Unmarshaler interface is respected.
That means you can simplify the earlier query by using predeclared Go types:
// import "time"
var query struct {
Viewer struct {
Login string // E.g., "gopher".
CreatedAt time.Time // E.g., time.Date(2017, 5, 26, 21, 17, 14, 0, time.UTC).
IsBountyHunter bool // E.g., true.
BioHTML string // E.g., `I am learning <a href="https://graphql.org">GraphQL</a>!`.
WebsiteURL string // E.g., "https://golang.org".
}
}
// Call client.Query() and use results in query...The DateTime scalar is described as "an ISO-8601 encoded UTC date string". If you wanted to fetch in that form without parsing it into a time.Time, you can use the string type. For example, this would work:
// import "html/template"
type MyBoolean bool
var query struct {
Viewer struct {
Login string // E.g., "gopher".
CreatedAt string // E.g., "2017-05-26T21:17:14Z".
IsBountyHunter MyBoolean // E.g., MyBoolean(true).
BioHTML template.HTML // E.g., template.HTML(`I am learning <a href="https://graphql.org">GraphQL</a>!`).
WebsiteURL template.URL // E.g., template.URL("https://golang.org").
}
}
// Call client.Query() and use results in query...Arguments and Variables
Often, you'll want to specify arguments on some fields. You can use the graphql struct field tag for this.
For example, to make the following GraphQL query:
{
repository(owner: "octocat", name: "Hello-World") {
description
}
}You can define this variable:
var q struct {
Repository struct {
Description string
} `graphql:"repository(owner: \"octocat\", name: \"Hello-World\")"`
}Then call client.Query:
err := client.Query(context.Background(), &q, nil)
if err != nil {
// Handle error.
}
fmt.Println(q.Repository.Description)
// Output:
// My first repository on GitHub!However, that'll only work if the arguments are constant and known in advance. Otherwise, you will need to make use of variables. Replace the constants in the struct field tag with variable names:
// fetchRepoDescription fetches description of repo with owner and name.
func fetchRepoDescription(ctx context.Context, owner, name string) (string, error) {
var q struct {
Repository struct {
Description string
} `graphql:"repository(owner: $owner, name: $name)"`
}When sending variables to GraphQL, you need to use exact types that match GraphQL scalar types, otherwise the GraphQL server will return an error.
So, define a variables map with their values that are converted to GraphQL scalar types:
variables := map[string]interface{}{
"owner": githubv4.String(owner),
"name": githubv4.String(name),
}Finally, call client.Query providing variables:
err := client.Query(ctx, &q, variables)
return q.Repository.Description, err
}Inline Fragments
Some GraphQL queries contain inline fragments. You can use the graphql struct field tag to express them.
For example, to make the following GraphQL query:
{
repositoryOwner(login: "github") {
login
... on Organization {
description
}
... on User {
bio
}
}
}You can define this variable:
var q struct {
RepositoryOwner struct {
Login string
Organization struct {
Description string
} `graphql:"... on Organization"`
User struct {
Bio string
} `graphql:"... on User"`
} `graphql:"repositoryOwner(login: \"github\")"`
}Alternatively, you can define the struct types corresponding to inline fragments, and use them as embedded fields in your query:
type (
OrganizationFragment struct {
Description string
}
UserFragment struct {
Bio string
}
)
var q struct {
RepositoryOwner struct {
Login string
OrganizationFragment `graphql:"... on Organization"`
UserFragment `graphql:"... on User"`
} `graphql:"repositoryOwner(login: \"github\")"`
}Then call client.Query:
err := client.Query(context.Background(), &q, nil)
if err != nil {
// Handle error.
}
fmt.Println(q.RepositoryOwner.Login)
fmt.Println(q.RepositoryOwner.Description)
fmt.Println(q.RepositoryOwner.Bio)
// Output:
// github
// How people build software.
//Pagination
Imagine you wanted to get a complete list of comments in an issue, and not just the first 10 or so. To do that, you'll need to perform multiple queries and use pagination information. For example:
type comment struct {
Body string
Author struct {
Login string
AvatarURL string `graphql:"avatarUrl(size: 72)"`
}
ViewerCanReact bool
}
var q struct {
Repository struct {
Issue struct {
Comments struct {
Nodes []comment
PageInfo struct {
EndCursor githubv4.String
HasNextPage bool
}
} `graphql:"comments(first: 100, after: $commentsCursor)"` // 100 per page.
} `graphql:"issue(number: $issueNumber)"`
} `graphql:"repository(owner: $repositoryOwner, name: $repositoryName)"`
}
variables := map[string]interface{}{
"repositoryOwner": githubv4.String(owner),
"repositoryName": githubv4.String(name),
"issueNumber": githubv4.Int(issue),
"commentsCursor": (*githubv4.String)(nil), // Null after argument to get first page.
}
// Get comments from all pages.
var allComments []comment
for {
err := s.clQL.Query(ctx, &q, variables)
if err != nil {
return err
}
allComments = append(allComments, q.Repository.Issue.Comments.Nodes...)
if !q.Repository.Issue.Comments.PageInfo.HasNextPage {
break
}
variables["commentsCursor"] = githubv4.NewString(q.Repository.Issue.Comments.PageInfo.EndCursor)
}There is more than one way to perform pagination. Consider additional fields inside PageInfo object.
Mutations
Mutations often require information that you can only find out by performing a query first. Let's suppose you've already done that.
For example, to make the following GraphQL mutation:
mutation($input: AddReactionInput!) {
addReaction(input: $input) {
reaction {
content
}
subject {
id
}
}
}
variables {
"input": {
"subjectId": "MDU6SXNzdWUyMTc5NTQ0OTc=",
"content": "HOORAY"
}
}You can define:
var m struct {
AddReaction struct {
Reaction struct {
Content githubv4.ReactionContent
}
Subject struct {
ID githubv4.ID
}
} `graphql:"addReaction(input: $input)"`
}
input := githubv4.AddReactionInput{
SubjectID: targetIssue.ID, // ID of the target issue from a previous query.
Content: githubv4.ReactionContentHooray,
}Then call client.Mutate:
err := client.Mutate(context.Background(), &m, input, nil)
if err != nil {
// Handle error.
}
fmt.Printf("Added a %v reaction to subject with ID %#v!\n", m.AddReaction.Reaction.Content, m.AddReaction.Subject.ID)
// Output:
// Added a HOORAY reaction to subject with ID "MDU6SXNzdWUyMTc5NTQ0OTc="!Directories
| Path | Synopsis |
|---|---|
| example/githubv4dev | githubv4dev is a test program currently being used for developing githubv4 package. |
License
Overview (`vendor/github.com/shurcooL/graphql/README.md`)
graphql
Package graphql provides a GraphQL client implementation.
For more information, see package github.com/shurcooL/githubv4, which is a specialized version targeting GitHub GraphQL API v4. That package is driving the feature development.
Status: In active early research and development. The API will change when opportunities for improvement are discovered; it is not yet frozen.
Installation
graphql requires Go version 1.8 or later.
go get -u github.com/shurcooL/graphqlUsage
Construct a GraphQL client, specifying the GraphQL server URL. Then, you can use it to make GraphQL queries and mutations.
client := graphql.NewClient("https://example.com/graphql", nil)
// Use client...Authentication
Some GraphQL servers may require authentication. The graphql package does not directly handle authentication. Instead, when creating a new client, you're expected to pass an http.Client that performs authentication. The easiest and recommended way to do this is to use the golang.org/x/oauth2 package. You'll need an OAuth token with the right scopes. Then:
import "golang.org/x/oauth2"
func main() {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: os.Getenv("GRAPHQL_TOKEN")},
)
httpClient := oauth2.NewClient(context.Background(), src)
client := graphql.NewClient("https://example.com/graphql", httpClient)
// Use client...Simple Query
To make a GraphQL query, you need to define a corresponding Go type.
For example, to make the following GraphQL query:
query {
me {
name
}
}You can define this variable:
var query struct {
Me struct {
Name graphql.String
}
}Then call client.Query, passing a pointer to it:
err := client.Query(context.Background(), &query, nil)
if err != nil {
// Handle error.
}
fmt.Println(query.Me.Name)
// Output: Luke SkywalkerArguments and Variables
Often, you'll want to specify arguments on some fields. You can use the graphql struct field tag for this.
For example, to make the following GraphQL query:
{
human(id: "1000") {
name
height(unit: METER)
}
}You can define this variable:
var q struct {
Human struct {
Name graphql.String
Height graphql.Float `graphql:"height(unit: METER)"`
} `graphql:"human(id: \"1000\")"`
}Then call client.Query:
err := client.Query(context.Background(), &q, nil)
if err != nil {
// Handle error.
}
fmt.Println(q.Human.Name)
fmt.Println(q.Human.Height)
// Output:
// Luke Skywalker
// 1.72However, that'll only work if the arguments are constant and known in advance. Otherwise, you will need to make use of variables. Replace the constants in the struct field tag with variable names:
var q struct {
Human struct {
Name graphql.String
Height graphql.Float `graphql:"height(unit: $unit)"`
} `graphql:"human(id: $id)"`
}Then, define a variables map with their values:
variables := map[string]interface{}{
"id": graphql.ID(id),
"unit": starwars.LengthUnit("METER"),
}Finally, call client.Query providing variables:
err := client.Query(context.Background(), &q, variables)
if err != nil {
// Handle error.
}Inline Fragments
Some GraphQL queries contain inline fragments. You can use the graphql struct field tag to express them.
For example, to make the following GraphQL query:
{
hero(episode: "JEDI") {
name
... on Droid {
primaryFunction
}
... on Human {
height
}
}
}You can define this variable:
var q struct {
Hero struct {
Name graphql.String
Droid struct {
PrimaryFunction graphql.String
} `graphql:"... on Droid"`
Human struct {
Height graphql.Float
} `graphql:"... on Human"`
} `graphql:"hero(episode: \"JEDI\")"`
}Alternatively, you can define the struct types corresponding to inline fragments, and use them as embedded fields in your query:
type (
DroidFragment struct {
PrimaryFunction graphql.String
}
HumanFragment struct {
Height graphql.Float
}
)
var q struct {
Hero struct {
Name graphql.String
DroidFragment `graphql:"... on Droid"`
HumanFragment `graphql:"... on Human"`
} `graphql:"hero(episode: \"JEDI\")"`
}Then call client.Query:
err := client.Query(context.Background(), &q, nil)
if err != nil {
// Handle error.
}
fmt.Println(q.Hero.Name)
fmt.Println(q.Hero.PrimaryFunction)
fmt.Println(q.Hero.Height)
// Output:
// R2-D2
// Astromech
// 0Mutations
Mutations often require information that you can only find out by performing a query first. Let's suppose you've already done that.
For example, to make the following GraphQL mutation:
mutation($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
variables {
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}You can define:
var m struct {
CreateReview struct {
Stars graphql.Int
Commentary graphql.String
} `graphql:"createReview(episode: $ep, review: $review)"`
}
variables := map[string]interface{}{
"ep": starwars.Episode("JEDI"),
"review": starwars.ReviewInput{
Stars: graphql.Int(5),
Commentary: graphql.String("This is a great movie!"),
},
}Then call client.Mutate:
err := client.Mutate(context.Background(), &m, variables)
if err != nil {
// Handle error.
}
fmt.Printf("Created a %v star review: %v\n", m.CreateReview.Stars, m.CreateReview.Commentary)
// Output:
// Created a 5 star review: This is a great movie!Directories
| Path | Synopsis |
|---|---|
| example/graphqldev | graphqldev is a test program currently being used for developing graphql package. |
| ident | Package ident provides functions for parsing and converting identifier names between various naming convention. |
| internal/jsonutil | Package jsonutil provides a function for decoding JSON into a GraphQL query data structure. |
License
Overview (`vendor/github.com/sirupsen/logrus/README.md`)
Logrus [](https://github.com/sirupsen/logrus/actions?query=workflow%3ACI) [](https://pkg.go.dev/github.com/sirupsen/logrus)
Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger.
Logrus is in maintenance mode. The project focuses on security, bug fixes,
and performance improvements. New features are not planned, aside from changes
required to provide interoperability with other logging ecosystems (e.g., Go's
log/slog).
I believe Logrus' biggest contribution is to have played a part in today's
widespread use of structured logging in Golang. There doesn't seem to be a
reason to do a major, breaking iteration into Logrus V2, since the fantastic Go
community has built those independently. Many fantastic alternatives have sprung
up. Logrus would look like those, had it been re-designed with what we know
about structured logging in Go today. Check out, for example,
Zerolog, Zap, and Apex.
Nicely color-coded in development (when a TTY is attached, otherwise just
plain text):
With logrus.SetFormatter(&logrus.JSONFormatter{}), for easy parsing by logstash
or Splunk:
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
{"level":"warning","msg":"The group's number increased tremendously!","number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
{"animal":"walrus","level":"info","msg":"A giant walrus appears!","size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.","size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}With the default logrus.SetFormatter(&logrus.TextFormatter{}) when a TTY is not
attached, the output is compatible with the
logfmt format:
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" animal=orca err="It's over 9000!" number=100 omg=true size=9009To ensure this behaviour even if a TTY is attached, set your formatter as follows:
logrus.SetFormatter(&logrus.TextFormatter{
DisableColors: true,
FullTimestamp: true,
})Logging Method Name
If you wish to add the calling method as a field, instruct the logger via:
logrus.SetReportCaller(true)This adds the caller as 'method' like so:
{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by","time":"2014-03-10 19:57:38.562543129 -0400 EDT"}time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguinNote that this does add measurable overhead - the cost will depend on the version of Go, but is
between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
environment via benchmarks:
go test -bench=ReportCallerCase-sensitivity
The organization's name was changed to lower-case. If you are getting import
conflicts due to case sensitivity, please use the lower-case import:github.com/sirupsen/logrus.
Example
The simplest way to use Logrus is simply the package-level exported logger:
package main
import "github.com/sirupsen/logrus"
func main() {
logrus.WithFields(logrus.Fields{
"animal": "walrus",
}).Info("A walrus appears")
}Note that it's completely api-compatible with the stdlib logger, so you can
replace your log imports everywhere with log "github.com/sirupsen/logrus"
and you'll now have the flexibility of Logrus. You can customize it all you
want:
package main
import (
"os"
log "github.com/sirupsen/logrus"
)
func init() {
// Log as JSON instead of the default ASCII formatter.
log.SetFormatter(&log.JSONFormatter{})
// Output to stdout instead of the default stderr
// Can be any io.Writer, see below for File example
log.SetOutput(os.Stdout)
// Only log the warning severity or above.
log.SetLevel(log.WarnLevel)
}
func main() {
log.WithFields(log.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
log.WithFields(log.Fields{
"omg": true,
"number": 122,
}).Warn("The group's number increased tremendously!")
log.WithFields(log.Fields{
"omg": true,
"number": 100,
}).Fatal("The ice breaks!")
// A common pattern is to re-use fields between logging statements by re-using
// the logrus.Entry returned from WithFields()
contextLogger := log.WithFields(log.Fields{
"common": "this is a common field",
"other": "I also should be logged always",
})
contextLogger.Info("I'll be logged with common and other field")
contextLogger.Info("Me too")
}For more advanced usage such as logging to multiple locations from the same
application, you can also create an instance of the logrus Logger:
package main
import (
"os"
"github.com/sirupsen/logrus"
)
// Create a new instance of the logger. You can have any number of instances.
var logger = logrus.New()
func main() {
// The API for setting attributes is a little different than the package level
// exported logger. See Godoc.
logger.Out = os.Stdout
// You could set this to any `io.Writer` such as a file
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
// if err == nil {
// logger.Out = file
// } else {
// logger.Info("Failed to log to file, using default stderr")
// }
logger.WithFields(logrus.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
}Fields
Logrus encourages careful, structured logging through logging fields instead of
long, unparseable error messages. For example, instead of: logrus.Fatalf("Failed to send event %s to topic %s with key %d"), you should log the much more
discoverable:
logrus.WithFields(logrus.Fields{
"event": event,
"topic": topic,
"key": key,
}).Fatal("Failed to send event")We've found this API forces you to think about logging in a way that produces
much more useful logging messages. We've been in countless situations where just
a single added field to a log statement that was already there would've saved us
hours. The WithFields call is optional.
In general, with Logrus using any of the printf-family functions should be
seen as a hint you should add a field, however, you can still use theprintf-family functions with Logrus.
Default Fields
Often it's helpful to have fields always attached to log statements in an
application or parts of one. For example, you may want to always log therequest_id and user_ip in the context of a request. Instead of writinglogger.WithFields(logrus.Fields{"request_id": request_id, "user_ip": user_ip}) on
every line, you can create a logrus.Entry to pass around instead:
requestLogger := logger.WithFields(logrus.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") // will log request_id and user_ip
requestLogger.Warn("something not great happened")Hooks
You can add hooks for logging levels. For example to send errors to an exception
tracking service on Error, Fatal and Panic, info to StatsD or log to
multiple places simultaneously, e.g. syslog.
Logrus comes with built-in hooks. Add those, or your custom hook, ininit:
package main
import (
"log/syslog"
"github.com/sirupsen/logrus"
airbrake "gopkg.in/gemnasium/logrus-airbrake-hook.v2"
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
)
func init() {
// Use the Airbrake hook to report errors that have Error severity or above to
// an exception tracker. You can create custom hooks, see the Hooks section.
logrus.AddHook(airbrake.NewHook(123, "xyz", "production"))
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
if err != nil {
logrus.Error("Unable to connect to local syslog daemon")
} else {
logrus.AddHook(hook)
}
}Note: Syslog hooks also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the syslog hook README.
A list of currently known service hooks can be found in this wiki page
Level logging
Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic.
logrus.Trace("Something very low level.")
logrus.Debug("Useful debugging information.")
logrus.Info("Something noteworthy happened!")
logrus.Warn("You should probably take a look at this.")
logrus.Error("Something failed but I'm not quitting.")
// Calls os.Exit(1) after logging
logrus.Fatal("Bye.")
// Calls panic() after logging
logrus.Panic("I'm bailing.")You can set the logging level on a Logger, then it will only log entries with
that severity or anything above it:
// Will log anything that is info or above (warn, error, fatal, panic). Default.
logrus.SetLevel(logrus.InfoLevel)It may be useful to set logrus.Level = logrus.DebugLevel in a debug or verbose
environment if your application has that.
Note: If you want different log levels for global (logrus.SetLevel(...)) and syslog logging, please check the syslog hook README.
Entries
Besides the fields added with WithField or WithFields some fields are
automatically added to all logging events:
time. The timestamp when the entry was created.msg. The logging message passed to{Info,Warn,Error,Fatal,Panic}after
theAddFieldscall. E.g.Failed to send event.level. The logging level. E.g.info.
Environments
Logrus has no notion of environment.
If you wish for hooks and formatters to only be used in specific environments,
you should handle that yourself. For example, if your application has a global
variable Environment, which is a string representation of the environment you
could do:
import (
"github.com/sirupsen/logrus"
)
func init() {
// do something here to set environment depending on an environment variable
// or command-line flag
if Environment == "production" {
logrus.SetFormatter(&logrus.JSONFormatter{})
} else {
// The TextFormatter is default, you don't actually have to do this.
logrus.SetFormatter(&logrus.TextFormatter{})
}
}This configuration is how logrus was intended to be used, but JSON in
production is mostly only useful if you do log aggregation with tools like
Splunk or Logstash.
Formatters
The built-in logging formatters are:
logrus.TextFormatter
logs the event in colors if the logger output is a TTY, otherwise without colors.- To force colored output when there is no TTY, set the
ForceColors
field totrue. To force no colored output even if there is a TTY set theDisableColorsfield totrue. - On modern Windows terminals with ANSI (Virtual Terminal) support, TextFormatter
automatically enables colored output. - If your environment does not support ANSI escape sequences, wrap the logger output
using github.com/mattn/go-colorable
and setForceColors(orCLICOLOR_FORCE=1) to enable colors through the wrapper. - When colors are enabled, levels are truncated to 4 characters by default. To disable
truncation set theDisableLevelTruncationfield totrue. - When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the
PadLevelTextfield totrueenables this behavior, by adding padding to the level text.
- To force colored output when there is no TTY, set the
logrus.JSONFormatter
logs fields as JSON.
Third-party logging formatters:
FluentdFormatter. Formats entries that can be parsed by Kubernetes and Google Container Engine.GELF. Formats entries so they comply to Graylog's GELF 1.1 specification.logstash. Logs fields as Logstash Events.prefixed. Displays log entry source along with alternative layout.zalgo. Invoking the Power of Zalgo.nested-logrus-formatter. Converts logrus fields to a nested structure.powerful-logrus-formatter. get fileName, log's line number and the latest function's name when print log; Save log to files.caption-json-formatter. logrus's message json formatter with human-readable caption added.easy-logrus-formatter. Provide a user-friendly formatter for logrus.redactrus. Redacts sensitive information like password, apikeys, email, etc. from logs.
You can define your formatter by implementing the Formatter interface,
requiring a Format method. Format takes an *Entry. entry.Data is aFields type (map[string]any) with all your fields as well as the
default ones (see Entries section above):
type MyJSONFormatter struct{}
logrus.SetFormatter(new(MyJSONFormatter))
func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
// Note this doesn't include Time, Level and Message which are available on
// the Entry. Consult `godoc` on information about those fields or read the
// source of the official loggers.
serialized, err := json.Marshal(entry.Data)
if err != nil {
return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err)
}
return append(serialized, '\n'), nil
}Logger as an `io.Writer`
Logrus can be transformed into an io.Writer. That writer is the end of an io.Pipe and it is your responsibility to close it.
w := logger.Writer()
defer w.Close()
srv := http.Server{
// create a stdlib log.Logger that writes to
// logrus.Logger.
ErrorLog: log.New(w, "", 0),
}Each line written to that writer will be printed the usual way, using formatters
and hooks. The level for those entries is info.
This means that we can override the standard library logger easily:
logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}
// Use logrus for standard log output
// Note that `log` here references stdlib's log
// Not logrus imported under the name `log`.
log.SetOutput(logger.Writer())Rotation
Log rotation is not provided with Logrus. Log rotation should be done by an
external program (like logrotate(8)) that can compress and delete old log
entries. It should not be a feature of the application-level logger.
Tools
| Tool | Description |
|---|---|
| Logrus Mate | Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will be generated with different configs in different environments. |
| Logrus Viper Helper | An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of Logrus Mate. sample |
Testing
Logrus has a built-in facility for asserting the presence of log messages. This is implemented through the test hook and provides:
- decorators for existing logger (
test.NewLocalandtest.NewGlobal) which basically just adds thetesthook - a test logger (
test.NewNullLogger) that just records log messages (and does not output any):
import(
"testing"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
)
func TestSomething(t*testing.T){
logger, hook := test.NewNullLogger()
logger.Error("Helloerror")
assert.Equal(t, 1, len(hook.Entries))
assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
assert.Equal(t, "Helloerror", hook.LastEntry().Message)
hook.Reset()
assert.Nil(t, hook.LastEntry())
}Fatal handlers
Logrus can register one or more functions that will be called when any fatal
level message is logged. The registered handlers will be executed before
logrus performs an os.Exit(1). This behavior may be helpful if callers need
to gracefully shut down. Unlike a panic("Something went wrong...") call which can be intercepted with a deferred recover a call to os.Exit(1) can not be intercepted.
// ...
handler := func() {
// gracefully shut down something...
}
logrus.RegisterExitHandler(handler)
// ...Thread safety
By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs.
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
Situations when locking is not needed include:
You have no hooks registered, or hooks calling is already thread-safe.
Writing to logger.Out is already thread-safe, for example:
logger.Out is protected by locks.
logger.Out is an os.File handler opened with
O_APPENDflag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing)(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
Overview (`vendor/github.com/spf13/cast/README.md`)
cast
Easy and safe casting from one type to another in Go
Donβt Panic! ... Cast
What is Cast?
Cast is a library to convert between different go types in a consistent and easy way.
Cast provides simple functions to easily convert a number to a string, an
interface into a bool, etc. Cast does this intelligently when an obvious
conversion is possible. It doesnβt make any attempts to guess what you meant,
for example you can only convert a string to an int when it is a string
representation of an int such as β8β. Cast was developed for use in
Hugo, a website engine which uses YAML, TOML or JSON
for meta data.
Why use Cast?
When working with dynamic data in Go you often need to cast or convert the data
from one type into another. Cast goes beyond just using type assertion (though
it uses that when possible) to provide a very straightforward and convenient
library.
If you are working with interfaces to handle things like dynamic content
youβll need an easy way to convert an interface into a given type. This
is the library for you.
If you are taking in data from YAML, TOML or JSON or other formats which lack
full types, then Cast is the library for you.
Usage
Cast provides a handful of To_____ methods. These methods will always return
the desired type. If input is provided that will not convert to that type, the
0 or nil value for that type will be returned.
Cast also provides identical methods To_____E. These return the same result as
the To_____ methods, plus an additional error which tells you if it successfully
converted. Using these methods you can tell the difference between when the
input matched the zero value or when the conversion failed and the zero value
was returned.
The following examples are merely a sample of what is available. Please review
the code for a complete set.
Example βToStringβ:
cast.ToString("mayonegg") // "mayonegg"
cast.ToString(8) // "8"
cast.ToString(8.31) // "8.31"
cast.ToString([]byte("one time")) // "one time"
cast.ToString(nil) // ""
var foo interface{} = "one more time"
cast.ToString(foo) // "one more time"Example βToIntβ:
cast.ToInt(8) // 8
cast.ToInt(8.31) // 8
cast.ToInt("8") // 8
cast.ToInt(true) // 1
cast.ToInt(false) // 0
var eight interface{} = 8
cast.ToInt(eight) // 8
cast.ToInt(nil) // 0License
The project is licensed under the MIT License.
Overview (`vendor/github.com/spf13/cobra/README.md`)
Cobra is a library for creating powerful modern CLI applications.
Visit Cobra.dev for extensive documentation
Cobra is used in many Go projects such as Kubernetes,
Hugo, and GitHub CLI to
name a few. This list contains a more extensive list of projects using Cobra.
Overview
Cobra is a library providing a simple interface to create powerful modern CLI
interfaces similar to git & go tools.
Cobra provides:
- Easy subcommand-based CLIs:
app server,app fetch, etc. - Fully POSIX-compliant flags (including short & long versions)
- Nested subcommands
- Global, local and cascading flags
- Intelligent suggestions (
app srver... did you meanapp server?) - Automatic help generation for commands and flags
- Grouping help for subcommands
- Automatic help flag recognition of
-h,--help, etc. - Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell)
- Automatically generated man pages for your application
- Command aliases so you can change things without breaking them
- The flexibility to define your own help, usage, etc.
- Optional seamless integration with viper for 12-factor apps
Concepts
Cobra is built on a structure of commands, arguments & flags.
Commands represent actions, Args are things and Flags are modifiers for those actions.
The best applications read like sentences when used, and as a result, users
intuitively know how to interact with them.
The pattern to follow isAPPNAME VERB NOUN --ADJECTIVE
orAPPNAME COMMAND ARG --FLAG.
A few good real world examples may better illustrate this point.
In the following example, 'server' is a command, and 'port' is a flag:
hugo server --port=1313In this command we are telling Git to clone the url bare.
git clone URL --bareCommands
Command is the central point of the application. Each interaction that
the application supports will be contained in a Command. A command can
have children commands and optionally run an action.
In the example above, 'server' is the command.
Flags
A flag is a way to modify the behavior of a command. Cobra supports
fully POSIX-compliant flags as well as the Go flag package.
A Cobra command can define flags that persist through to children commands
and flags that are only available to that command.
In the example above, 'port' is the flag.
Flag functionality is provided by the pflag
library, a fork of the flag standard library
which maintains the same interface while adding POSIX compliance.
Installing
Using Cobra is easy. First, use go get to install the latest version
of the library.
go get -u github.com/spf13/cobra@latestNext, include Cobra in your application:
import "github.com/spf13/cobra"Usage
cobra-cli is a command line program to generate cobra applications and command files.
It will bootstrap your application scaffolding to rapidly
develop a Cobra-based application. It is the easiest way to incorporate Cobra into your application.
It can be installed by running:
go install github.com/spf13/cobra-cli@latestFor complete details on using the Cobra-CLI generator, please read The Cobra Generator README
For complete details on using the Cobra library, please read The Cobra User Guide.
License
Cobra is released under the Apache 2.0 license. See LICENSE.txt
Overview (`vendor/github.com/spf13/pflag/README.md`)
Description
pflag is a drop-in replacement for Go's flag package, implementing
POSIX/GNU-style --flags.
pflag is compatible with the GNU extensions to the POSIX recommendations
for command-line options. For a more precise description, see the
"Command-line flag syntax" section below.
pflag is available under the same style of BSD license as the Go language,
which can be found in the LICENSE file.
Installation
pflag is available using the standard go get command.
Install by running:
go get github.com/spf13/pflagRun tests by running:
go test github.com/spf13/pflagUsage
pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function
with no changes.
import flag "github.com/spf13/pflag"There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set.
Most code never instantiates this struct directly, and instead uses
functions such as String(), BoolVar(), and Var(), and is therefore
unaffected.
Define flags using flag.String(), Bool(), Int(), etc.
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
var ip *int = flag.Int("flagname", 1234, "help message for flagname")If you like, you can bind the flag to a variable using the Var() functions.
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by
flag.Var(&flagVal, "name", "help message for flagname")For such flags, the default value is just the initial value of the variable.
After all flags are defined, call
flag.Parse()to parse the command line into the defined flags.
Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)There are helper functions available to get the value stored in a Flag if you have a FlagSet but find
it difficult to keep up with all of the pointers in your code.
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
can use GetInt() to get the int value. But notice that 'flagname' must exist
and it must be an int. GetString("flagname") will fail.
i, err := flagset.GetInt("flagname")After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
The arguments are indexed from 0 through flag.NArg()-1.
The pflag package also defines some new functions that are not in flag,
that give one-letter shorthands for flags. You can use these by appending
'P' to the name of any function that defines a flag.
var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
}
flag.VarP(&flagVal, "varname", "v", "help message")Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags.
The default set of command-line flags is controlled by
top-level functions. The FlagSet type allows one to define
independent sets of flags, such as to implement subcommands
in a command-line interface. The methods of FlagSet are
analogous to the top-level functions for the command-line
flag set.
Setting no option default values for flags
After you create a flag it is possible to set the pflag.NoOptDefVal for
the given flag. Doing this changes the meaning of the flag slightly. If
a flag has a NoOptDefVal and the flag is set on the command line without
an option the flag will be set to the NoOptDefVal. For example given:
var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"Would result in something like
| Parsed Arguments | Resulting Value |
|---|---|
| --flagname=1357 | ip=1357 |
| --flagname | ip=4321 |
| [nothing] | ip=1234 |
Command line flag syntax
--flag // boolean flags, or flags with no option default values
--flag x // only on flags without a default value
--flag=xUnlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags
or a flag with a default value
// boolean or flags where the 'no option default value' is set
-f
-f=true
-abc
but
-b true is INVALID
// non-boolean and flags without a 'no option default value'
-n 1234
-n=1234
-n1234
// mixed
-abcs "hello"
-absd="hello"
-abcs1234Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.
Integer flags accept 1234, 0664, 0x1234 and may be negative.
Boolean flags (in their long form) accept 1, 0, t, f, true, false,
TRUE, FALSE, True, False.
Duration flags accept any input valid for time.ParseDuration.
Mutating or "Normalizing" Flag names
It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow.
Example #1: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag
func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
from := []string{"-", "_"}
to := "."
for _, sep := range from {
name = strings.Replace(name, sep, to, -1)
}
return pflag.NormalizedName(name)
}
myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc)Example #2: You want to alias two flags. aka --old-flag-name == --new-flag-name
func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
switch name {
case "old-flag-name":
name = "new-flag-name"
break
}
return pflag.NormalizedName(name)
}
myFlagSet.SetNormalizeFunc(aliasNormalizeFunc)Deprecating a flag or its shorthand
It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used.
Example #1: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead.
// deprecate a flag by specifying its name and a usage message
flags.MarkDeprecated("badflag", "please use --good-flag instead")This hides "badflag" from help text, and prints Flag --badflag has been deprecated, please use --good-flag instead when "badflag" is used.
Example #2: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n".
// deprecate a flag shorthand by specifying its flag name and a usage message
flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only")This hides the shortname "n" from help text, and prints Flag shorthand -n has been deprecated, please use --noshorthandflag only when the shorthand "n" is used.
Note that usage message is essential here, and it should not be empty.
Hidden flags
It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text.
Example: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available.
// hide a flag by specifying its name
flags.MarkHidden("secretFlag")Disable sorting of flags
pflag allows you to disable sorting of flags for help and usage message.
Example:
flags.BoolP("verbose", "v", false, "verbose output")
flags.String("coolflag", "yeaah", "it's really cool flag")
flags.Int("usefulflag", 777, "sometimes it's very useful")
flags.SortFlags = false
flags.PrintDefaults()Output:
-v, --verbose verbose output
--coolflag string it's really cool flag (default "yeaah")
--usefulflag int sometimes it's very useful (default 777)Supporting Go flags when using pflag
In order to support flags defined using Go's flag package, they must be added to the pflag flagset. This is usually necessary
to support flags defined by third-party dependencies (e.g. golang/glog).
Example: You want to add the Go flags to the CommandLine flagset
import (
goflag "flag"
flag "github.com/spf13/pflag"
)
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
func main() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
flag.Parse()
}Using pflag with go test
pflag does not parse the shorthand versions of go test's built-in flags (i.e., those starting with -test.).
For more context, see issues #63 and #238 for more details.
For example, if you use pflag in your TestMain function and call pflag.Parse() after defining your custom flags, running a test like this:
go test /your/tests -run ^YourTest -v --your-test-pflagswill result in the -v flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags.
To work around this, you can use the ParseSkippedFlags function, which ensures that go test's flags are parsed separately using the standard flag package.
Example: You want to parse go test flags that are otherwise ignore by pflag.Parse()
import (
goflag "flag"
flag "github.com/spf13/pflag"
)
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
func main() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
flag.Parse()
}More info
You can see the full reference documentation of the pflag package
at godoc.org, or through go's standard documentation system by
running godoc -http=:6060 and browsing to
http://localhost:6060/pkg/github.com/spf13/pflag after
installation.
Overview (`vendor/github.com/tektoncd/plumbing/README.md`)
Plumbing
This repo holds configuration for infrastructure used across the tektoncd org ποΈ:
- Tekton resources for:
- Continuous Delivery: release projects, build docker images and other periodic jobs
- Continuous Integration: run CI jobs for the various Tekton Projects. NOTE this responsibility is used shared with Prow
- Prow manifests and configuration for:
- Continuous Integration: run CI jobs, merge approved changes (via Tide)
- Support functionality via various plugins
- Ingress configuration for access via
tekton.dev - Gubernator is used for holding and displaying Prow logs
- Boskos is used to control a pool of GCP projects which end to end tests can run against
- Peribolos is used to control org and repo permissions
- bots
- custom interceptors, used for Tekton based CI
- Catlin, which provides validation for catalog resources
Automation runs in the tektoncd GCP projects.
More details on the infrastructure are available in the documentation.
Support
If you need support, reach out in the tektoncd slack
via the #plumbing channel.
Members of the Tekton governing board
have access to the underlying resources.
Overview (`vendor/github.com/x448/float16/README.md`)
Float16 (Binary16) in Go/Golang
float16 package provides IEEE 754 half-precision floating-point format (binary16) with IEEE 754 default rounding for conversions. IEEE 754-2008 refers to this 16-bit floating-point format as binary16.
IEEE 754 default rounding ("Round-to-Nearest RoundTiesToEven") is considered the most accurate and statistically unbiased estimate of the true result.
All possible 4+ billion floating-point conversions with this library are verified to be correct.
Lowercase "float16" refers to IEEE 754 binary16. And capitalized "Float16" refers to exported Go data type provided by this library.
Features
Current features include:
- float16 to float32 conversions use lossless conversion.
- float32 to float16 conversions use IEEE 754-2008 "Round-to-Nearest RoundTiesToEven".
- conversions using pure Go take about 2.65 ns/op on a desktop amd64.
- unit tests provide 100% code coverage and check all possible 4+ billion conversions.
- other functions include: IsInf(), IsNaN(), IsNormal(), PrecisionFromfloat32(), String(), etc.
- all functions in this library use zero allocs except String().
Status
This library is used by fxamacker/cbor and is ready for production use on supported platforms. The version number < 1.0 indicates more functions and options are planned but not yet published.
Current status:
- core API is done and breaking API changes are unlikely.
- 100% of unit tests pass:
- short mode (
go test -short) tests around 65765 conversions in 0.005s. - normal mode (
go test) tests all possible 4+ billion conversions in about 95s.
- short mode (
- 100% code coverage with both short mode and normal mode.
- tested on amd64 but it should work on all little-endian platforms supported by Go.
Roadmap:
- add functions for fast batch conversions leveraging SIMD when supported by hardware.
- speed up unit test when verifying all possible 4+ billion conversions.
- test on additional platforms.
Float16 to Float32 Conversion
Conversions from float16 to float32 are lossless conversions. All 65536 possible float16 to float32 conversions (in pure Go) are confirmed to be correct.
Unit tests take a fraction of a second to check all 65536 expected values for float16 to float32 conversions.
Float32 to Float16 Conversion
Conversions from float32 to float16 use IEEE 754 default rounding ("Round-to-Nearest RoundTiesToEven"). All 4294967296 possible float32 to float16 conversions (in pure Go) are confirmed to be correct.
Unit tests in normal mode take about 1-2 minutes to check all 4+ billion float32 input values and results for Fromfloat32(), FromNaN32ps(), and PrecisionFromfloat32().
Unit tests in short mode use a small subset (around 229 float32 inputs) and finish in under 0.01 second while still reaching 100% code coverage.
Usage
Install with go get github.com/x448/float16.
// Convert float32 to float16
pi := float32(math.Pi)
pi16 := float16.Fromfloat32(pi)
// Convert float16 to float32
pi32 := pi16.Float32()
// PrecisionFromfloat32() is faster than the overhead of calling a function.
// This example only converts if there's no data loss and input is not a subnormal.
if float16.PrecisionFromfloat32(pi) == float16.PrecisionExact {
pi16 := float16.Fromfloat32(pi)
}Float16 Type and API
Float16 (capitalized) is a Go type with uint16 as the underlying state. There are 6 exported functions and 9 exported methods.
/* Detailed source-code truncated for AI context efficiency. */See API at godoc.org for more info.
Benchmarks
Conversions (in pure Go) are around 2.65 ns/op for float16 -> float32 and float32 -> float16 on amd64. Speeds can vary depending on input value.
All functions have zero allocations except float16.String().
FromFloat32pi-2 2.59ns Β± 0% // speed using Fromfloat32() to convert a float32 of math.Pi to Float16
ToFloat32pi-2 2.69ns Β± 0% // speed using Float32() to convert a float16 of math.Pi to float32
Frombits-2 0.29ns Β± 5% // speed using Frombits() to cast a uint16 to Float16
PrecisionFromFloat32-2 0.29ns Β± 1% // speed using PrecisionFromfloat32() to check for overflows, etc.System Requirements
- Tested on Go 1.11, 1.12, and 1.13 but it should also work with older versions.
- Tested on amd64 but it should also work on all little-endian platforms supported by Go.
Special Thanks
Special thanks to Kathryn Long (starkat99) for creating half-rs, a very nice rust implementation of float16.
License
Copyright (c) 2019 Montgomery Edwardsβ΄β΄βΈ and Faye Amacker
Licensed under MIT License
Overview (`vendor/github.com/youmark/pkcs8/README.md`)
pkcs8
OpenSSL can generate private keys in both "traditional format" and PKCS#8 format. Newer applications are advised to use more secure PKCS#8 format. Go standard crypto package provides a function to parse private key in PKCS#8 format. There is a limitation to this function. It can only handle unencrypted PKCS#8 private keys. To use this function, the user has to save the private key in file without encryption, which is a bad practice to leave private keys unprotected on file systems. In addition, Go standard package lacks the functions to convert RSA/ECDSA private keys into PKCS#8 format.
pkcs8 package fills the gap here. It implements functions to process private keys in PKCS#8 format, as defined in RFC5208 and RFC5958. It can handle both unencrypted PKCS#8 PrivateKeyInfo format and EncryptedPrivateKeyInfo format with PKCS#5 (v2.0) algorithms.
Installation
Supports Go 1.10+. Release v1.1 is the last release supporting Go 1.9
go get github.com/youmark/pkcs8dependency
This package depends on golang.org/x/crypto/pbkdf2 and golang.org/x/crypto/scrypt packages. Use the following command to retrieve them
go get golang.org/x/crypto/pbkdf2
go get golang.org/x/crypto/scryptOverview (`vendor/go.opentelemetry.io/otel/attribute/README.md`)
Attribute
Overview (`vendor/go.opentelemetry.io/otel/baggage/README.md`)
Baggage
Overview (`vendor/go.opentelemetry.io/otel/codes/README.md`)
Codes
Overview (`vendor/go.opentelemetry.io/otel/metric/README.md`)
Metric API
Overview (`vendor/go.opentelemetry.io/otel/propagation/README.md`)
Propagation
Overview (`vendor/go.opentelemetry.io/otel/sdk/README.md`)
SDK
Overview (`vendor/go.opentelemetry.io/otel/trace/README.md`)
Trace API
Overview (`vendor/go.yaml.in/yaml/v2/README.md`)
YAML support for the Go language
Introduction
The yaml package enables Go programs to comfortably encode and decode YAML
values. It was developed within Canonical as
part of the juju project, and is based on a
pure Go port of the well-known libyaml
C library to parse and generate YAML data quickly and reliably.
Compatibility
The yaml package supports most of YAML 1.1 and 1.2, including support for
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
implemented, and base-60 floats from YAML 1.1 are purposefully not
supported since they're a poor design and are gone in YAML 1.2.
Installation and usage
The import path for the package is go.yaml.in/yaml/v2.
To install it, run:
go get go.yaml.in/yaml/v2API documentation
See: https://pkg.go.dev/go.yaml.in/yaml/v2
API stability
The package API for yaml v2 will remain stable as described in gopkg.in.
License
The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
Example
package main
import (
"fmt"
"log"
"go.yaml.in/yaml/v2"
)
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
t := T{}
err := yaml.Unmarshal([]byte(data), &t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t:\n%v\n\n", t)
d, err := yaml.Marshal(&t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t dump:\n%s\n\n", string(d))
m := make(map[interface{}]interface{})
err = yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)
d, err = yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))
}This example will generate the following output:
--- t:
{Easy! {2 [3 4]}}
--- t dump:
a: Easy!
b:
c: 2
d: [3, 4]
--- m:
map[a:Easy! b:map[c:2 d:[3 4]]]
--- m dump:
a: Easy!
b:
c: 2
d:
- 3
- 4Overview (`vendor/go.yaml.in/yaml/v3/README.md`)
go.yaml.in/yaml
YAML Support for the Go Language
Introduction
The yaml package enables Go programs to comfortably encode
and decode YAML values.
It was originally developed within Canonical as
part of the juju project, and is based on a pure Go
port of the well-known libyaml C library to
parse and generate YAML data quickly and reliably.
Project Status
This project started as a fork of the extremely popular go-yaml
project, and is being maintained by the official YAML organization.
The YAML team took over ongoing maintenance and development of the project after
discussion with go-yaml's author, @niemeyer, following his decision to
label the project repository as "unmaintained" in April 2025.
We have put together a team of dedicated maintainers including representatives
of go-yaml's most important downstream projects.
We will strive to earn the trust of the various go-yaml forks to switch back to
this repository as their upstream.
Please contact us if you
would like to contribute or be involved.
Compatibility
The yaml package supports most of YAML 1.2, but preserves some behavior from
1.1 for backwards compatibility.
Specifically, v3 of the yaml package:
- Supports YAML 1.1 bools (
yes/no,on/off) as long as they are being
decoded into a typed bool value.
Otherwise they behave as a string.
Booleans in YAML 1.2 aretrue/falseonly. - Supports octals encoded and decoded as
0777per YAML 1.1, rather than0o777as specified in YAML 1.2, because most parsers still use the old
format.
Octals in the0o777format are supported though, so new files work. - Does not support base-60 floats.
These are gone from YAML 1.2, and were actually never supported by this
package as it's clearly a poor choice.
Installation and Usage
The import path for the package is go.yaml.in/yaml/v3.
To install it, run:
go get go.yaml.in/yaml/v3API Documentation
See: https://pkg.go.dev/go.yaml.in/yaml/v3
API Stability
The package API for yaml v3 will remain stable as described in gopkg.in.
Example
package main
import (
"fmt"
"log"
"go.yaml.in/yaml/v3"
)
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
t := T{}
err := yaml.Unmarshal([]byte(data), &t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t:\n%v\n\n", t)
d, err := yaml.Marshal(&t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t dump:\n%s\n\n", string(d))
m := make(map[interface{}]interface{})
err = yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)
d, err = yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))
}This example will generate the following output:
--- t:
{Easy! {2 [3 4]}}
--- t dump:
a: Easy!
b:
c: 2
d: [3, 4]
--- m:
map[a:Easy! b:map[c:2 d:[3 4]]]
--- m dump:
a: Easy!
b:
c: 2
d:
- 3
- 4License
The yaml package is licensed under the MIT and Apache License 2.0 licenses.
Please see the LICENSE file for details.
Overview (`vendor/golang.org/x/oauth2/README.md`)
OAuth2 for Go
oauth2 package contains a client implementation for OAuth 2.0 spec.
See pkg.go.dev for further documentation and examples.
Policy for new endpoints
We no longer accept new provider-specific packages in this repo if all
they do is add a single endpoint variable. If you just want to add a
single endpoint, add it to the
pkg.go.dev/golang.org/x/oauth2/endpoints
package.
Report Issues / Send Patches
The main issue tracker for the oauth2 repository is located at
https://github.com/golang/oauth2/issues.
This repository uses Gerrit for code changes. To learn how to submit changes to
this repository, see https://go.dev/doc/contribute.
The git repository is https://go.googlesource.com/oauth2.
Note:
- Excluding trivial changes, all contributions should be connected to an existing issue.
- API changes must go through the change proposal process before they can be accepted.
- The code owners are listed at dev.golang.org/owners.
Overview (`vendor/golang.org/x/term/README.md`)
Go terminal/console support
This repository provides Go terminal and console support packages.
Report Issues / Send Patches
This repository uses Gerrit for code changes. To learn how to submit changes to
this repository, see https://go.dev/doc/contribute.
The git repository is https://go.googlesource.com/term.
The main issue tracker for the term repository is located at
https://go.dev/issues. Prefix your issue with "x/term:" in the
subject line, so it is easy to find.
Overview (`vendor/gopkg.in/evanphx/json-patch.v4/README.md`)
JSON-Patch
jsonpatch is a library which provides functionality for both applying
RFC6902 JSON patches against documents, as
well as for calculating & applying RFC7396 JSON merge patches.
Get It!
Latest and greatest:
go get -u github.com/evanphx/json-patch/v5If you need version 4, use go get -u gopkg.in/evanphx/json-patch.v4
(previous versions below v3 are unavailable)
Use It!
- Create and apply a merge patch
- Create and apply a JSON Patch
- Comparing JSON documents
- Combine merge patches
Configuration
There is a global configuration variable
jsonpatch.SupportNegativeIndices.
This defaults totrueand enables the non-standard practice of allowing
negative indices to mean indices starting at the end of an array. This
functionality can be disabled by settingjsonpatch.SupportNegativeIndices = false.There is a global configuration variable
jsonpatch.AccumulatedCopySizeLimit,
which limits the total size increase in bytes caused by "copy" operations in a
patch. It defaults to 0, which means there is no limit.
These global variables control the behavior of jsonpatch.Apply.
An alternative to jsonpatch.Apply is jsonpatch.ApplyWithOptions whose behavior
is controlled by an options parameter of type *jsonpatch.ApplyOptions.
Structure jsonpatch.ApplyOptions includes the configuration options above
and adds two new options: AllowMissingPathOnRemove and EnsurePathExistsOnAdd.
When AllowMissingPathOnRemove is set to true, jsonpatch.ApplyWithOptions will ignoreremove operations whose path points to a non-existent location in the JSON document.AllowMissingPathOnRemove defaults to false which will lead to jsonpatch.ApplyWithOptions
returning an error when hitting a missing path on remove.
When EnsurePathExistsOnAdd is set to true, jsonpatch.ApplyWithOptions will make sure
that add operations produce all the path elements that are missing from the target object.
Use jsonpatch.NewApplyOptions to create an instance of jsonpatch.ApplyOptions
whose values are populated from the global configuration variables.
Create and apply a merge patch
Given both an original JSON document and a modified JSON document, you can create
a Merge Patch document.
It can describe the changes needed to convert from the original to the
modified JSON document.
Once you have a merge patch, you can apply it to other JSON documents using thejsonpatch.MergePatch(document, patch) function.
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
// Let's create a merge patch from these two documents...
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
target := []byte(`{"name": "Jane", "age": 24}`)
patch, err := jsonpatch.CreateMergePatch(original, target)
if err != nil {
panic(err)
}
// Now lets apply the patch against a different JSON document...
alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`)
modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)
fmt.Printf("patch document: %s\n", patch)
fmt.Printf("updated alternative doc: %s\n", modifiedAlternative)
}When ran, you get the following output:
$ go run main.go
patch document: {"height":null,"name":"Jane"}
updated alternative doc: {"age":28,"name":"Jane"}Create and apply a JSON Patch
You can create patch objects using DecodePatch([]byte), which can then
be applied against JSON documents.
The following is an example of creating a patch from two operations, and
applying it against a JSON document.
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
patchJSON := []byte(`[
{"op": "replace", "path": "/name", "value": "Jane"},
{"op": "remove", "path": "/height"}
]`)
patch, err := jsonpatch.DecodePatch(patchJSON)
if err != nil {
panic(err)
}
modified, err := patch.Apply(original)
if err != nil {
panic(err)
}
fmt.Printf("Original document: %s\n", original)
fmt.Printf("Modified document: %s\n", modified)
}When ran, you get the following output:
$ go run main.go
Original document: {"name": "John", "age": 24, "height": 3.21}
Modified document: {"age":24,"name":"Jane"}Comparing JSON documents
Due to potential whitespace and ordering differences, one cannot simply compare
JSON strings or byte-arrays directly.
As such, you can instead use jsonpatch.Equal(document1, document2) to
determine if two JSON documents are structurally equal. This ignores
whitespace differences, and key-value ordering.
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
similar := []byte(`
{
"age": 24,
"height": 3.21,
"name": "John"
}
`)
different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`)
if jsonpatch.Equal(original, similar) {
fmt.Println(`"original" is structurally equal to "similar"`)
}
if !jsonpatch.Equal(original, different) {
fmt.Println(`"original" is _not_ structurally equal to "different"`)
}
}When ran, you get the following output:
$ go run main.go
"original" is structurally equal to "similar"
"original" is _not_ structurally equal to "different"Combine merge patches
Given two JSON merge patch documents, it is possible to combine them into a
single merge patch which can describe both set of changes.
The resulting merge patch can be used such that applying it results in a
document structurally similar as merging each merge patch to the document
in succession.
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
nameAndHeight := []byte(`{"height":null,"name":"Jane"}`)
ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`)
// Let's combine these merge patch documents...
combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)
if err != nil {
panic(err)
}
// Apply each patch individual against the original document
withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)
if err != nil {
panic(err)
}
withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)
if err != nil {
panic(err)
}
// Apply the combined patch against the original document
withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)
if err != nil {
panic(err)
}
// Do both result in the same thing? They should!
if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {
fmt.Println("Both JSON documents are structurally the same!")
}
fmt.Printf("combined merge patch: %s", combinedPatch)
}When ran, you get the following output:
$ go run main.go
Both JSON documents are structurally the same!
combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"}CLI for comparing JSON documents
You can install the commandline program json-patch.
This program can take multiple JSON patch documents as arguments,
and fed a JSON document from stdin. It will apply the patch(es) against
the document and output the modified doc.
patch.1.json
[
{"op": "replace", "path": "/name", "value": "Jane"},
{"op": "remove", "path": "/height"}
]patch.2.json
[
{"op": "add", "path": "/address", "value": "123 Main St"},
{"op": "replace", "path": "/age", "value": "21"}
]document.json
{
"name": "John",
"age": 24,
"height": 3.21
}You can then run:
$ go install github.com/evanphx/json-patch/cmd/json-patch
$ cat document.json | json-patch -p patch.1.json -p patch.2.json
{"address":"123 Main St","age":"21","name":"Jane"}Help It!
Contributions are welcomed! Leave an issue
or create a PR.
Before creating a pull request, we'd ask that you make sure tests are passing
and that you have added new tests when applicable.
Contributors can run tests using:
go test -cover ./...Builds for pull requests are tested automatically
using GitHub Actions.
Overview (`vendor/k8s.io/gengo/v2/README.md`)
Gengo: a framework for building simple code generators
This repo is used by Kubernetes to build some codegen tooling. It is not
intended to be general-purpose and makes some assumptions that may not hold
outside of Kubernetes.
In the past this repo was partially supported for external use (outside of the
Kubernetes project overall), but that is no longer true. We may change the API
in incompatible ways, without warning.
If you are not building something that is part of Kubernetes, DO NOT DEPEND ON
THIS REPO.
New usage within Kubernetes
Gengo is a very opinionated framework. It is primarily aimed at generating Go
code derived from types defined in other Go code, but it is possible to use it
for other things (e.g. proto files). Net new tools should consider usinggolang.org/x/tools/go/packages directly. Gengo can serve as an example of
how to do that.
If you still decide you want to use gengo, see the
simple examples in this repo or the more extensive tools in the
Kubernetes code-generator
repo.
Overview
Gengo is used to build tools (generally a tool is a binary). Each tool
describes some number of Targets. A target is a single output package, which
may be the same as the inputs (if the tool generates code alongside the inputs)
or different. Each Target describes some number of Generators. A
generator is responsible for emitting a single file into the target directory.
Gengo helps the tool to load and process input packages, e.g. extracting type
information and associating comments. Each target will be offered every known
type, and can filter that down to the set of types it cares about. Each
generator will be offered the result of the target's filtering, and can filter
the set of types further. Finally, the generator will be called to emit code
for all of the remaining types.
The tracer example in this repo can be used to examine all of the hooks.
Contributing
Please see CONTRIBUTING.md for instructions on how to contribute.
Overview (`vendor/k8s.io/klog/v2/README.md`)
klog
klog is a permanent fork of https://github.com/golang/glog.
Why was klog created?
The decision to create klog was one that wasn't made lightly, but it was necessary due to some
drawbacks that are present in glog. Ultimately, the fork was created due to glog not being under active development; this can be seen in the glog README:
The code in this repo [...] is not itself under development
This makes us unable to solve many use cases without a fork. The factors that contributed to needing feature development are listed below:
glogpresents a lot "gotchas" and introduces challenges in containerized environments, all of which aren't well documented.glogdoesn't provide an easy way to test logs, which detracts from the stability of software using it- A long term goal is to implement a logging interface that allows us to add context, change output format, etc.
Historical context is available here:
- https://github.com/kubernetes/kubernetes/issues/61006
- https://github.com/kubernetes/kubernetes/issues/70264
- https://groups.google.com/forum/#!msg/kubernetes-sig-architecture/wCWiWf3Juzs/hXRVBH90CgAJ
- https://groups.google.com/forum/#!msg/kubernetes-dev/7vnijOMhLS0/1oRiNtigBgAJ
Release versioning
Semantic versioning is used in this repository. It contains several Go modules
with different levels of stability:
k8s.io/klog/v2- stable API,vX.Y.Ztagsexamples- no stable API, no tags, no intention to ever stabilize
Exempt from the API stability guarantee are items (packages, functions, etc.)
which are marked explicitly as EXPERIMENTAL in their docs comment. Those
may still change in incompatible ways or get removed entirely. This can only
be used for code that is used in tests to avoid situations where non-test
code from two different Kubernetes dependencies depends on incompatible
releases of klog because an experimental API was changed.
How to use klog
- Replace imports for
"github.com/golang/glog"with"k8s.io/klog/v2" - Use
klog.InitFlags(nil)explicitly for initializing global flags as we no longer useinit()method to register the flags - You can now use
log_fileinstead oflog_dirfor logging to a single file (Seeexamples/log_file/usage_log_file.go) - If you want to redirect everything logged using klog somewhere else (say syslog!), you can use
klog.SetOutput()method and supply aio.Writer. (Seeexamples/set_output/usage_set_output.go) - For more logging conventions (See Logging Conventions)
- See our documentation on pkg.go.dev/k8s.io.
Coexisting with klog/v2
See this example to see how to coexist with both klog/v1 and klog/v2.
Coexisting with glog
This package can be used side by side with glog. This example shows how to initialize and synchronize flags from the global flag.CommandLine FlagSet. In addition, the example makes use of stderr as combined output by setting alsologtostderr (or logtostderr) to true.
Community, discussion, contribution, and support
Learn how to engage with the Kubernetes community on the community page.
You can reach the maintainers of this project at:
Code of conduct
Participation in the Kubernetes community is governed by the Kubernetes Code of Conduct.
glog
Leveled execution logs for Go.
This is an efficient pure Go implementation of leveled logs in the
manner of the open source C++ package
https://github.com/google/glog
By binding methods to booleans it is possible to use the log package
without paying the expense of evaluating the arguments to the log.
Through the -vmodule flag, the package also provides fine-grained
control over logging at the file level.
The comment from glog.go introduces the ideas:
Package glog implements logging analogous to the Google-internal
C++ INFO/ERROR/V setup. It provides functions Info, Warning,
Error, Fatal, plus formatting variants such as Infof. It
also provides V-style logging controlled by the -v and
-vmodule=file=2 flags.
Basic examples:
glog.Info("Prepare to repel boarders")
glog.Fatalf("Initialization failed: %s", err)
See the documentation of the V function for an explanation
of these examples:
if glog.V(2) {
glog.Info("Starting transaction...")
}
glog.V(2).Infoln("Processed", nItems, "elements")The repository contains an open source version of the log package
used inside Google. The master copy of the source lives inside
Google, not here. The code in this repo is for export only and is not itself
under development. Feature requests will be ignored.
Send bug reports to [email protected].
Overview (`vendor/k8s.io/utils/clock/README.md`)
Clock
This package provides an interface for time-based operations. It allows
mocking time for testing.
Overview (`vendor/k8s.io/utils/pointer/README.md`)
Pointer
This package provides some functions for pointer-based operations.
Overview (`vendor/k8s.io/utils/ptr/README.md`)
Pointer
This package provides some functions for pointer-based operations.
Overview (`vendor/k8s.io/utils/trace/README.md`)
Trace
This package provides an interface for recording the latency of operations and logging details
about all operations where the latency exceeds a limit.
Usage
To create a trace:
func doSomething() {
opTrace := trace.New("operation", Field{Key: "fieldKey1", Value: "fieldValue1"})
defer opTrace.LogIfLong(100 * time.Millisecond)
// do something
}To split an trace into multiple steps:
func doSomething() {
opTrace := trace.New("operation")
defer opTrace.LogIfLong(100 * time.Millisecond)
// do step 1
opTrace.Step("step1", Field{Key: "stepFieldKey1", Value: "stepFieldValue1"})
// do step 2
opTrace.Step("step2")
}To nest traces:
func doSomething() {
rootTrace := trace.New("rootOperation")
defer rootTrace.LogIfLong(100 * time.Millisecond)
func() {
nestedTrace := rootTrace.Nest("nested", Field{Key: "nestedFieldKey1", Value: "nestedFieldValue1"})
defer nestedTrace.LogIfLong(50 * time.Millisecond)
// do nested operation
}()
}Traces can also be logged unconditionally or introspected:
opTrace.TotalTime() // Duration since the Trace was created
opTrace.Log() // unconditionally log the traceUsing context.Context to nest traces
context.Context can be used to manage nested traces. Create traces by calling trace.GetTraceFromContext(ctx).Nest.
This is safe even if there is no parent trace already in the context because (*(Trace)nil).Nest() returns
a top level trace.
func doSomething(ctx context.Context) {
opTrace := trace.FromContext(ctx).Nest("operation") // create a trace, possibly nested
ctx = trace.ContextWithTrace(ctx, opTrace) // make this trace the parent trace of the context
defer opTrace.LogIfLong(50 * time.Millisecond)
doSomethingElse(ctx)
}Overview (`vendor/knative.dev/pkg/injection/README.md`)
Knative Dependency Injection
This library supports the production of controller processes with minimal
boilerplate outside of the reconciler implementation.
Building Controllers
To adopt this model of controller construction, implementations should start
with the following controller constructor:
import (
"context"
"knative.dev/pkg/configmap"
"knative.dev/pkg/controller"
"knative.dev/pkg/logging"
kindreconciler "knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<resource>"
)
func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
logger := logging.FromContext(ctx)
// TODO(you): Access informers
r := &Reconciler{
// TODO(you): Pass listers, clients, and other stuff.
}
impl := kindreconciler.NewImpl(ctx, r)
// TODO(you): Set up event handlers.
return impl
}Generated Reconcilers
A code generator is available for simple subset of reconciliation requirements.
A label above the API type will signal to the injection code generator to
generate a strongly typed reconciler. Use +genreconciler to generate the
reconcilers.
// +genclient
// +genreconciler
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExampleType struct {
...
}+genreconciler will produce a helper method to get a controller impl.
Update NewController as follows:
"knative.dev/pkg/controller"
...
impl := controller.NewContext(ctx, c, controller.ControllerOptions{
Logger: logger,
WorkQueueName: "NameOfController",
})becomes
kindreconciler "knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<resource>"
...
impl := kindreconciler.NewImpl(ctx, c)See
Generated Reconciler Responsibilities
for more information.
Implementing Reconcilers
Type Reconciler is expected to implement Reconcile:
func (r *Reconciler) Reconcile(ctx context.Context, key string) error {
...
}Generated Reconcilers
If generated reconcilers are used, Type Reconciler is expected to implementReconcileKind:
func (r *Reconciler) ReconcileKind(ctx context.Context, o *samplesv1alpha1.AddressableService) reconciler.Event {
...
}And if finalizers are required,
func (r *Reconciler) FinalizeKind(ctx context.Context, o *samplesv1alpha1.AddressableService) reconciler.Event {
...
}See
Generated Reconciler Responsibilities
for more information.
Consuming Informers
Knative controllers use "informers" to set up the various event hooks needed to
queue work, and pass the "listers" fed by the informers' caches to the nested
"Reconciler" for accessing objects.
Our controller constructor is passed a context.Context onto which we inject
any informers we access. The accessors for these informers are in little stub
libraries, which we have hand rolled for Kubernetes (more on how to generate
these below).
import (
// These are how you access a client or informer off of the "ctx" passed
// to set up the controller.
"knative.dev/pkg/client/injection/kube/client"
svcinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/service"
// Other imports ...
)
func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
logger := logging.FromContext(ctx)
// Access informers
svcInformer := svcinformer.Get(ctx)
c := &Reconciler{
// Pass the lister and client to the Reconciler.
Client: kubeclient.Get(ctx),
ServiceLister: svcInformer.Lister(),
}
logger = logger.Named("NameOfController")
impl := controller.NewContext(ctx, c, controller.ControllerOptions{
Logger: logger,
WorkQueueName: "NameOfController",
})
// Set up event handlers.
svcInformer.Informer().AddEventHandler(...)
return impl
}How it works: by importing the accessor for a client or informer we link it
and trigger theinit()method for its package to run at startup. Each of
these libraries registers themselves similar to ourinit()and controller
processes can leverage this to setup and inject all of the registered things
onto a context to pass to yourNewController().
Testing Controllers
Similar to injection.Default, we also have injection.Fake. While linking the
normal accessors sets up the former, linking their fakes set up the latter.
import (
"testing"
// Link the fakes for any informers our controller accesses.
_ "knative.dev/pkg/client/injection/kube/informers/core/v1/service/fake"
"k8s.io/client-go/rest"
"knative.dev/pkg/injection"
logtesting "knative.dev/pkg/logging/testing"
)
func TestFoo(t *testing.T) {
ctx := logtesting.TestContextWithLogger(t)
// Setup a context from all of the injected fakes.
ctx, _ = injection.Fake.SetupInformers(ctx, &rest.Config{})
cmw := configmap.NewStaticWatcher(...)
ctrl := NewController(ctx, cmw)
// Test the controller process.
}The fake clients also support manually setting up contexts seeded with objects:
import (
"testing"
fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake"
"k8s.io/client-go/rest"
"knative.dev/pkg/injection"
logtesting "knative.dev/pkg/logging/testing"
)
func TestFoo(t *testing.T) {
ctx := logtesting.TestContextWithLogger(t)
objs := []runtime.Object{
// Some list of initial objects in the client.
}
ctx, kubeClient := fakekubeclient.With(ctx, objs...)
// The fake clients returned by our library are the actual fake type,
// which enables us to access test-specific methods, e.g.
kubeClient.AppendReactor(...)
c := &Reconciler{
Client: kubeClient,
}
// Test the reconciler...
}Starting controllers
All we do is import the controller packages and pass their constructors along
with a component name (single word) to our shared main. Then our shared main
method sets it all up and runs our controllers.
package main
import (
// The set of controllers this process will run.
"github.com/knative/foo/pkg/reconciler/bar"
"github.com/knative/baz/pkg/reconciler/blah"
// This defines the shared main for injected controllers.
"knative.dev/pkg/injection/sharedmain"
)
func main() {
sharedmain.Main("componentname",
bar.NewController,
blah.NewController,
)
}Generating Injection Stubs.
To make generating stubs simple, we have harnessed the Kubernetes
code-generation tooling to produce injection-gen. Similar to how you might
ordinarily run the other foo-gen processed:
To run injection-gen you run the following (replacing the import path and api
group):
KNATIVE_CODEGEN_PKG=${KNATIVE_CODEGEN_PKG:-$(cd ${REPO_ROOT}; ls -d -1 ./vendor/knative.dev/pkg 2>/dev/null || echo ../pkg)}
${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \
github.com/knative/sample-controller/pkg/client github.com/knative/sample-controller/pkg/apis \
"samples:v1alpha1" \
--go-header-file ${REPO_ROOT}/hack/boilerplate/boilerplate.go.txtTo ensure the appropriate tooling is vendored, add the following toGopkg.toml:
required = [
"knative.dev/pkg/codegen/cmd/injection-gen",
]
# .. Constraints
# Keeps things like the generate-knative.sh script
[[prune.project]]
name = "knative.dev/pkg"
unused-packages = false
non-go = falseGenerated Reconciler Responsibilities
The goal of generating the reconcilers is to provide the controller implementer
a strongly typed interface, and ensure correct reconciler behaviour around
status updates, Kubernetes event creation, and queue management.
We have already helped the queue management with libraries in this repo. But
there was a gap in support and standards around how status updates (and retries)
are performed, and when Kubernetes events are created for the resource.
The general flow with generated reconcilers looks like the following:
[k8s] -> [watches] -> [reconciler enqeueue] -> [Reconcile(key)] -> [ReconcileKind(resource)]
^-- you set up. ^-- generated ^-- stubbed and you customizeOptionally, support for finalizers:
[Reconcile(key)] -> <resource deleted?> - no -> [ReconcileKind(resource)]
`
(optional)
`- yes -> [FinalizeKind(resource)]ReconcileKindis only called if the resource's deletion timestamp is empty.FinalizeKindis optional, and if implemented by the reconciler will be
called when the resource's deletion timestamp is set.
The responsibility and consequences of using the generatedReconcileKind(resource) method are as follows:
- In
NewController, set up watches and reconciler enqueue requests as before. - Implementing
ReconcileKind(ctx, resource)to handle active resources. - Implementing
FinalizeKind(ctx, resource)to finalize deleting active
resources.- NOTE: Implementing
FinalizeKindwill result in the reconciler using
finalizers on the resource.
- NOTE: Implementing
- Resulting changes from
ReconcilecallingReconcileKind(ctx, resource):- DO NOT edit the spec of
resource, it will be ignored. - DO NOT edit the metadata of
resource, it will be ignored. - If
resource.statusis changed,Reconcilewill synchronize it back to the
API Server.- Note: the watches setup for
resource.Kindwill see the update to status
and cause another reconciliation.
- Note: the watches setup for
- DO NOT edit the spec of
ReconcileKind(ctx, resource)returns areconciler.Eventresults in:- If
eventis anerror(reconciler.Eventextendserrorinternally),Reconcilerwill produce aWarningkubernetes event with reasonInternalErrorand the body of the error as the message.- Additionally, the
errorwill be returned fromReconcilerandkeywill
requeue back into the reconciler key queue.
- Additionally, the
- If
eventis areconciler.Event,Reconcilerwill log a typed and reasoned
Kubernetes Event based on the contents ofevent.eventis not considered an error for requeue and nil is returned fromReconciler.
- If additional events are required to be produced, an implementation can pull a
recorder from the context:recorder := controller.GetEventRecorder(ctx).
Future features to be considered:
- Document how we leverage
configStoreand specificallyctx = r.configStore.ToContext(ctx)insideReconcile. - Adjust
+genreconcilerto allow for generated reconcilers to be made without
annotating the type struct. - Add class-based annotation filtering.
ConfigStore
Config store is used to decorate the context with a snapshot of configmaps to be
used in a reconciler method.
To add this feature to the generated reconciler, it will have to be passed in onreconciler<kind>.NewImpl like so:
kindreconciler "knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<resource>"
...
impl := kindreconciler.NewImpl(ctx, c, func(impl *controller.Impl) controller.Options {
// Setup options that require access to a controller.Impl.
configsToResync := []interface{}{
&some.Config{},
}
resyncOnConfigChange := configmap.TypeFilter(configsToResync...)(func(string, interface{}) {
impl.FilteredGlobalResync(myFilterFunc, kindInformer.Informer())
})
configStore := config.NewStore(c.Logger.Named("config-store"), resyncOnConfigChange)
configStore.WatchConfigs(cmw)
// Return the controller options.
return controller.Options{
ConfigStore: configStore,
}
})Filtering on controller promotion
The generated controllers implement the
LeaderAwareFuncs
interface to support HA controller deployments. When a generated controller is
promoted, by default it will trigger a re-reconcile of every resource it
manages.
To filter which objects get reconciled, pass a PromoteFilterFunc to the
controller's constructor:
kindreconciler "knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<resource>"
pkgreconciler "knative.dev/pkg/reconciler"
...
impl := kindreconciler.NewImpl(ctx, c, func(impl *controller.Impl) controller.Options {
return controller.Options{
PromoteFilterFunc: pkgreconciler.LabelFilterFunc("mylabel", "myvalue", false),
}
})Artifacts
The artifacts are targeted to the configured client/injection directory:
kindreconciler "knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<kind>"Controller related artifacts:
NewImpl- gets an injection based client and lister for<kind>, sets up
Kubernetes Event recorders, and delegates tocontroller.NewContextfor queue
management.
impl := reconciler.NewImpl(ctx, reconcilerInstance)Reconciler related artifacts:
Interface- defines the strongly typed interfaces to be implemented by a
controller reconciling<kind>.
// Check that our Reconciler implements Interface
var _ addressableservicereconciler.Interface = (*Reconciler)(nil)Finalizer- defines the strongly typed interfaces to be implemented by a
controller finalizing<kind>.
// Check that our Reconciler implements Interface
var _ addressableservicereconciler.Finalizer = (*Reconciler)(nil)Annotation based class filters
Sometimes a reconciler only wants to reconcile a class of resource identified by
a special annotation on the Custom Resource.
This behavior can be enabled in the generators by adding the annotation class
key to the type struct:
// +genreconciler:class=example.com/filter.classThe genreconciler generator code will now have the addition ofclassValue string to NewImpl and NewReconciler (for tests):
NewImpl(ctx context.Context, r Interface, classValue string, optionsFns ...controller.OptionsFn) *controller.ImplNewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister pubv1alpha1.BarLister, recorder record.EventRecorder, r Interface, classValue string, options ...controller.Options) controller.ReconcilerReconcileKind and FinalizeKind will NOT be called for resources that DO NOT
have the provided +genreconciler:class=<key> key annotation. Additionally the
value of the <key> annotation on a resource must match the value provided toNewImpl (or NewReconcile) for ReconcileKind or FinalizeKind to be called
for that resource.
Annotation based common logic
krshapedlogic=false may be used to omit common reconciler logic
Reconcilers can handle common logic for resources that conform to the KRShaped
interface. This allows the generated code to automatically increment
ObservedGeneration.
// +genreconcilerSetting this annotation will emit the following in the generated reconciler.
reconciler.PreProcessReconcile(ctx, resource)
reconcileEvent = r.reconciler.ReconcileKind(ctx, resource)
reconciler.PostProcessReconcile(ctx, resource, oldResource)Stubs
To enable stubs generation, add the stubs flag:
// +genreconciler:stubsOr with the class annotation:
// +genreconciler:class=example.com/filter.class,stubsThe stubs are intended to be used to get started, or to use as reference. It is
intended to be copied out of the client dir.
knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<kind>/stubs/controller.go
- A basic implementation of
NewController.
knative.dev/<repo>/pkg/client/injection/reconciler/<clientgroup>/<version>/<kind>/stubs/reconciler.go
- A basic implementation of
type Reconciler struct {}andReconciler.ReconcileKind. - A commented out example of a basic implementation of
Reconciler.FinalizeKind. - An example
reconciler.Event:newReconciledNormal
Examples
Please look atsample-controller orsample-source for working
integrations of the generated geconciler code.
Overview (`vendor/knative.dev/pkg/test/README.md`)
Test
This directory contains tests and testing docs.
- Test library contains code you can use in your
knative
tests - Flags added by the test library
- Unit tests currently reside in the codebase alongside
the code they test
Running unit tests
To run all unit tests:
go test ./...Test library
You can use the test library in this dir to:
Use common test flags
These flags are useful for running against an existing cluster, making use of
your existing
environment setup.
By importing knative.dev/pkg/test you get access to a global variable calledtest.Flags which holds the values of
the command line flags.
logger.Infof("Using namespace %s", test.Flags.Namespace)See e2e_flags.go.
Output logs
When tests are run with --logverbose option,
debug logs will be emitted to stdout.
We are using a generic
FormatLogger
that can be passed in any existing logger that satisfies it. Test can use the
generic logging methods to log info and
error logs. All the common methods accept generic FormatLogger as a parameter
and tests can pass in t.Logf like this:
_, err = pkgTest.WaitForEndpointState(
kubeClient,
t.Logf,
...),See logging.go.
Check Knative Serving resources
WARNING: this code also exists inknative/serving.
After creating Knative Serving resources or making changes to them, you will
need to wait for the system to realize those changes. You can use the Knative
Serving CRD check and polling methods to check the resources are either in or
reach the desired state.
The WaitFor* functions use the kuberneteswait package. To poll
they usePollImmediate
and the return values of the function you provide behave the same asConditionFunc:
a bool to indicate if the function should stop or continue polling, and anerror to indicate if there has been an error.
For example, you can poll a Configuration object to find the name of theRevision that was created for it:
var revisionName string
err := test.WaitForConfigurationState(
clients.ServingClient, configName, func(c *v1alpha1.Configuration) (bool, error) {
if c.Status.LatestCreatedRevisionName != "" {
revisionName = c.Status.LatestCreatedRevisionName
return true, nil
}
return false, nil
}, "ConfigurationUpdatedWithRevision")See kube_checks.go.
Ensure test cleanup
To ensure your test is cleaned up, you should defer cleanup to execute after
your test completes and also ensure the cleanup occurs if the test is
interrupted:
defer tearDown(clients)
test.CleanupOnInterrupt(func() { tearDown(clients) })See cleanup.go.
Flags
Importing the test library adds flags that are useful for end
to end tests that need to run against a cluster.
Tests importing knative.dev/pkg/test recognize these flags:
--kubeconfig--cluster--namespace--logverbose--ingressendpoint--dockerrepo--tag--imagetemplate
Specifying kubeconfig
By default the tests will use the
kubeconfig file
at ~/.kube/config. If there is an error getting the current user, it will usekubeconfig instead as the default value. You can specify a different config
file with the argument --kubeconfig.
To run tests with a non-default kubeconfig file:
go test ./test --kubeconfig /my/path/kubeconfigSpecifying cluster
The --cluster argument lets you use a different cluster than
your specified kubeconfig's active context.
go test ./test --cluster your-cluster-nameThe current cluster names can be obtained by running:
kubectl config get-clustersSpecifying ingress endpoint
The --ingressendpoint argument lets you specify a static url to use as the
ingress server during tests. This is useful for Kubernetes configurations which
do not provide external IPs.
go test ./test --ingressendpoint <k8s-controller-ip>:32380Specifying namespace
The --namespace argument lets you specify the namespace to use for the tests.
By default, tests will use serving-tests.
go test ./test --namespace your-namespace-nameOutput verbose logs
The --logverbose argument lets you see verbose test logs and k8s logs.
go test ./test --logverboseSpecifying docker repo
The --dockerrepo argument lets you specify a uri of the docker repo where you
have uploaded the test image to using uploadtestimage.sh. Defaults to$KO_DOCKER_REPO
go test ./test --dockerrepo myspecialdockerrepoSpecifying tag
The --tag argument lets you specify the version tag for the test images.
go test ./test --tag v1.0Specifying image template
The --imagetemplate argument lets you specify a template to generate the
reference to an image from the test. Defaults to{{.Repository}}/{{.Name}}:{{.Tag}}
go test ./test --imagetemplate {{.Repository}}/{{.Name}}:{{.Tag}}Except as otherwise noted, the content of this page is licensed under the
Creative Commons Attribution 4.0 License,
and code samples are licensed under the
Apache 2.0 License.
Overview (`vendor/knative.dev/pkg/webhook/README.md`)
Knative Webhooks
Knative provides infrastructure for authoring webhooks underknative.dev/pkg/webhook and has a few built-in helpers for certain common
admission control scenarios. The built-in admission controllers are:
- Resource validation and defaulting (builds around
apis.Validatableandapis.Defaultableunderknative.dev/pkg/apis). - ConfigMap validation, which builds around similar patterns from
knative.dev/pkg/configmap(in particular thestoreconcept)
To illustrate standing up the webhook, let's start with one of these built-in
admission controllers and then talk about how you can write your own admission
controller.
Standing up a Webhook from an Admission Controller
We provide facilities in knative.dev/pkg/injection/sharedmain to try and
eliminate much of the boilerplate involved in standing up a webhook. For this
example we will show how to stand up the webhook using the built-in admission
controller for validating and defaulting resources.
The code to stand up such a webhook looks roughly like this:
/* Detailed source-code truncated for AI context efficiency. */There is also a config map validation admission controller built in underknative.dev/pkg/webhook/configmaps.
TLS Configuration
The webhook server supports configuring TLS parameters through the webhook.Options struct. This allows you to control the TLS version, cipher suites, and elliptic curve preferences for enhanced security.
Available TLS Options
type Options struct {
// ... other fields ...
// TLSMinVersion contains the minimum TLS version that is acceptable.
// Default is TLS 1.3 if not specified.
// Supported values: tls.VersionTLS12, tls.VersionTLS13
TLSMinVersion uint16
// TLSMaxVersion contains the maximum TLS version that is acceptable.
// If not set (0), the maximum version supported by the implementation will be used.
// Useful for enforcing Modern profile (TLS 1.3 only) by setting both
// TLSMinVersion and TLSMaxVersion to tls.VersionTLS13.
TLSMaxVersion uint16
// TLSCipherSuites specifies the list of enabled cipher suites.
// If empty, a default list of secure cipher suites will be used.
// Note: Cipher suites are not configurable in TLS 1.3; they are
// determined by the implementation.
TLSCipherSuites []uint16
// TLSCurvePreferences specifies the elliptic curves that will be used
// in an ECDHE handshake. If empty, the default curves will be used.
TLSCurvePreferences []tls.CurveID
}Environment Variable Configuration
You can also configure the minimum TLS version via the WEBHOOK_TLS_MIN_VERSION environment variable:
env:
- name: WEBHOOK_TLS_MIN_VERSION
value: "1.3" # or "1.2"Usage Examples
Example 1: Default Configuration (Recommended)
By default, the webhook uses TLS 1.3 as the minimum version with secure defaults:
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: "webhook",
Port: 8443,
SecretName: "webhook-certs",
// TLS defaults: MinVersion=1.3, secure cipher suites and curves
})Example 2: Modern Profile (TLS 1.3 Only)
To enforce TLS 1.3 only (highest security profile):
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: "webhook",
Port: 8443,
SecretName: "webhook-certs",
TLSMinVersion: tls.VersionTLS13,
TLSMaxVersion: tls.VersionTLS13, // Enforce TLS 1.3 only
})Example 3: Intermediate Profile (TLS 1.2+)
For broader compatibility while maintaining security:
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: "webhook",
Port: 8443,
SecretName: "webhook-certs",
TLSMinVersion: tls.VersionTLS12,
})Example 4: Custom Cipher Suites
To specify custom cipher suites (for TLS 1.2):
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: "webhook",
Port: 8443,
SecretName: "webhook-certs",
TLSMinVersion: tls.VersionTLS12,
TLSCipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
},
})Example 5: Custom Elliptic Curves
To specify elliptic curve preferences:
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: "webhook",
Port: 8443,
SecretName: "webhook-certs",
TLSCurvePreferences: []tls.CurveID{
tls.X25519, // Preferred
tls.CurveP256,
tls.CurveP384,
},
})Example 6: Complete Custom Configuration
For full control over TLS parameters:
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: "webhook",
Port: 8443,
SecretName: "webhook-certs",
TLSMinVersion: tls.VersionTLS12,
TLSMaxVersion: tls.VersionTLS13,
TLSCipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
},
TLSCurvePreferences: []tls.CurveID{
tls.X25519,
tls.CurveP256,
},
})Writing new Admission Controllers
To implement your own admission controller akin to the resource defaulting and
validation controller above, you implement aknative.dev/pkg/controller.Reconciler as with any you would with any other
type of controller, but the Reconciler that gets embedded in the*controller.Impl should also implement:
// AdmissionController provides the interface for different admission controllers
type AdmissionController interface {
// Path returns the path that this particular admission controller serves on.
Path() string
// Admit is the callback which is invoked when an HTTPS request comes in on Path().
Admit(context.Context, *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
}The Reconciler part is responsible for the mutating or validating webhook
configuration. The AdmissionController part is responsible for guiding request
dispatch (Path()) and handling admission requests (Admit()).
Overview (`vendor/cloud.google.com/go/compute/metadata/README.md`)
Compute API
This is a utility library for communicating with Google Cloud metadata service
on Google Cloud.
Install
go get cloud.google.com/go/compute/metadataGo Version Support
See the Go Versions Supported
section in the root directory's README.
Contributing
Contributions are welcome. Please, see the [CONTRIBUTING](https: