func controllerSetup(startingObjects []runtime.Object, stopChannel chan struct{}, t *testing.T) ( /*caName*/ string, *fake.Clientset, *watch.FakeWatcher, *ServiceServingCertController) { certDir, err := ioutil.TempDir("", "serving-cert-unit-") if err != nil { t.Fatalf("unexpected error: %v", err) } caInfo := admin.DefaultServiceSignerCAInfo(certDir) caOptions := admin.CreateSignerCertOptions{ CertFile: caInfo.CertFile, KeyFile: caInfo.KeyFile, Name: admin.DefaultServiceServingCertSignerName(), Output: ioutil.Discard, } ca, err := caOptions.CreateSignerCert() if err != nil { t.Fatalf("unexpected error: %v", err) } kubeclient := fake.NewSimpleClientset(startingObjects...) fakeWatch := watch.NewFake() kubeclient.PrependReactor("create", "*", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, action.(core.CreateAction).GetObject(), nil }) kubeclient.PrependReactor("update", "*", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, action.(core.UpdateAction).GetObject(), nil }) kubeclient.PrependWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) controller := NewServiceServingCertController(kubeclient.Core(), kubeclient.Core(), ca, "cluster.local", 10*time.Minute) return caOptions.Name, kubeclient, fakeWatch, controller }
// BuildSerializeableMasterConfig takes the MasterArgs (partially complete config) and uses them along with defaulting behavior to create the fully specified // config object for starting the master func (args MasterArgs) BuildSerializeableMasterConfig() (*configapi.MasterConfig, error) { masterPublicAddr, err := args.GetMasterPublicAddress() if err != nil { return nil, err } assetPublicAddr, err := args.GetAssetPublicAddress() if err != nil { return nil, err } dnsBindAddr, err := args.GetDNSBindAddress() if err != nil { return nil, err } listenServingInfo := servingInfoForAddr(&args.ListenArg.ListenAddr) // always include the all-in-one server's web console as an allowed CORS origin // always include localhost as an allowed CORS origin // always include master public address as an allowed CORS origin corsAllowedOrigins := sets.NewString(args.CORSAllowedOrigins...) corsAllowedOrigins.Insert(assetPublicAddr.Host, masterPublicAddr.Host, "localhost", "127.0.0.1") etcdAddress, err := args.GetEtcdAddress() if err != nil { return nil, err } builtInEtcd := !args.EtcdAddr.Provided var etcdConfig *configapi.EtcdConfig if builtInEtcd { etcdConfig, err = args.BuildSerializeableEtcdConfig() if err != nil { return nil, err } } builtInKubernetes := len(args.KubeConnectionArgs.ClientConfigLoadingRules.ExplicitPath) == 0 var kubernetesMasterConfig *configapi.KubernetesMasterConfig if builtInKubernetes { kubernetesMasterConfig, err = args.BuildSerializeableKubeMasterConfig() if err != nil { return nil, err } } oauthConfig, err := args.BuildSerializeableOAuthConfig() if err != nil { return nil, err } kubeletClientInfo := admin.DefaultMasterKubeletClientCertInfo(args.ConfigDir.Value()) etcdClientInfo := admin.DefaultMasterEtcdClientCertInfo(args.ConfigDir.Value()) serviceServingCertSigner := admin.DefaultServiceSignerCAInfo(args.ConfigDir.Value()) dnsServingInfo := servingInfoForAddr(&dnsBindAddr) config := &configapi.MasterConfig{ ServingInfo: configapi.HTTPServingInfo{ ServingInfo: listenServingInfo, }, CORSAllowedOrigins: corsAllowedOrigins.List(), MasterPublicURL: masterPublicAddr.String(), KubernetesMasterConfig: kubernetesMasterConfig, EtcdConfig: etcdConfig, OAuthConfig: oauthConfig, PauseControllers: args.PauseControllers, AssetConfig: &configapi.AssetConfig{ ServingInfo: configapi.HTTPServingInfo{ ServingInfo: listenServingInfo, }, LogoutURL: "", MasterPublicURL: masterPublicAddr.String(), PublicURL: assetPublicAddr.String(), }, DNSConfig: &configapi.DNSConfig{ BindAddress: dnsServingInfo.BindAddress, BindNetwork: dnsServingInfo.BindNetwork, AllowRecursiveQueries: true, }, MasterClients: configapi.MasterClients{ OpenShiftLoopbackKubeConfig: admin.DefaultKubeConfigFilename(args.ConfigDir.Value(), bootstrappolicy.MasterUnqualifiedUsername), ExternalKubernetesKubeConfig: args.KubeConnectionArgs.ClientConfigLoadingRules.ExplicitPath, }, EtcdClientInfo: configapi.EtcdConnectionInfo{ URLs: []string{etcdAddress.String()}, }, KubeletClientInfo: configapi.KubeletConnectionInfo{ Port: ports.KubeletPort, }, PolicyConfig: configapi.PolicyConfig{ BootstrapPolicyFile: args.GetPolicyFile(), OpenShiftSharedResourcesNamespace: bootstrappolicy.DefaultOpenShiftSharedResourcesNamespace, }, ImageConfig: configapi.ImageConfig{ Format: args.ImageFormatArgs.ImageTemplate.Format, Latest: args.ImageFormatArgs.ImageTemplate.Latest, }, ProjectConfig: configapi.ProjectConfig{ DefaultNodeSelector: "", ProjectRequestMessage: "", ProjectRequestTemplate: "", // Allocator defaults on SecurityAllocator: &configapi.SecurityAllocator{}, }, NetworkConfig: configapi.MasterNetworkConfig{ NetworkPluginName: args.NetworkArgs.NetworkPluginName, ClusterNetworkCIDR: args.NetworkArgs.ClusterNetworkCIDR, HostSubnetLength: args.NetworkArgs.HostSubnetLength, ServiceNetworkCIDR: args.NetworkArgs.ServiceNetworkCIDR, }, VolumeConfig: configapi.MasterVolumeConfig{ DynamicProvisioningEnabled: true, }, ControllerConfig: configapi.ControllerConfig{ ServiceServingCert: configapi.ServiceServingCert{ Signer: &serviceServingCertSigner, }, }, } if args.ListenArg.UseTLS() { config.ServingInfo.ServerCert = admin.DefaultMasterServingCertInfo(args.ConfigDir.Value()) config.ServingInfo.ClientCA = admin.DefaultAPIClientCAFile(args.ConfigDir.Value()) config.AssetConfig.ServingInfo.ServerCert = admin.DefaultAssetServingCertInfo(args.ConfigDir.Value()) if oauthConfig != nil { s := admin.DefaultCABundleFile(args.ConfigDir.Value()) oauthConfig.MasterCA = &s } // Only set up ca/cert info for kubelet connections if we're self-hosting Kubernetes if builtInKubernetes { config.KubeletClientInfo.CA = admin.DefaultRootCAFile(args.ConfigDir.Value()) config.KubeletClientInfo.ClientCert = kubeletClientInfo.CertLocation config.ServiceAccountConfig.MasterCA = admin.DefaultCABundleFile(args.ConfigDir.Value()) } // Only set up ca/cert info for etcd connections if we're self-hosting etcd if builtInEtcd { config.EtcdClientInfo.CA = admin.DefaultRootCAFile(args.ConfigDir.Value()) config.EtcdClientInfo.ClientCert = etcdClientInfo.CertLocation } } if builtInKubernetes { // When we start Kubernetes, we're responsible for generating all the managed service accounts config.ServiceAccountConfig.ManagedNames = []string{ bootstrappolicy.DefaultServiceAccountName, bootstrappolicy.BuilderServiceAccountName, bootstrappolicy.DeployerServiceAccountName, } // We also need the private key file to give to the token generator config.ServiceAccountConfig.PrivateKeyFile = admin.DefaultServiceAccountPrivateKeyFile(args.ConfigDir.Value()) // We also need the public key file to give to the authenticator config.ServiceAccountConfig.PublicKeyFiles = []string{ admin.DefaultServiceAccountPublicKeyFile(args.ConfigDir.Value()), } } else { // When running against an external Kubernetes, we're only responsible for the builder and deployer accounts. // We don't have the private key, but we need to get the public key to authenticate signed tokens. // TODO: JTL: take arg for public key(s)? config.ServiceAccountConfig.ManagedNames = []string{ bootstrappolicy.BuilderServiceAccountName, bootstrappolicy.DeployerServiceAccountName, } config.ServiceAccountConfig.PublicKeyFiles = []string{} } // embed a default policy for generated config defaultImagePolicy, err := bootstrap.Asset("pkg/image/admission/imagepolicy/api/v1/default-policy.yaml") if err != nil { return nil, fmt.Errorf("unable to find default image admission policy: %v", err) } // TODO: this should not be necessary, runtime.Unknown#MarshalJSON should handle YAML content type correctly defaultImagePolicy, err = yaml.ToJSON(defaultImagePolicy) if err != nil { return nil, err } if config.AdmissionConfig.PluginConfig == nil { config.AdmissionConfig.PluginConfig = make(map[string]configapi.AdmissionPluginConfig) } config.AdmissionConfig.PluginConfig[imagepolicyapi.PluginName] = configapi.AdmissionPluginConfig{ Configuration: &runtime.Unknown{Raw: defaultImagePolicy}, } internal, err := applyDefaults(config, configapiv1.SchemeGroupVersion) if err != nil { return nil, err } config = internal.(*configapi.MasterConfig) // When creating a new config, use Protobuf configapi.SetProtobufClientDefaults(config.MasterClients.OpenShiftLoopbackClientConnectionOverrides) configapi.SetProtobufClientDefaults(config.MasterClients.ExternalKubernetesClientConnectionOverrides) return config, nil }