Merge pull request #10823 from azhao155/yzhao/feature/auto-hook
Add auto-pause webhook to inject env into pods for redirecting in-cluster kubectl request to reverse proxy of api server.pull/10952/head
commit
660cc42e88
|
@ -27,6 +27,7 @@ _testmain.go
|
|||
*.prof
|
||||
|
||||
/deploy/kicbase/auto-pause
|
||||
/deploy/addons/auto-pause/auto-pause-hook
|
||||
/out
|
||||
/_gopath
|
||||
|
||||
|
|
17
Makefile
17
Makefile
|
@ -100,6 +100,9 @@ SHA512SUM=$(shell command -v sha512sum || echo "shasum -a 512")
|
|||
# to update minikubes default, update deploy/addons/gvisor
|
||||
GVISOR_TAG ?= latest
|
||||
|
||||
# auto-pause-hook tag to push changes to
|
||||
AUTOPAUSE_HOOK_TAG ?= 1.13
|
||||
|
||||
# storage provisioner tag to push changes to
|
||||
STORAGE_PROVISIONER_TAG ?= v4
|
||||
|
||||
|
@ -834,6 +837,20 @@ out/mkcmp:
|
|||
deploy/kicbase/auto-pause: $(SOURCE_GENERATED) $(SOURCE_FILES)
|
||||
GOOS=linux GOARCH=$(GOARCH) go build -o $@ cmd/auto-pause/auto-pause.go
|
||||
|
||||
.PHONY: deploy/addons/auto-pause/auto-pause-hook
|
||||
deploy/addons/auto-pause/auto-pause-hook: $(SOURCE_GENERATED) ## Build auto-pause hook addon
|
||||
$(if $(quiet),@echo " GO $@")
|
||||
$(Q)GOOS=linux CGO_ENABLED=0 go build -a --ldflags '-extldflags "-static"' -tags netgo -installsuffix netgo -o $@ cmd/auto-pause/auto-pause-hook/main.go cmd/auto-pause/auto-pause-hook/config.go cmd/auto-pause/auto-pause-hook/certs.go
|
||||
|
||||
.PHONY: auto-pause-hook-image
|
||||
auto-pause-hook-image: deploy/addons/auto-pause/auto-pause-hook ## Build docker image for auto-pause hook
|
||||
docker build -t docker.io/azhao155/auto-pause-hook:$(AUTOPAUSE_HOOK_TAG) ./deploy/addons/auto-pause
|
||||
|
||||
.PHONY: push-auto-pause-hook-image
|
||||
push-auto-pause-hook-image: auto-pause-hook-image
|
||||
docker login docker.io/azhao155
|
||||
$(MAKE) push-docker IMAGE=docker.io/azhao155/auto-pause-hook:$(AUTOPAUSE_HOOK_TAG)
|
||||
|
||||
.PHONY: out/performance-bot
|
||||
out/performance-bot:
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/pr-bot/bot.go
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright 2021 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// generate https certs for the webhook server
|
||||
func gencerts() (caCert []byte, serverCert []byte, serverKey []byte) {
|
||||
var caPEM, serverCertPEM, serverPrivKeyPEM *bytes.Buffer
|
||||
// CA config
|
||||
ca := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(2020),
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"velotio.com"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(1, 0, 0),
|
||||
IsCA: true,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
// CA private key
|
||||
caPrivKey, err := rsa.GenerateKey(cryptorand.Reader, 4096)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// Self signed CA certificate
|
||||
caBytes, err := x509.CreateCertificate(cryptorand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// PEM encode CA cert
|
||||
caPEM = new(bytes.Buffer)
|
||||
_ = pem.Encode(caPEM, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: caBytes,
|
||||
})
|
||||
|
||||
dnsNames := []string{"webhook",
|
||||
"webhook.auto-pause", "webhook.auto-pause.svc"}
|
||||
commonName := "webhook.auto-pause.svc"
|
||||
|
||||
// server cert config
|
||||
cert := &x509.Certificate{
|
||||
DNSNames: dnsNames,
|
||||
SerialNumber: big.NewInt(1658),
|
||||
Subject: pkix.Name{
|
||||
CommonName: commonName,
|
||||
Organization: []string{"velotio.com"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(1, 0, 0),
|
||||
SubjectKeyId: []byte{1, 2, 3, 4, 6},
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
}
|
||||
|
||||
// server private key
|
||||
serverPrivKey, err := rsa.GenerateKey(cryptorand.Reader, 4096)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// sign the server cert
|
||||
serverCertBytes, err := x509.CreateCertificate(cryptorand.Reader, cert, ca, &serverPrivKey.PublicKey, caPrivKey)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// PEM encode the server cert and key
|
||||
serverCertPEM = new(bytes.Buffer)
|
||||
_ = pem.Encode(serverCertPEM, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: serverCertBytes,
|
||||
})
|
||||
|
||||
serverPrivKeyPEM = new(bytes.Buffer)
|
||||
_ = pem.Encode(serverPrivKeyPEM, &pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(serverPrivKey),
|
||||
})
|
||||
|
||||
return caPEM.Bytes(), serverCertPEM.Bytes(), serverPrivKeyPEM.Bytes()
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
Copyright 2021 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
var (
|
||||
webhookName = "env-inject-webhook"
|
||||
webhookConfigName = "env-inject.zyanshu.io"
|
||||
skipLabel = "auto-pause-skip"
|
||||
)
|
||||
|
||||
// Create a clientset with in-cluster config.
|
||||
func client() *kubernetes.Clientset {
|
||||
config, err := rest.InClusterConfig()
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
return clientset
|
||||
}
|
||||
|
||||
// Retrieve the CA cert that will signed the cert used by the
|
||||
// "GenericAdmissionWebhook" plugin admission controller.
|
||||
func apiServerCert(clientset *kubernetes.Clientset) []byte {
|
||||
c, err := clientset.CoreV1().ConfigMaps("kube-system").Get("extension-apiserver-authentication", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
|
||||
pem, ok := c.Data["requestheader-client-ca-file"]
|
||||
if !ok {
|
||||
glog.Fatalf(fmt.Sprintf("cannot find the ca.crt in the configmap, configMap.Data is %#v", c.Data))
|
||||
}
|
||||
glog.Info("client-ca-file=", pem)
|
||||
return []byte(pem)
|
||||
}
|
||||
|
||||
func configTLS(clientset *kubernetes.Clientset, serverCert []byte, serverKey []byte) *tls.Config {
|
||||
cert := apiServerCert(clientset)
|
||||
apiserverCA := x509.NewCertPool()
|
||||
apiserverCA.AppendCertsFromPEM(cert)
|
||||
|
||||
sCert, err := tls.X509KeyPair(serverCert, serverKey)
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{sCert},
|
||||
ClientCAs: apiserverCA,
|
||||
ClientAuth: tls.VerifyClientCertIfGiven, // TODO: actually require client cert
|
||||
}
|
||||
}
|
||||
|
||||
// register this example webhook admission controller with the kube-apiserver
|
||||
// by creating externalAdmissionHookConfigurations.
|
||||
func selfRegistration(clientset *kubernetes.Clientset, caCert []byte) {
|
||||
client := clientset.AdmissionregistrationV1().MutatingWebhookConfigurations()
|
||||
_, err := client.Get(webhookName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
if err2 := client.Delete(webhookName, &metav1.DeleteOptions{}); err2 != nil {
|
||||
glog.Fatal(err2)
|
||||
}
|
||||
}
|
||||
var failurePolicy v1.FailurePolicyType = v1.Fail
|
||||
var sideEffects v1.SideEffectClass = v1.SideEffectClassNone
|
||||
|
||||
webhookConfig := &v1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: webhookName,
|
||||
},
|
||||
Webhooks: []v1.MutatingWebhook{
|
||||
{
|
||||
Name: webhookConfigName,
|
||||
Rules: []v1.RuleWithOperations{
|
||||
{
|
||||
Operations: []v1.OperationType{v1.Create, v1.Update},
|
||||
Rule: v1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Operations: []v1.OperationType{v1.Create, v1.Update},
|
||||
Rule: v1.Rule{
|
||||
APIGroups: []string{"extensions"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
},
|
||||
},
|
||||
},
|
||||
FailurePolicy: &failurePolicy,
|
||||
ObjectSelector: &metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: skipLabel,
|
||||
Operator: metav1.LabelSelectorOpDoesNotExist,
|
||||
},
|
||||
},
|
||||
},
|
||||
ClientConfig: v1.WebhookClientConfig{
|
||||
Service: &v1.ServiceReference{
|
||||
Namespace: "auto-pause",
|
||||
Name: "webhook",
|
||||
},
|
||||
CABundle: caCert,
|
||||
},
|
||||
AdmissionReviewVersions: []string{"v1"},
|
||||
SideEffects: &sideEffects,
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := client.Create(webhookConfig); err != nil {
|
||||
glog.Fatalf("Client creation failed with %s", err)
|
||||
}
|
||||
log.Println("CLIENT CREATED")
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
Copyright 2021 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/mattbaird/jsonpatch"
|
||||
|
||||
v1 "k8s.io/api/admission/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
var (
|
||||
runtimeScheme = runtime.NewScheme()
|
||||
codecs = serializer.NewCodecFactory(runtimeScheme)
|
||||
deserializer = codecs.UniversalDeserializer()
|
||||
)
|
||||
|
||||
var targetIP *string
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("Handling a request")
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
log.Printf("error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
if contentType != "application/json" {
|
||||
log.Printf("Wrong content type. Got: %s", contentType)
|
||||
return
|
||||
}
|
||||
|
||||
admReq := v1.AdmissionReview{}
|
||||
admResp := v1.AdmissionReview{}
|
||||
|
||||
if _, _, err := deserializer.Decode(body, nil, &admReq); err != nil {
|
||||
log.Printf("Could not decode body: %v", err)
|
||||
admResp.Response = admissionError(err)
|
||||
} else {
|
||||
admResp.Response = AdmissionDecision(&admReq)
|
||||
}
|
||||
|
||||
admResp.APIVersion = "admission.k8s.io/v1"
|
||||
admResp.Kind = "AdmissionReview"
|
||||
resp, err := json.Marshal(admResp)
|
||||
if err != nil {
|
||||
log.Printf("error marshalling decision: %v", err)
|
||||
}
|
||||
log.Printf("%s", string(resp))
|
||||
if _, err := w.Write(resp); err != nil {
|
||||
log.Printf("error writing response %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func admissionError(err error) *v1.AdmissionResponse {
|
||||
return &v1.AdmissionResponse{
|
||||
Result: &metav1.Status{Message: err.Error()},
|
||||
}
|
||||
}
|
||||
|
||||
// Create the admission decision for the request
|
||||
func AdmissionDecision(admReq *v1.AdmissionReview) *v1.AdmissionResponse {
|
||||
req := admReq.Request
|
||||
var pod corev1.Pod
|
||||
|
||||
err := json.Unmarshal(req.Object.Raw, &pod)
|
||||
if err != nil {
|
||||
log.Printf("Could not unmarshal raw object: %v", err)
|
||||
return admissionError(err)
|
||||
}
|
||||
|
||||
log.Printf("AdmissionReview for Kind=%v Namespace=%v Name=%v UID=%v Operation=%v UserInfo=%v",
|
||||
req.Kind, req.Namespace, req.Name, req.UID, req.Operation, req.UserInfo)
|
||||
|
||||
patch, err := patchConfig(&pod)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Error creating conduit patch: %v", err)
|
||||
return admissionError(err)
|
||||
}
|
||||
|
||||
jsonPatchType := v1.PatchTypeJSONPatch
|
||||
|
||||
return &v1.AdmissionResponse{
|
||||
Allowed: true,
|
||||
Patch: patch,
|
||||
PatchType: &jsonPatchType,
|
||||
UID: req.UID,
|
||||
}
|
||||
}
|
||||
|
||||
func patchConfig(pod *corev1.Pod) ([]byte, error) {
|
||||
var patch []jsonpatch.JsonPatchOperation
|
||||
|
||||
configEnv := []corev1.EnvVar{
|
||||
{Name: "KUBERNETES_SERVICE_HOST", Value: *targetIP},
|
||||
{Name: "KUBERNETES_SERVICE_PORT", Value: strconv.Itoa(constants.AutoPauseProxyPort)}}
|
||||
for idx, container := range pod.Spec.Containers {
|
||||
patch = append(patch, addEnv(container.Env, configEnv, fmt.Sprintf("/spec/containers/%d/env", idx))...)
|
||||
}
|
||||
return json.Marshal(patch)
|
||||
}
|
||||
|
||||
// addEnv performs the mutation(s) needed to add the extra environment variables to the target
|
||||
// resource
|
||||
func addEnv(target, envVars []corev1.EnvVar, basePath string) (patch []jsonpatch.JsonPatchOperation) {
|
||||
first := len(target) == 0
|
||||
var value interface{}
|
||||
for _, envVar := range envVars {
|
||||
value = envVar
|
||||
path := basePath
|
||||
if first {
|
||||
first = false
|
||||
value = []corev1.EnvVar{envVar}
|
||||
} else {
|
||||
path += "/-"
|
||||
}
|
||||
patch = append(patch, jsonpatch.JsonPatchOperation{
|
||||
Operation: "add",
|
||||
Path: path,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return patch
|
||||
}
|
||||
|
||||
func main() {
|
||||
addr := flag.String("addr", ":8080", "address to serve on")
|
||||
targetIP = flag.String("targetIP", "192.168.49.2", "The reverse proxy IP")
|
||||
|
||||
http.HandleFunc("/", handler)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
log.Printf("Starting HTTPS webhook server on %+v and target ip is %v", *addr, *targetIP)
|
||||
cacert, serverCert, serverKey := gencerts()
|
||||
clientset := client()
|
||||
server := &http.Server{
|
||||
Addr: *addr,
|
||||
TLSConfig: configTLS(clientset, serverCert, serverKey),
|
||||
}
|
||||
go selfRegistration(clientset, cacert)
|
||||
err := server.ListenAndServeTLS("", "")
|
||||
if err != nil {
|
||||
glog.Fatalf("Start https server failed with %s", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
FROM golang:1.8
|
||||
ADD auto-pause-hook /auto-pause-hook
|
|
@ -0,0 +1,57 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: auto-pause
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: env-inject
|
||||
name: env-inject
|
||||
namespace: auto-pause
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: env-inject
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: env-inject
|
||||
name: env-inject
|
||||
spec:
|
||||
containers:
|
||||
- name: webhook
|
||||
image: {{.CustomRegistries.AutoPauseHook | default .ImageRepository | default .Registries.AutoPauseHook }}{{.Images.AutoPauseHook}}
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
command: ["/auto-pause-hook"]
|
||||
args: ["-targetIP={{.NetworkInfo.ControlPlaneNodeIP}}"]
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
role: webhook
|
||||
name: webhook
|
||||
namespace: auto-pause
|
||||
spec:
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: env-inject
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: webhook
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: auto-pause
|
|
@ -11,6 +11,7 @@ metadata:
|
|||
namespace: auto-pause
|
||||
labels:
|
||||
app: auto-pause-proxy
|
||||
auto-pause-skip: "true"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
|
|
2
go.mod
2
go.mod
|
@ -27,6 +27,7 @@ require (
|
|||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/google/go-cmp v0.5.5
|
||||
github.com/google/go-containerregistry v0.4.1
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
|
@ -52,6 +53,7 @@ require (
|
|||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/libvirt/libvirt-go v3.9.0+incompatible
|
||||
github.com/machine-drivers/docker-machine-driver-vmware v0.1.1
|
||||
github.com/mattbaird/jsonpatch v0.0.0-20200820163806-098863c1fc24 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
github.com/moby/hyperkit v0.0.0-20210108224842-2f061e447e14
|
||||
|
|
3
go.sum
3
go.sum
|
@ -416,6 +416,7 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
|||
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
|
||||
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -680,6 +681,8 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
|
|||
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
|
||||
github.com/maruel/panicparse v1.5.0/go.mod h1:aOutY/MUjdj80R0AEVI9qE2zHqig+67t2ffUDDiLzAM=
|
||||
github.com/mattbaird/jsonpatch v0.0.0-20200820163806-098863c1fc24 h1:uYuGXJBAi1umT+ZS4oQJUgKtfXCAYTR+n9zw1ViT0vA=
|
||||
github.com/mattbaird/jsonpatch v0.0.0-20200820163806-098863c1fc24/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
|
|
|
@ -216,7 +216,14 @@ https://github.com/kubernetes/minikube/issues/7332`, out.V{"driver_name": cc.Dri
|
|||
}
|
||||
}
|
||||
|
||||
data := assets.GenerateTemplateData(addon, cc.KubernetesConfig)
|
||||
var networkInfo assets.NetworkInfo
|
||||
if len(cc.Nodes) >= 1 {
|
||||
networkInfo.ControlPlaneNodeIP = cc.Nodes[0].IP
|
||||
} else {
|
||||
out.WarningT("At least needs control plane nodes to enable addon")
|
||||
}
|
||||
|
||||
data := assets.GenerateTemplateData(addon, cc.KubernetesConfig, networkInfo)
|
||||
return enableOrDisableAddonInternal(cc, addon, runner, data, enable)
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,11 @@ type Addon struct {
|
|||
Registries map[string]string
|
||||
}
|
||||
|
||||
// NetworkInfo contains control plane node IP address used for add on template
|
||||
type NetworkInfo struct {
|
||||
ControlPlaneNodeIP string
|
||||
}
|
||||
|
||||
// NewAddon creates a new Addon
|
||||
func NewAddon(assets []*BinAsset, enabled bool, addonName string, images map[string]string, registries map[string]string) *Addon {
|
||||
a := &Addon{
|
||||
|
@ -77,6 +82,11 @@ var Addons = map[string]*Addon{
|
|||
vmpath.GuestAddonsDir,
|
||||
"auto-pause.yaml",
|
||||
"0640"),
|
||||
MustBinAsset(
|
||||
"deploy/addons/auto-pause/auto-pause-hook.yaml.tmpl",
|
||||
vmpath.GuestAddonsDir,
|
||||
"auto-pause-hook.yaml",
|
||||
"0640"),
|
||||
MustBinAsset(
|
||||
"deploy/addons/auto-pause/haproxy.cfg",
|
||||
"/var/lib/minikube/",
|
||||
|
@ -95,9 +105,9 @@ var Addons = map[string]*Addon{
|
|||
|
||||
//GuestPersistentDir
|
||||
}, false, "auto-pause", map[string]string{
|
||||
"haproxy": "haproxy:2.3.5",
|
||||
"AutoPauseHook": "azhao155/auto-pause-hook:1.13",
|
||||
}, map[string]string{
|
||||
"haproxy": "gcr.io",
|
||||
"AutoPauseHook": "docker.io",
|
||||
}),
|
||||
"dashboard": NewAddon([]*BinAsset{
|
||||
// We want to create the kubernetes-dashboard ns first so that every subsequent object can be created
|
||||
|
@ -650,7 +660,7 @@ var Addons = map[string]*Addon{
|
|||
}
|
||||
|
||||
// GenerateTemplateData generates template data for template assets
|
||||
func GenerateTemplateData(addon *Addon, cfg config.KubernetesConfig) interface{} {
|
||||
func GenerateTemplateData(addon *Addon, cfg config.KubernetesConfig, networkInfo NetworkInfo) interface{} {
|
||||
|
||||
a := runtime.GOARCH
|
||||
// Some legacy docker images still need the -arch suffix
|
||||
|
@ -669,6 +679,7 @@ func GenerateTemplateData(addon *Addon, cfg config.KubernetesConfig) interface{}
|
|||
Images map[string]string
|
||||
Registries map[string]string
|
||||
CustomRegistries map[string]string
|
||||
NetworkInfo map[string]string
|
||||
}{
|
||||
Arch: a,
|
||||
ExoticArch: ea,
|
||||
|
@ -679,11 +690,15 @@ func GenerateTemplateData(addon *Addon, cfg config.KubernetesConfig) interface{}
|
|||
Images: addon.Images,
|
||||
Registries: addon.Registries,
|
||||
CustomRegistries: make(map[string]string),
|
||||
NetworkInfo: make(map[string]string),
|
||||
}
|
||||
if opts.ImageRepository != "" && !strings.HasSuffix(opts.ImageRepository, "/") {
|
||||
opts.ImageRepository += "/"
|
||||
}
|
||||
|
||||
// Network info for generating template
|
||||
opts.NetworkInfo["ControlPlaneNodeIP"] = networkInfo.ControlPlaneNodeIP
|
||||
|
||||
if opts.Images == nil {
|
||||
opts.Images = make(map[string]string) // Avoid nil access when rendering
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue