{"id":16812002,"url":"https://github.com/riita10069/ket","last_synced_at":"2025-10-10T15:14:11.436Z","repository":{"id":43885605,"uuid":"401657710","full_name":"riita10069/ket","owner":"riita10069","description":"the simplest testing framework for Kubernetes controller.","archived":false,"fork":false,"pushed_at":"2022-02-14T14:39:22.000Z","size":253,"stargazers_count":39,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-10T15:14:11.195Z","etag":null,"topics":["custom-controller","kubernetes"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/riita10069.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-31T10:10:43.000Z","updated_at":"2024-08-03T07:36:37.000Z","dependencies_parsed_at":"2022-08-28T15:31:05.131Z","dependency_job_id":null,"html_url":"https://github.com/riita10069/ket","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/riita10069/ket","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riita10069%2Fket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riita10069%2Fket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riita10069%2Fket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riita10069%2Fket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/riita10069","download_url":"https://codeload.github.com/riita10069/ket/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riita10069%2Fket/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004574,"owners_count":26083735,"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","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["custom-controller","kubernetes"],"created_at":"2024-10-13T10:20:18.552Z","updated_at":"2025-10-10T15:14:11.406Z","avatar_url":"https://github.com/riita10069.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![ket](./ket.png)\n\n# KET(Kind E2e Test framework)\n\nKET is the simplest testing framework for Kubernetes controller.\nKET is available as open source software, and we look forward to contributions from any engineers.\n\n## Introduction\n\nThe goal of KET is to help you build what you need to test your Kubernetes Controller.\nIt is an open platform that allows developers to focus only on the responsibilities of the controller, without worrying about the complexities of running a cluster, building resources, and events that make the Reconciliation Loop work.\n\nKET has following feature.\n\n- create **kind** cluster\n- Provide **Build and Deploy** pipelines using Skaffold\n- The necessary client tools include **client-go and kubectl**\n- Reproduce declarative resource state, i.e., **kubectl apply -f**\n\nKET is composed of these components:\n\n- \u003ca href=\"https://kind.sigs.k8s.io/\"\u003eKind\u003c/a\u003e\n- \u003ca href=\"https://skaffold.dev/\"\u003eSkaffold\u003c/a\u003e\n- \u003ca href=\"https://kubernetes.io/docs/reference/kubectl/overview/\"\u003ekubectl\u003c/a\u003e\n- \u003ca href=\"https://github.com/kubernetes/client-go\"\u003eclient-go\u003c/a\u003e\n\n## Example\n\n### Setup for e2e testing\n\nIf you want to do E2E (end to end) testing against your Kubernetes controller.\n\nWe recommend you to build a cluster environment using TestMain.\n\n```go\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/riita10069/ket/pkg/setup\"\n\t\"k8s.io/apimachinery/pkg/types\"\n)\n\nfunc TestMain(m *testing.M) {\n\tos.Exit(func() int {\n\t\tctx := context.Background()\n\t\tctx, cancel := context.WithCancel(ctx)\n\t\tdefer cancel()\n\n\t\tcliSet, err := setup.Start(\n\t\t\tctx,\n\t\t\tsetup.WithBinaryDirectory(\"./_dev/bin\"),\n\t\t\tsetup.WithKindClusterName(\"ket-controller\"),\n\t\t\tsetup.WithKindVersion(\"0.11.0\"),\n\t\t\tsetup.WithKubernetesVersion(\"1.20.2\"),\n\t\t\tsetup.WithKubeconfigPath(\"./.kubeconfig\"),\n\t\t\tsetup.WithCRDKustomizePath(\"./manifest/crd\"),\n\t\t\tsetup.WithUseSkaffold(),\n\t\t\tsetup.WithSkaffoldVersion(\"1.26.1\"),\n\t\t\tsetup.WithSkaffoldYaml(\"./manifest/skaffold/skaffold.yaml\"),\n\t\t)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"failed to setup kind, kubectl and skaffold: %s\\n\", err)\n\t\t\treturn 1\n\t\t}\n\n\t\tkubectl := cliSet.Kubectl\n\t\t_, err = kubectl.WaitAResource(\n\t\t\tctx,\n\t\t\t\"deploy\",\n\t\t\ttypes.NamespacedName{\n\t\t\t\tNamespace: \"CONTROLLER_NAMESPACE\",\n\t\t\t\tName:      \"CONTROLLER_NAME\",\n\t\t\t},\n\t\t)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"failed to wait resource: %s\\n\", err)\n\t\t\treturn 1\n\t\t}\n\n\t\treturn m.Run()\n\t}())\n}\n```\n\n`setup.Start()`function builds the testing environment.\n\n### context.Context\n\n`setup.Start` will start one or more goroutines.\nIt is desirable to give a context that will be canceled() at the end of the test.\n\n### WithBinaryDirectory\n\nSave the binary, e.g. kubectl, in the specified directory.\nBy default, `. /bin` is used.\n\n### WithKindClusterName\n\nYou can specify the name of the Kind cluster.\nBy default, `ket` is used.\n\n### WithKubeconfigPath\n\nIt is possible to change the PATH of kubeconfig.\nThe default is to use `$HOME/.kube/config`.\n\nPlease see below for details.\nhttps://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/\n\n### WithCRDKustomizePath\n\nThe CRD resources used by the controller are Apply using \u003ca href=\"https://github.com/kubernetes-sigs/kustomize\"\u003ekustomize\u003c/a\u003e。\n\nThe path to kustomize.yaml should be given here.\nIf you do not use this option, the resource will not be applied.\nIf you don't need a CRD, you should.\n\n### WithUseSkaffold\n\nIf this is not used, the controller will not run on the cluster.\nIf you want to use a build with Skaffold, make sure to give this option explicitly.\nIf you want the controller to be built directly using the local Go environment, you do not need to use this option.\n\n### WithSkaffoldYaml\n\nIf you use `WithUseSkaffold()`, use it.\nThis will specify the PATH to \u003ca href=\"https://skaffold.dev/docs/references/yaml/\"\u003eskaffold.yaml\u003c/a\u003e.\n\n## clientSet\n\nThe return value of the setup.Start() function is the ClientSet struct.\n\n```go\ntype ClientSet struct {\n\tClientGo *k8s.ClientGo\n\tKubectl  *kubectl.Kubectl\n\tKind     *kind.Kind\n\tSkaffold *skaffold.Skaffold\n}\n```\n\n\nStart() function is a ClientSet struct, from which you can use the commands you need in your test logic.\n\n## kubectl\n\n### ApplyKustomize, ApplyFile\n\nApplyKustomize, ApplyFile will execute `kubectl apply -k` and `kubectl -f`.\n\nAlso, `ApplyAllManifest` will apply all files by passing the path of the file as an array.\nBy including this code at the beginning of the test case, declarative resource management using yaml files becomes possible.\n\n```go\nkubectl.ApplyAllManifest(ctx, tt.fixture.manifestPaths, false)\n```\n\nTo avoid affecting the next case, make sure to delete the created resource at the end of the case as follows\n\n```go\nkubectl.DeleteAllManifest(ctx, tt.fixture.manifestPaths, true)\n```\n\nAlso, resources created by other things such as Controller can be explicitly deleted as follows.\n\n```go\nkubectl.DeleteResource(ctx, \"ket\", \"ket-namespace\", \"pod\")\n```\n\nThe fourth argument gives the name of the resource to be deleted.\nThe name of the resource must be of type string according to the following table.\nhttps://kubernetes.io/ja/docs/reference/kubectl/_print/#resource-types\n\n\n### WaitAResource\n\nThis is a command that waits for a resource to be created.\nThe name of the resource must be of type string according to the following table.\nhttps://kubernetes.io/ja/docs/reference/kubectl/_print/#resource-types\n\nAlso, when the resource is a Pod or a Deployment, it will continue to wait until it is not only created but also has a Status of Ready.\nPlease note that ReplicaSet and DaemonSet are not supported yet.\n\n## verify using kubectl\n\nIt is more versatile to use cllient-go.\nHowever, I felt that there is merit in intuitive operation using kubectl, so I created some methods.\n\n\n\n\n\n### GetNamespacesList\n\nYou can get a list of Namespaces that exist in the cluster.\n\n\n### GetResourceNameList\n\nYou can get a list of Names of resources in a specific Namespace.\n\n## Kind\n\n### Create Cluster\n\nYou can create a kind cluster.\n\n### Delete Cluster\n\nifyou use this method, You can also delete the kind cluster at the end of the test.\n\n\n## Self-created commands\n\nOn KET, it is too simple and instantaneous to methodize the command you want to execute.\n\nThe KET API provided is still poor.\nHowever, you can use your own commands to do the operations you want to do.\nAnd I am very much looking forward to your contributions as well.\n\nSuppose you want to use the command `kubectl get all --all-namespaces -o=jsonpath='{.items[*].metadata.name}` as a method in your test.\n\nWhat we need to do to execute the kubectl command is to implement it as a method of the kubectl struct.\nIt is very easy to provide arguments to the command. We just need to create an array.\n\nYou can do this as follows\n\n```go\nfunc (k *Kubectl) AllResourcesNameList(ctx context.Context) (string, error) {\n\targs := []string{\"get\", \"all\", \"--all-namespaces\", \"-o=jsonpath='{.items[*].metadata.name}'\"}\n\tstdout, _, err := k.Capture(ctx, args)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t\n\treturn stdout, nil\n}\n```\n\nThis is the only way to receive the output.\nIf you do not need to receive the output, use Execute instead of Capture.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friita10069%2Fket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Friita10069%2Fket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friita10069%2Fket/lists"}