github.com/openshift/installer@v1.4.17/pkg/clusterapi/localcontrolplane.go (about) 1 package clusterapi 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "time" 9 10 capnv1 "github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1" 11 "github.com/sirupsen/logrus" 12 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 13 "k8s.io/client-go/kubernetes/scheme" 14 "k8s.io/client-go/rest" 15 "k8s.io/client-go/tools/clientcmd" 16 "k8s.io/client-go/tools/clientcmd/api" 17 "k8s.io/klog/v2" 18 capav1beta1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta1" 19 capav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" 20 capzv1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 21 capgv1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1" 22 capiv1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2" 23 capov1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" 24 capvv1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" 25 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 26 "sigs.k8s.io/controller-runtime/pkg/client" 27 "sigs.k8s.io/controller-runtime/pkg/envtest" 28 "sigs.k8s.io/controller-runtime/pkg/log" 29 30 "github.com/openshift/installer/cmd/openshift-install/command" 31 ) 32 33 var ( 34 // Scheme is the scheme used by the local control plane. 35 Scheme = scheme.Scheme 36 ) 37 38 func init() { 39 utilruntime.Must(clusterv1.AddToScheme(Scheme)) 40 utilruntime.Must(capav1beta1.AddToScheme(Scheme)) 41 utilruntime.Must(capav1.AddToScheme(Scheme)) 42 utilruntime.Must(capzv1.AddToScheme(Scheme)) 43 utilruntime.Must(capgv1.AddToScheme(Scheme)) 44 utilruntime.Must(capvv1.AddToScheme(Scheme)) 45 utilruntime.Must(capov1.AddToScheme(Scheme)) 46 utilruntime.Must(capiv1.AddToScheme(Scheme)) 47 utilruntime.Must(capnv1.AddToScheme(Scheme)) 48 } 49 50 // localControlPlane creates a local capi control plane 51 // to use as a management cluster. 52 type localControlPlane struct { 53 Env *envtest.Environment 54 Client client.Client 55 Cfg *rest.Config 56 BinDir string 57 EtcdDataDir string 58 KubeconfigPath string 59 EtcdLog *os.File 60 APIServerLog *os.File 61 } 62 63 // Run launches the local control plane. 64 func (c *localControlPlane) Run(ctx context.Context) error { 65 // Create a temporary directory to unpack the cluster-api binaries. 66 c.BinDir = filepath.Join(command.RootOpts.Dir, "cluster-api") 67 if err := UnpackClusterAPIBinary(c.BinDir); err != nil { 68 return fmt.Errorf("failed to unpack cluster-api binary: %w", err) 69 } 70 if err := UnpackEnvtestBinaries(c.BinDir); err != nil { 71 return fmt.Errorf("failed to unpack envtest binaries: %w", err) 72 } 73 c.EtcdDataDir = filepath.Join(command.RootOpts.Dir, ArtifactsDir, "etcd") 74 75 // Write etcd & kube-apiserver output to log files. 76 var err error 77 if err := os.MkdirAll(filepath.Join(command.RootOpts.Dir, ArtifactsDir), 0750); err != nil { 78 return fmt.Errorf("error creating artifacts dir: %w", err) 79 } 80 if c.EtcdLog, err = os.Create(filepath.Join(command.RootOpts.Dir, ArtifactsDir, "etcd.log")); err != nil { 81 return fmt.Errorf("failed to create etcd log file: %w", err) 82 } 83 if c.APIServerLog, err = os.Create(filepath.Join(command.RootOpts.Dir, ArtifactsDir, "kube-apiserver.log")); err != nil { 84 return fmt.Errorf("failed to create kube-apiserver log file: %w", err) 85 } 86 87 log.SetLogger(klog.NewKlogr()) 88 logrus.Info("Started local control plane with envtest") 89 c.Env = &envtest.Environment{ 90 Scheme: Scheme, 91 AttachControlPlaneOutput: true, 92 BinaryAssetsDirectory: c.BinDir, 93 ControlPlaneStartTimeout: 10 * time.Second, 94 ControlPlaneStopTimeout: 10 * time.Second, 95 ControlPlane: envtest.ControlPlane{ 96 Etcd: &envtest.Etcd{ 97 DataDir: c.EtcdDataDir, 98 Out: c.EtcdLog, 99 Err: c.EtcdLog, 100 }, 101 APIServer: &envtest.APIServer{ 102 Out: c.APIServerLog, 103 Err: c.APIServerLog, 104 }, 105 }, 106 } 107 c.Cfg, err = c.Env.Start() 108 if err != nil { 109 return err 110 } 111 112 artifactsDirPath := filepath.Join(command.RootOpts.Dir, ArtifactsDir) 113 err = os.MkdirAll(artifactsDirPath, 0750) 114 if err != nil { 115 return fmt.Errorf("error creating cluster-api artifacts directory: %w", err) 116 } 117 118 kc := fromEnvTestConfig(c.Cfg) 119 { 120 kf, err := os.Create(filepath.Join(artifactsDirPath, "envtest.kubeconfig")) 121 if err != nil { 122 return err 123 } 124 if _, err := kf.Write(kc); err != nil { 125 return err 126 } 127 if err := kf.Close(); err != nil { 128 return err 129 } 130 c.KubeconfigPath, err = filepath.Abs(kf.Name()) 131 if err != nil { 132 return err 133 } 134 } 135 136 // Create a new client to interact with the cluster. 137 cl, err := client.New(c.Cfg, client.Options{ 138 Scheme: c.Env.Scheme, 139 }) 140 if err != nil { 141 return err 142 } 143 c.Client = cl 144 145 logrus.Infof("Stored kubeconfig for envtest in: %v", c.KubeconfigPath) 146 return nil 147 } 148 149 func (c *localControlPlane) Stop() error { 150 return c.Env.Stop() 151 } 152 153 // fromEnvTestConfig returns a new Kubeconfig in byte form when running in envtest. 154 func fromEnvTestConfig(cfg *rest.Config) []byte { 155 clusterName := "envtest" 156 contextName := fmt.Sprintf("%s@%s", cfg.Username, clusterName) 157 c := api.Config{ 158 Clusters: map[string]*api.Cluster{ 159 clusterName: { 160 Server: cfg.Host, 161 CertificateAuthorityData: cfg.CAData, 162 }, 163 }, 164 Contexts: map[string]*api.Context{ 165 contextName: { 166 Cluster: clusterName, 167 AuthInfo: cfg.Username, 168 }, 169 }, 170 AuthInfos: map[string]*api.AuthInfo{ 171 cfg.Username: { 172 ClientKeyData: cfg.KeyData, 173 ClientCertificateData: cfg.CertData, 174 }, 175 }, 176 CurrentContext: contextName, 177 } 178 data, err := clientcmd.Write(c) 179 if err != nil { 180 logrus.Fatalf("failed to write kubeconfig: %v", err) 181 } 182 return data 183 }