{"id":19002315,"url":"https://github.com/linkerd/linkerd2-conformance","last_synced_at":"2025-07-10T09:35:43.499Z","repository":{"id":144212232,"uuid":"267353400","full_name":"linkerd/linkerd2-conformance","owner":"linkerd","description":"A Conformance Validation tool for Linkerd 2.X","archived":false,"fork":false,"pushed_at":"2020-09-02T08:21:52.000Z","size":264,"stargazers_count":1,"open_issues_count":4,"forks_count":2,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-27T07:04:27.687Z","etag":null,"topics":["linkerd2"],"latest_commit_sha":null,"homepage":"https://linkerd.io/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linkerd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-27T15:14:56.000Z","updated_at":"2020-09-01T17:59:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"112c09b3-a410-464c-8fae-f192edf3d7d6","html_url":"https://github.com/linkerd/linkerd2-conformance","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/linkerd/linkerd2-conformance","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkerd%2Flinkerd2-conformance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkerd%2Flinkerd2-conformance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkerd%2Flinkerd2-conformance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkerd%2Flinkerd2-conformance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linkerd","download_url":"https://codeload.github.com/linkerd/linkerd2-conformance/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkerd%2Flinkerd2-conformance/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264559433,"owners_count":23628039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linkerd2"],"created_at":"2024-11-08T18:14:37.445Z","updated_at":"2025-07-10T09:35:43.486Z","avatar_url":"https://github.com/linkerd.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Linkerd Conformance Validation\n\n![Linkerd][logo]\n\nThis repo contains the conformance tests for  [Linkerd2](https://github.com/linkerd/linkerd2)\nas described by [this](https://github.com/linkerd/rfc/pull/24) RFC.\n\nThe conformance validation tool is\nprimarily intended to be run on a\nspecified version of Linkerd to verify\nthe correctness of a [Kubernetes](https://kubernetes.io/)\ncluster's configuration with respect\nto Linkerd as well as validate non-trivial\nnetwork communication (HTTP, gRPC, websocket)\namong stateless and stateful workloads\nin the Linkerd data plane.\n\nThe conformance tests exercise the following features:\n\n- [ ] Validation of your Linkerd2 control plane\n- [ ] Automatic proxy injection on workloads\n- [ ] Functioning of  `linkerd tap`, `stat`, `routes` and `edges` commands\n- [ ] Verifying the functioning of the `tap` extension API server\n- [ ] Retries and timeouts\n- [ ] Data plane health checks\n- [ ] Ingress configuration\n_...and much more_\n\nIf you are interested in helping to extend the test suites, see\n[Adding new tests](https://github.com/linkerd/linkerd2-conformance#2-adding-tests)\nbelow.\n\n## Table of Contents\n\n- [Repository Structure](https://github.com/linkerd/linkerd2-conformance#repository-structure)\n- [Configuring your tests](https://github.com/linkerd/linkerd2-conformance#configuring-your-tests)\n  - [Configuration Options](https://github.com/linkerd/linkerd2-conformance#configuration-options)\n- [Usage](https://github.com/linkerd/linkerd2-conformance#usage)\n  - [Using the Sonobuoy CLI](https://github.com/linkerd/linkerd2-conformance#using-the-sonobuoy-cli)\n  - Running the tests using Docker\n  - [Running the tests locally](https://github.com/linkerd/linkerd2-conformance#running-the-tests-locally)\n- [Adding new tests](https://github.com/linkerd/linkerd2-conformance#adding-new-tests)\n  - [Bootstrapping](https://github.com/linkerd/linkerd2-conformance#1-bootstrapping)\n  - [Adding tests](https://github.com/linkerd/linkerd2-conformance#2-writing-the-tests)\n  - [Wiring up the newly added tests](https://github.com/linkerd/linkerd2-conformance#3-wiring-up-the-newly-added-test)\n\n## Repository Structure\n\n- [`specs`](https://github.com/linkerd/linkerd2-conformance/tree/master/specs)\ncontains the tests for each of the features organized into separate\npackages\n- [`sonobuoy`](https://github.com/linkerd/linkerd2-conformance/tree/master/sonobuoy)\ncontains the items required to be able to run the tests as a\n[Sonobuoy](https://github.com/vmware-tanzu/sonobuoy) plugin\n- [`utils`](https://github.com/linkerd/linkerd2-conformance/tree/master/utils)\ncontains helper functions that can be used while\nwriting conformance tests\n- [`bin`](https://github.com/linkerd/linkerd2-conformance/blob/master/bin)\ncontains useful helper scripts to build/push the\nDocker image and running the tests\n- [`testdata`](https://github.com/linkerd/linkerd2-conformance/blob/master/bin)\ncontains the necessary files required by the tests,\norganized into subfolders\n\n## Configuring your tests\n\nThe conformance tests can be easily configured\nby specifying a `config.yaml` that holds the\nconfiguration values. This includes things like\nLinkerd version, Linkerd add-ons, test specific\nconfiguration, binary path, etc.  \n\nRun the command below to pull up a sample\nconfiguration file, `config.yaml`, and modify\nit according to your requirements. The tests\nshall read this YAML file during runtime and run\naccordingly.\n\n```bash\nCONFIG=https://raw.githubusercontent.com/linkerd/linkerd2-conformance/master/config.yaml\n\ncurl -sL $CONFIG \u003e config.yaml\n```\n\n### Configuration options\n\nThis section describes the various configuration\noptions and its default values. Not providing a\nconfiguration file, or providing a partial\nconfiguration file will result in the tests running\non default settings as described below\n\n| Option | Description | Default value |\n|-|-|-|\n| `linkerdVersion` | The linkerd2 binary version to use | Latest stable release |\n| `linkerdBinaryPath` | If specified, the tests use the binary installed in the directory. It is recommended that this is left\nunspecified while using Sonobuoy or if upgrade tests are enabled | `$HOME/.linkerd2/bin/linkerd` |\n| `clusterDomain` | Use the specified cluster domain | `\"cluster.local\"` |\n| `K8sContext` | Use the specified K8s context. Its is recommended that while running the tests with Sonobuoy (`sonobuoy run`), use the `--context` flag | `\"\"` |\n| `controlPlane.namespace` | Installs the control plane in the specified namespace | `\"l5d-conformance\"` |\n| `controlPlane.config.ha` | Use a high-availability control plane for the tests | `false` |\n| `controlPlane.config.flags` | Use the specified `linkerd install` CLI flag options while testing control plane installation | `[]` |\n| `controlPlane.config.addOns` | Use the specified add-on configuration while testing control plane installation | `nil` |\n| `testCase.lifecycle.skip` | Skip the pre-flight control plane installation tests | `false` |\n| `testCase.lifecycle.upgradeFromVersion` | If specified, first install the CLI and control plane using the specified version, and test if they can be upgraded to `linkerdVersion` | `\"\"` |\n| `testCase.lifecycle.reinstall` | If true, install a new control plane for each test. Otherwise, use a single control plane throughout | `false` |\n| `testCase.lifecycle.uninstall` | If using a single control plane, uninstall once the tests complete (whether they pass or fail) | `false` |\n| `testCase.inject.skip` | Skip proxy injection tests | `false` |\n| `testCase.inject.clean` | Delete the resources created for testing proxy injection | `false` |\n| `testCase.ingress.skip` | If true, skips all ingress tests | `false` |\n| `testCase.ingress.config.controllers` | List of ingress controllers to test. Currently only supports `nginx` | []string |\n\n## Usage\n\nThis section outlines the various methods that can\nbe used to run the conformance tests against your\n[Kubernetes](https://kubernetes.io/) cluster\n\n### Using the Sonobuoy CLI\n\n[Sonobuoy](https://github.com/vmware-tanzu/sonobuoy)\noffers a reliable way to run diagnostic tests in a\nKubernetes cluster. We leverage its [plugin model](https://sonobuoy.io/docs/master/plugins/)\nto run conformance tests inside a Kubernetes pod.\n\nThe below commands assume that the user has the\n[Sonobuoy CLI](https://github.com/vmware-tanzu/sonobuoy#installation)\nand [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/)\n(with a correctly configured `kubeconfig`) installed locally.\n\nThis repo provides a Sonobuoy plugin file that is intended to be\nplugged into the Sonobuoy CLI. Sonobuoy reads the plugin definition,\nand spins up a pod with the [linkerd2-conformance Docker image](#).\n\n```bash\n# Create a ConfigMap from the `config.yaml` mentioned in the previous section\n# This step allows the sonobuoy pod to read the test configurations.\n$ kubectl create ns sonobuoy \u0026\u0026 \\\n  kubectl create cm l5d-config \\\n  -n sonobuoy \\\n  --from-file=config.yaml=/path/to/config.yaml\n\n# Run the plugin\n$ plugin=https://raw.githubusercontent.com/linkerd/linkerd2-conformance/master/sonobuoy/plugin.yaml\n\n$ sonobuoy run \\\n  --plugin $plugin \\\n  --skip-preflight \\\n  --wait\n\n# [Optional] Check the status of the pod\n$ sonobuoy status\n\n# Retrieve the test results\n# This command downloads the tar ball containing the results\n$ results=$(sonobuoy retrieve)\n\n# Inspect the results\n$ sonobuoy results $results --mode dump\n\n# Clean up your cluster\n$ sonobuoy delete --wait\n```\n\n### Running the tests locally\n\nThese commands assume a working [Go 1.14](https://golang.org/doc/go1.14)\nenvironment along with the\n[Linkerd2 CLI](https://linkerd.io/2/getting-started/#step-1-install-the-cli)\nand [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/)\n(with a correctly configured `kubeconfig`) installed.\n\n```bash\n# clone this repository\n$ git clone https://github.com/linkerd/linkerd2-conformance\n\n# Navigate into project directory\n$ cd linkerd2-conformance\n\n$ go test -timeout 1h -ginkgo.v\n\n# Optionally, you may also use the -ginkgo.reportFile flag to\n# get a JUnit report\n\n$ go test -timeout 1h -ginkgo.v -ginkgo.reportFile=path/to/report.xml\n```\n\n## Adding new tests\n\nThis project makes use of [Ginkgo](https://github.com/onsi/ginkgo)\npaired with [Gomega](https://github.com/onsi/gomega) matcher\nlibrary to describe tests and write assertions. Each of the\ntests can be found under the `tests/` folder, in its respective packages.\n\nRather than having a separate test suite for each feature\n(and its associated `_test.go` files), this project provides\na single test suite that runs tests for each of the features\nas an organized collection of\n[specs](https://onsi.github.io/ginkgo/#adding-specs-to-a-suite).\nThis was done to not only have greater control over the order in\nwhich the tests are run, but also to have a smooth\nand consistent contribution experience.\n\nFor the sake of understanding, we shall assume a feature\ncalled `l5dFeature`, for which we shall add a new test\nas shown below.\n\n#### 1. Bootstrapping\n\nTo add a new test for `l5Feature`, we first add a new\npackage `l5dFeature` under the `specs` folder.\n\n```bash\nmkdir specs/l5dFeature\n```\n\nOur new package shall mainly require 2 new files\n\n- `spec.go` - this file holds the description and structure\nof the test in the form of\n[`Describe`](https://onsi.github.io/ginkgo/#organizing-specs-with-containers-describe-and-context),\n[`It`](https://onsi.github.io/ginkgo/#individual-specs-it),\n[`Context`](https://onsi.github.io/ginkgo/#organizing-specs-with-containers-describe-and-context),\n[etc.](https://onsi.github.io/ginkgo/#structuring-your-specs) blocks.\n- `tests.go` - this file shall contain assertions and testing logic\nfor each of our specs as described in `specs.go`\n\n```bash\ntouch specs/l5dFeature/tests.go\ntouch specs/l5dFeature/spec.go\n```\n\n#### 2. Writing the tests\n\n`spec.go` must contain a single (if required, more) exported\nfunction that returns a `ginkgo.Describe` block that holds\nthe specs. This function must be named `Runl5dFeatureTests`. \n\nFor example\n\n```go\n// spec.go\n\npackage l5dFeature\n\nimport (\n\t\"github.com/onsi/ginkgo\"\n)\n\nfunc Runl5dFeatureTests() bool {\n  return ginkgo.Describe(\"l5d Feature\", func() {\n    ginkgo.It(\"can do something cool\", testDoSomethingCool)\n    ginkgo.It(\"can do something cooler\", testDoSomethingCooler)\n\n    ginkgo.It(\"should throw error\", func() {\n      ginkgo.When(\"this is unspecified\", testThrowErrorUnspecified)\n      ginkgo.When(\"something breaks\", testThrowErrorWhenBroken)\n    })\n  })\n}\n```\n\n`tests.go` must contain the functions that do the actual testing\nand assertions, which are used as callbacks as shown above.\n\nFor example\n\n```go\n// tests.go\n\npackage l5dFeature\n\nimport (\n\t\"github.com/onsi/ginkgo\"\n\t\"github.com/onsi/gomega\"\n)\n\nfunc testSomethingCool() {\n  // ...add testing logic here\n\n  err := doSomethingCool()\n\n  // sample assertion\n  gomega.Expect(err).Should(gomega.BeNil(), \"could not do something cool\")\n}\n```\n\n#### 3. Wiring up the newly added test\n\nOnce the tests have been added, the newly written\n`Runl5dFeatureTests` must be brought to scope under\nthe `specs` package. To do so, simply import the `l5dFeature`\npackage under `specs/specs.go`, and call `Runl5dFeatureTests`\nin the function body of `runPrimaryTests` (or `runLifecycleTests`\ndepending on what is being tested).\n\nFor example\n\n```go\nfunc runPrimaryTests() bool {\n\treturn ginkgo.Describe(\"\", func() {\n    // ...test initialisation logic here\n\n    // Bring main tests into scope\n    _ = inject.RunInjectTests()\n    _ = l5dFeature.Runl5dFeatureTests() // call your test here\n\n    // ...post testing logic\n\t})\n}\n\n```\n\n\u003c!-- refs --\u003e\n[logo]: https://user-images.githubusercontent.com/9226/33582867-3e646e02-d90c-11e7-85a2-2e238737e859.png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinkerd%2Flinkerd2-conformance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinkerd%2Flinkerd2-conformance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinkerd%2Flinkerd2-conformance/lists"}