more work on mutatiuon controller
This commit is contained in:
parent
cd14bc11fa
commit
d029a6a0bf
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
.vscode/*
|
||||
.vscode
|
@ -1,184 +1,126 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
admission "k8s.io/api/admission/v1"
|
||||
core "k8s.io/api/core/v1"
|
||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Allowed bool
|
||||
Msg string
|
||||
PatchOps []patchOperation
|
||||
}
|
||||
|
||||
type admitFunc func(request *admission.AdmissionRequest) (*result, error)
|
||||
|
||||
type hook struct {
|
||||
Create admitFunc
|
||||
Delete admitFunc
|
||||
Update admitFunc
|
||||
Connect admitFunc
|
||||
}
|
||||
|
||||
func webMutatePod(w http.ResponseWriter, r *http.Request) {
|
||||
//https://github.com/douglasmakey/admissioncontroller
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
var (
|
||||
codecs = serializer.NewCodecFactory(runtime.NewScheme())
|
||||
)
|
||||
|
||||
func admissionReviewFromRequest(r *http.Request, deserializer runtime.Decoder) (*admission.AdmissionReview, error) {
|
||||
// Validate that the incoming content type is correct.
|
||||
if r.Header.Get("Content-Type") != "application/json" {
|
||||
return nil, fmt.Errorf("expected application/json content-type")
|
||||
podsValidation := hook{
|
||||
Create: validateCreate(),
|
||||
}
|
||||
|
||||
// Get the body data, which will be the AdmissionReview
|
||||
// content for the request.
|
||||
var body []byte
|
||||
if r.Body != nil {
|
||||
requestData, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
admissionHandler := &struct {
|
||||
decoder runtime.Decoder
|
||||
}{
|
||||
decoder: serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer(),
|
||||
}
|
||||
|
||||
// read request body
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
tmpltError(w, http.StatusBadRequest, "No data in request body.")
|
||||
return
|
||||
}
|
||||
|
||||
// see if request body can be decoded
|
||||
var review admission.AdmissionReview
|
||||
if _, _, err := admissionHandler.decoder.Decode(body, nil, &review); err != nil {
|
||||
tmpltError(w, http.StatusBadRequest, "Unable to decode request body.")
|
||||
return
|
||||
}
|
||||
|
||||
var o *result
|
||||
switch review.Request.Operation {
|
||||
case admission.Create:
|
||||
if podsValidation.Create == nil {
|
||||
tmpltError(w, http.StatusBadRequest, fmt.Sprintf("operation %s is not registered", review.Request.Operation))
|
||||
return
|
||||
}
|
||||
body = requestData
|
||||
o, _ = podsValidation.Create(review.Request)
|
||||
case admission.Update:
|
||||
if podsValidation.Update == nil {
|
||||
tmpltError(w, http.StatusBadRequest, fmt.Sprintf("operation %s is not registered", review.Request.Operation))
|
||||
return
|
||||
}
|
||||
o, _ = podsValidation.Update(review.Request)
|
||||
case admission.Delete:
|
||||
if podsValidation.Delete == nil {
|
||||
tmpltError(w, http.StatusBadRequest, fmt.Sprintf("operation %s is not registered", review.Request.Operation))
|
||||
return
|
||||
}
|
||||
o, _ = podsValidation.Delete(review.Request)
|
||||
case admission.Connect:
|
||||
if podsValidation.Connect == nil {
|
||||
tmpltError(w, http.StatusBadRequest, fmt.Sprintf("operation %s is not registered", review.Request.Operation))
|
||||
return
|
||||
}
|
||||
o, _ = podsValidation.Connect(review.Request)
|
||||
}
|
||||
|
||||
// Decode the request body into
|
||||
admissionReviewRequest := &admission.AdmissionReview{}
|
||||
if _, _, err := deserializer.Decode(body, nil, admissionReviewRequest); err != nil {
|
||||
return nil, err
|
||||
admissionResult := admission.AdmissionReview{
|
||||
Response: &admission.AdmissionResponse{
|
||||
UID: review.Request.UID,
|
||||
Allowed: o.Allowed,
|
||||
Result: &meta.Status{
|
||||
Message: o.Msg,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return admissionReviewRequest, nil
|
||||
}
|
||||
|
||||
func webMutatePod(w http.ResponseWriter, r *http.Request) {
|
||||
httpAccessLog(r)
|
||||
|
||||
deserializer := codecs.UniversalDeserializer()
|
||||
|
||||
// Parse the AdmissionReview from the http request.
|
||||
admissionReviewRequest, err := admissionReviewFromRequest(r, deserializer)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("error getting admission review from request: %v", err)
|
||||
log.Printf("[ERROR] %v", msg)
|
||||
tmpltError(w, http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
// Do server-side validation that we are only dealing with a pod resource. This
|
||||
// should also be part of the MutatingWebhookConfiguration in the cluster, but
|
||||
// we should verify here before continuing.
|
||||
podResource := meta.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
|
||||
if admissionReviewRequest.Request.Resource != podResource {
|
||||
msg := fmt.Sprintf("did not receive pod, got %s", admissionReviewRequest.Request.Resource.Resource)
|
||||
log.Printf("[ERROR] %v", msg)
|
||||
tmpltError(w, http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
// Decode the pod from the AdmissionReview.
|
||||
rawRequest := admissionReviewRequest.Request.Object.Raw
|
||||
pod := core.Pod{}
|
||||
if _, _, err := deserializer.Decode(rawRequest, nil, &pod); err != nil {
|
||||
msg := fmt.Sprintf("error decoding raw pod: %v", err)
|
||||
log.Printf("[ERROR] %v", msg)
|
||||
tmpltError(w, http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
// check to see if mutation is required by looking for a label
|
||||
if !mutationRequired(&pod.ObjectMeta) {
|
||||
mutationResp(w, admissionReviewRequest, &admission.AdmissionResponse{Allowed: true})
|
||||
}
|
||||
|
||||
// Add sidecar
|
||||
sidecarContainer := []core.Container{{
|
||||
Image: "ca-cert-server:latest",
|
||||
}}
|
||||
|
||||
patchBytes, _ := createPatch(&pod, sidecarContainer)
|
||||
|
||||
// respond with patch
|
||||
mutationResp(w, admissionReviewRequest, &admission.AdmissionResponse{
|
||||
Allowed: true,
|
||||
Patch: patchBytes,
|
||||
PatchType: func() *admission.PatchType {
|
||||
pt := admission.PatchTypeJSONPatch
|
||||
return &pt
|
||||
}(),
|
||||
})
|
||||
}
|
||||
|
||||
// prepare response
|
||||
func mutationResp(w http.ResponseWriter, aRRequest *admission.AdmissionReview, aResponse *admission.AdmissionResponse) {
|
||||
var aRResponse admission.AdmissionReview
|
||||
aRResponse.Response = aResponse
|
||||
aRResponse.SetGroupVersionKind(aRRequest.GroupVersionKind())
|
||||
aRResponse.Response.UID = aRRequest.Request.UID
|
||||
|
||||
resp, err := json.Marshal(aRResponse)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("error marshalling response json: %v", err)
|
||||
log.Printf("[ERROR] %v", msg)
|
||||
tmpltError(w, http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
resp, _ := json.Marshal(admissionResult)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
/*
|
||||
// create mutation patch for resources
|
||||
func createPatch(pod *core.Pod, containers []core.Container) ([]byte, error) {
|
||||
var (
|
||||
patch []patchOperation
|
||||
first bool
|
||||
value interface{}
|
||||
)
|
||||
|
||||
if len(pod.Spec.Containers) == 0 {
|
||||
first = true
|
||||
}
|
||||
|
||||
for _, add := range containers {
|
||||
value = add
|
||||
path := "/spec/containers"
|
||||
if first {
|
||||
first = false
|
||||
value = []core.Container{add}
|
||||
} else {
|
||||
path = path + "/-"
|
||||
func validateCreate() admitFunc {
|
||||
return func(r *admission.AdmissionRequest) (*result, error) {
|
||||
pod, err := parsePod(r.Object.Raw)
|
||||
if err != nil {
|
||||
return &result{Msg: err.Error()}, nil
|
||||
}
|
||||
patch = append(patch, patchOperation{
|
||||
Op: "add",
|
||||
Path: path,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
|
||||
return json.Marshal(patch)
|
||||
for _, c := range pod.Spec.Containers {
|
||||
if strings.HasSuffix(c.Image, ":latest") {
|
||||
return &result{Msg: "You cannot use the tag 'latest' in a container."}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return &result{Allowed: true}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the target resource needs to be mutated
|
||||
func mutationRequired(metadata *meta.ObjectMeta) bool {
|
||||
var ignoredNamespaces = []string{
|
||||
meta.NamespaceSystem,
|
||||
meta.NamespacePublic,
|
||||
func parsePod(object []byte) (*core.Pod, error) {
|
||||
var pod core.Pod
|
||||
if err := json.Unmarshal(object, &pod); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skip special kubernetes system namespaces
|
||||
for _, namespace := range ignoredNamespaces {
|
||||
if metadata.Namespace == namespace {
|
||||
log.Printf("[TRACE] Protected namespace detected (%s) skipping mutation: %s", metadata.Namespace, metadata.Name)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
annotations := metadata.GetLabels()
|
||||
if annotations == nil {
|
||||
annotations = map[string]string{}
|
||||
}
|
||||
|
||||
// determine whether to perform mutation based on annotation for the target resource
|
||||
var required bool
|
||||
switch strings.ToLower(annotations["sidecar-injector-webhook/inject"]) {
|
||||
case "yes", "y", "true", "t", "on":
|
||||
required = true
|
||||
default:
|
||||
required = false
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] Mutation policy for %s/%s: required:%b", metadata.Namespace, metadata.Name, required)
|
||||
return required
|
||||
return &pod, nil
|
||||
}
|
||||
*/
|
||||
|
59
cmd/webhook/patch.go
Normal file
59
cmd/webhook/patch.go
Normal file
@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
const (
|
||||
addOperation = "add"
|
||||
removeOperation = "remove"
|
||||
replaceOperation = "replace"
|
||||
copyOperation = "copy"
|
||||
moveOperation = "move"
|
||||
)
|
||||
|
||||
type patchOperation struct {
|
||||
Op string `json:"op"`
|
||||
Path string `json:"path"`
|
||||
From string `json:"from"`
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func addPatchOperation(path string, value interface{}) patchOperation {
|
||||
return patchOperation{
|
||||
Op: addOperation,
|
||||
Path: path,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// RemovePatchOperation returns a remove JSON patch operation.
|
||||
func removePatchOperation(path string) patchOperation {
|
||||
return patchOperation{
|
||||
Op: removeOperation,
|
||||
Path: path,
|
||||
}
|
||||
}
|
||||
|
||||
// ReplacePatchOperation returns a replace JSON patch operation.
|
||||
func replacePatchOperation(path string, value interface{}) patchOperation {
|
||||
return patchOperation{
|
||||
Op: replaceOperation,
|
||||
Path: path,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// CopyPatchOperation returns a copy JSON patch operation.
|
||||
func copyPatchOperation(from, path string) patchOperation {
|
||||
return patchOperation{
|
||||
Op: copyOperation,
|
||||
Path: path,
|
||||
From: from,
|
||||
}
|
||||
}
|
||||
|
||||
// MovePatchOperation returns a move JSON patch operation.
|
||||
func movePatchOperation(from, path string) patchOperation {
|
||||
return patchOperation{
|
||||
Op: moveOperation,
|
||||
Path: path,
|
||||
From: from,
|
||||
}
|
||||
}
|
24
go.mod
24
go.mod
@ -2,4 +2,26 @@ module mutating-webhook
|
||||
|
||||
go 1.19
|
||||
|
||||
require github.com/hashicorp/logutils v1.0.0
|
||||
require (
|
||||
github.com/hashicorp/logutils v1.0.0
|
||||
k8s.io/api v0.25.2
|
||||
k8s.io/apimachinery v0.25.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/klog/v2 v2.70.1 // indirect
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
)
|
||||
|
85
go.sum
85
go.sum
@ -1,2 +1,87 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8=
|
||||
k8s.io/api v0.25.2/go.mod h1:qP1Rn4sCVFwx/xIhe+we2cwBLTXNcheRyYXwajonhy0=
|
||||
k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs=
|
||||
k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
|
||||
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
Loading…
x
Reference in New Issue
Block a user