Permalink
Comparing changes
Open a pull request
- 3 commits
- 10 files changed
- 0 commit comments
- 1 contributor
Unified
Split
Showing
with
211 additions
and 84 deletions.
- +16 −4 cmd/virt-handler/virt-handler.go
- +1 −18 pkg/certificates/certificates.go
- +13 −0 pkg/certificates/certificates_suite_test.go
- +34 −0 pkg/certificates/certificates_test.go
- +8 −12 pkg/feature-gates/feature-gates.go
- +23 −0 pkg/util/util.go
- +26 −17 pkg/virt-api/api.go
- +14 −18 pkg/virt-controller/watch/application.go
- +54 −3 tests/{controller_leader_election_test.go → infra_test.go}
- +22 −12 tests/utils.go
| @@ -21,6 +21,7 @@ package main | ||
| import ( | ||
| "fmt" | ||
| "io/ioutil" | ||
| "net/http" | ||
| "os" | ||
| "time" | ||
| @@ -36,6 +37,8 @@ import ( | ||
| "k8s.io/client-go/tools/cache" | ||
| "k8s.io/client-go/tools/record" | ||
| "kubevirt.io/kubevirt/pkg/util" | ||
| "kubevirt.io/kubevirt/pkg/certificates" | ||
| "kubevirt.io/kubevirt/pkg/api/v1" | ||
| @@ -148,13 +151,22 @@ func (app *virtHandlerApp) Run() { | ||
| maxDevices, | ||
| ) | ||
| // Bootstrapping. From here on the startup order matters | ||
| stop := make(chan struct{}) | ||
| defer close(stop) | ||
| certStore, err := certificates.GenerateSelfSignedCert("virt-handler", certificates.GetNamespace()) | ||
| certsDirectory, err := ioutil.TempDir("", "certsdir") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| defer os.RemoveAll(certsDirectory) | ||
| namespace, err := util.GetNamespace() | ||
| if err != nil { | ||
| glog.Fatalf("Error searching for namespace: %v", err) | ||
| } | ||
| certStore, err := certificates.GenerateSelfSignedCert(certsDirectory, "virt-handler", namespace) | ||
| if err != nil { | ||
| glog.Fatalf("unable to generate certificates: %v", err) | ||
| } | ||
| // Bootstrapping. From here on the startup order matters | ||
| stop := make(chan struct{}) | ||
| defer close(stop) | ||
| go vmController.Run(3, stop) | ||
| http.Handle("/metrics", promhttp.Handler()) | ||
| @@ -1,16 +1,12 @@ | ||
| package certificates | ||
| import ( | ||
| "io/ioutil" | ||
| "strings" | ||
| "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/client-go/util/cert" | ||
| "k8s.io/client-go/util/cert/triple" | ||
| "k8s.io/client-go/util/certificate" | ||
| ) | ||
| func GenerateSelfSignedCert(name string, namespace string) (certificate.FileStore, error) { | ||
| func GenerateSelfSignedCert(certsDirectory string, name string, namespace string) (certificate.FileStore, error) { | ||
| caKeyPair, _ := triple.NewCA("kubevirt.io") | ||
| keyPair, _ := triple.NewServerKeyPair( | ||
| caKeyPair, | ||
| @@ -22,10 +18,6 @@ func GenerateSelfSignedCert(name string, namespace string) (certificate.FileStor | ||
| nil, | ||
| ) | ||
| certsDirectory, err := ioutil.TempDir("", "certsdir") | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| store, err := certificate.NewFileStore(name, certsDirectory, certsDirectory, "", "") | ||
| if err != nil { | ||
| return nil, err | ||
| @@ -36,12 +28,3 @@ func GenerateSelfSignedCert(name string, namespace string) (certificate.FileStor | ||
| } | ||
| return store, nil | ||
| } | ||
| func GetNamespace() string { | ||
| if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { | ||
| if ns := strings.TrimSpace(string(data)); len(ns) > 0 { | ||
| return ns | ||
| } | ||
| } | ||
| return v1.NamespaceSystem | ||
| } | ||
| @@ -0,0 +1,13 @@ | ||
| package certificates_test | ||
| import ( | ||
| . "github.com/onsi/ginkgo" | ||
| . "github.com/onsi/gomega" | ||
| "testing" | ||
| ) | ||
| func TestCertificates(t *testing.T) { | ||
| RegisterFailHandler(Fail) | ||
| RunSpecs(t, "Certificates Suite") | ||
| } |
| @@ -0,0 +1,34 @@ | ||
| package certificates_test | ||
| import ( | ||
| "io/ioutil" | ||
| "os" | ||
| . "github.com/onsi/ginkgo" | ||
| . "github.com/onsi/gomega" | ||
| "kubevirt.io/kubevirt/pkg/certificates" | ||
| ) | ||
| var _ = Describe("Certificates", func() { | ||
| var certDir string | ||
| BeforeEach(func() { | ||
| var err error | ||
| certDir, err = ioutil.TempDir("", "certsdir") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| }) | ||
| It("should be generated in temporary directory", func() { | ||
| store, err := certificates.GenerateSelfSignedCert(certDir, "testname", "testnamespace") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| _, err = store.Current() | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(store.CurrentPath()).To(ContainSubstring(certDir)) | ||
| }) | ||
| AfterEach(func() { | ||
| os.RemoveAll(certDir) | ||
| }) | ||
| }) |
| @@ -20,7 +20,6 @@ | ||
| package featuregates | ||
| import ( | ||
| "io/ioutil" | ||
| "os" | ||
| "strings" | ||
| "time" | ||
| @@ -29,6 +28,8 @@ import ( | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/util/wait" | ||
| "kubevirt.io/kubevirt/pkg/util" | ||
| "k8s.io/apimachinery/pkg/api/errors" | ||
| "kubevirt.io/kubevirt/pkg/kubecli" | ||
| @@ -41,26 +42,21 @@ const ( | ||
| cpuManager = "CPUManager" | ||
| ) | ||
| func getNamespace() string { | ||
| if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { | ||
| if ns := strings.TrimSpace(string(data)); len(ns) > 0 { | ||
| return ns | ||
| } | ||
| } | ||
| return metav1.NamespaceSystem | ||
| } | ||
| func ParseFeatureGatesFromConfigMap() { | ||
| virtClient, err := kubecli.GetKubevirtClient() | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| var cfgMap *k8sv1.ConfigMap | ||
| var curErr error | ||
| err = wait.PollImmediate(time.Second*1, time.Second*10, func() (bool, error) { | ||
| cfgMap, curErr = virtClient.CoreV1().ConfigMaps(getNamespace()).Get("kubevirt-config", metav1.GetOptions{}) | ||
| namespace, curErr := util.GetNamespace() | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| cfgMap, curErr = virtClient.CoreV1().ConfigMaps(namespace).Get("kubevirt-config", metav1.GetOptions{}) | ||
| if curErr != nil { | ||
| if errors.IsNotFound(curErr) { | ||
| @@ -0,0 +1,23 @@ | ||
| package util | ||
| import ( | ||
| "fmt" | ||
| "io/ioutil" | ||
| "os" | ||
| "strings" | ||
| "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| ) | ||
| const ServiceAccountNamespaceFile = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" | ||
| func GetNamespace() (string, error) { | ||
| if data, err := ioutil.ReadFile(ServiceAccountNamespaceFile); err == nil { | ||
| if ns := strings.TrimSpace(string(data)); len(ns) > 0 { | ||
| return ns, nil | ||
| } | ||
| } else if err != nil && !os.IsNotExist(err) { | ||
| return "", fmt.Errorf("failed to determine namespace from %s: %v", ServiceAccountNamespaceFile, err) | ||
| } | ||
| return v1.NamespaceSystem, nil | ||
| } |
| @@ -44,7 +44,7 @@ import ( | ||
| apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1" | ||
| aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" | ||
| "kubevirt.io/kubevirt/pkg/certificates" | ||
| "kubevirt.io/kubevirt/pkg/util" | ||
| "kubevirt.io/kubevirt/pkg/api/v1" | ||
| "kubevirt.io/kubevirt/pkg/feature-gates" | ||
| @@ -109,6 +109,7 @@ type virtAPIApp struct { | ||
| keyBytes []byte | ||
| clientCABytes []byte | ||
| requestHeaderClientCABytes []byte | ||
| namespace string | ||
| } | ||
| var _ service.Service = &virtAPIApp{} | ||
| @@ -143,6 +144,10 @@ func (app *virtAPIApp) Execute() { | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| app.namespace, err = util.GetNamespace() | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| app.Compose() | ||
| app.ConfigureOpenAPIService() | ||
| @@ -392,7 +397,7 @@ func deserializeStrings(in string) ([]string, error) { | ||
| } | ||
| func (app *virtAPIApp) getClientCert() error { | ||
| authConfigMap, err := app.virtCli.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get("extension-apiserver-authentication", metav1.GetOptions{}) | ||
| authConfigMap, err := app.virtCli.CoreV1().ConfigMaps(app.namespace).Get("extension-apiserver-authentication", metav1.GetOptions{}) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| @@ -444,9 +449,8 @@ func (app *virtAPIApp) getClientCert() error { | ||
| func (app *virtAPIApp) getSelfSignedCert() error { | ||
| var ok bool | ||
| namespace := certificates.GetNamespace() | ||
| generateCerts := false | ||
| secret, err := app.virtCli.CoreV1().Secrets(namespace).Get(virtApiCertSecretName, metav1.GetOptions{}) | ||
| secret, err := app.virtCli.CoreV1().Secrets(app.namespace).Get(virtApiCertSecretName, metav1.GetOptions{}) | ||
| if err != nil { | ||
| if k8serrors.IsNotFound(err) { | ||
| generateCerts = true | ||
| @@ -460,9 +464,9 @@ func (app *virtAPIApp) getSelfSignedCert() error { | ||
| caKeyPair, _ := triple.NewCA("kubevirt.io") | ||
| keyPair, _ := triple.NewServerKeyPair( | ||
| caKeyPair, | ||
| "virt-api."+namespace+".pod.cluster.local", | ||
| "virt-api."+app.namespace+".pod.cluster.local", | ||
| "virt-api", | ||
| namespace, | ||
| app.namespace, | ||
| "cluster.local", | ||
| nil, | ||
| nil, | ||
| @@ -475,7 +479,7 @@ func (app *virtAPIApp) getSelfSignedCert() error { | ||
| secret := k8sv1.Secret{ | ||
| ObjectMeta: metav1.ObjectMeta{ | ||
| Name: virtApiCertSecretName, | ||
| Namespace: namespace, | ||
| Namespace: app.namespace, | ||
| Labels: map[string]string{ | ||
| v1.AppLabel: "virt-api-aggregator", | ||
| }, | ||
| @@ -487,7 +491,7 @@ func (app *virtAPIApp) getSelfSignedCert() error { | ||
| signingCertBytesValue: app.signingCertBytes, | ||
| }, | ||
| } | ||
| _, err := app.virtCli.CoreV1().Secrets(namespace).Create(&secret) | ||
| _, err := app.virtCli.CoreV1().Secrets(app.namespace).Create(&secret) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| @@ -523,7 +527,6 @@ func (app *virtAPIApp) createWebhook() error { | ||
| } | ||
| func (app *virtAPIApp) createValidatingWebhook() error { | ||
| namespace := certificates.GetNamespace() | ||
| registerWebhook := false | ||
| vmiPathCreate := vmiCreateValidatePath | ||
| vmiPathUpdate := vmiUpdateValidatePath | ||
| @@ -555,7 +558,7 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| }}, | ||
| ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ | ||
| Service: &admissionregistrationv1beta1.ServiceReference{ | ||
| Namespace: namespace, | ||
| Namespace: app.namespace, | ||
| Name: virtApiServiceName, | ||
| Path: &vmiPathCreate, | ||
| }, | ||
| @@ -576,7 +579,7 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| }}, | ||
| ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ | ||
| Service: &admissionregistrationv1beta1.ServiceReference{ | ||
| Namespace: namespace, | ||
| Namespace: app.namespace, | ||
| Name: virtApiServiceName, | ||
| Path: &vmiPathUpdate, | ||
| }, | ||
| @@ -598,7 +601,7 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| }}, | ||
| ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ | ||
| Service: &admissionregistrationv1beta1.ServiceReference{ | ||
| Namespace: namespace, | ||
| Namespace: app.namespace, | ||
| Name: virtApiServiceName, | ||
| Path: &vmPath, | ||
| }, | ||
| @@ -620,7 +623,7 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| }}, | ||
| ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ | ||
| Service: &admissionregistrationv1beta1.ServiceReference{ | ||
| Namespace: namespace, | ||
| Namespace: app.namespace, | ||
| Name: virtApiServiceName, | ||
| Path: &vmirsPath, | ||
| }, | ||
| @@ -642,7 +645,7 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| }}, | ||
| ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ | ||
| Service: &admissionregistrationv1beta1.ServiceReference{ | ||
| Namespace: namespace, | ||
| Namespace: app.namespace, | ||
| Name: virtApiServiceName, | ||
| Path: &vmipresetPath, | ||
| }, | ||
| @@ -667,7 +670,7 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| } else { | ||
| for _, webhook := range webhookRegistration.Webhooks { | ||
| if webhook.ClientConfig.Service != nil && webhook.ClientConfig.Service.Namespace != namespace { | ||
| if webhook.ClientConfig.Service != nil && webhook.ClientConfig.Service.Namespace != app.namespace { | ||
| return fmt.Errorf("ValidatingAdmissionWebhook [%s] is already registered using services endpoints in a different namespace. Existing webhook registration must be deleted before virt-api can proceed.", virtWebhookValidator) | ||
| } | ||
| } | ||
| @@ -701,7 +704,10 @@ func (app *virtAPIApp) createValidatingWebhook() error { | ||
| } | ||
| func (app *virtAPIApp) createMutatingWebhook() error { | ||
| namespace := certificates.GetNamespace() | ||
| namespace, err := util.GetNamespace() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| registerWebhook := false | ||
| vmiPath := vmiMutatePath | ||
| @@ -775,7 +781,10 @@ func (app *virtAPIApp) createMutatingWebhook() error { | ||
| } | ||
| func (app *virtAPIApp) createSubresourceApiservice() error { | ||
| namespace := certificates.GetNamespace() | ||
| namespace, err := util.GetNamespace() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| config, err := kubecli.GetConfig() | ||
| if err != nil { | ||
| return err | ||
Oops, something went wrong.