github.com/IBM-Cloud/bluemix-go@v0.0.0-20240314082800-4e02a69b84b2/api/container/containerv2/clusters.go (about)

     1  package containerv2
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/url"
     8  	"os"
     9  	"path"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"gopkg.in/yaml.v2"
    14  
    15  	"github.com/IBM-Cloud/bluemix-go/api/container/containerv1"
    16  	"github.com/IBM-Cloud/bluemix-go/client"
    17  	"github.com/IBM-Cloud/bluemix-go/helpers"
    18  	"github.com/IBM-Cloud/bluemix-go/trace"
    19  )
    20  
    21  // ClusterCreateRequest ...
    22  type ClusterCreateRequest struct {
    23  	DisablePublicServiceEndpoint bool             `json:"disablePublicServiceEndpoint"`
    24  	KubeVersion                  string           `json:"kubeVersion" description:"kubeversion of cluster"`
    25  	Billing                      string           `json:"billing,omitempty"`
    26  	PodSubnet                    string           `json:"podSubnet"`
    27  	Provider                     string           `json:"provider"`
    28  	ServiceSubnet                string           `json:"serviceSubnet"`
    29  	Name                         string           `json:"name" binding:"required" description:"The cluster's name"`
    30  	DefaultWorkerPoolEntitlement string           `json:"defaultWorkerPoolEntitlement"`
    31  	CosInstanceCRN               string           `json:"cosInstanceCRN"`
    32  	WorkerPools                  WorkerPoolConfig `json:"workerPool"`
    33  	SecurityGroupIDs             []string         `json:"securityGroupIDs,omitempty"`
    34  }
    35  
    36  type WorkerPoolConfig struct {
    37  	HostPoolID string `json:"hostPoolID,omitempty"`
    38  	CommonWorkerPoolConfig
    39  }
    40  
    41  type WorkerVolumeEncryption struct {
    42  	KmsInstanceID     string `json:"kmsInstanceID,omitempty"`
    43  	WorkerVolumeCRKID string `json:"workerVolumeCRKID,omitempty"`
    44  	KMSAccountID      string `json:"kmsAccountID,omitempty"`
    45  }
    46  
    47  // type Label struct {
    48  // 	AdditionalProp1 string `json:"additionalProp1,omitempty"`
    49  // 	AdditionalProp2 string `json:"additionalProp2,omitempty"`
    50  // 	AdditionalProp3 string `json:"additionalProp3,omitempty"`
    51  // }
    52  
    53  type Zone struct {
    54  	ID       string `json:"id,omitempty" description:"The id"`
    55  	SubnetID string `json:"subnetID,omitempty"`
    56  }
    57  
    58  // ClusterInfo ...
    59  type ClusterInfo struct {
    60  	CreatedDate                   string        `json:"createdDate"`
    61  	DataCenter                    string        `json:"dataCenter"`
    62  	ID                            string        `json:"id"`
    63  	Location                      string        `json:"location"`
    64  	Entitlement                   string        `json:"entitlement"`
    65  	MasterKubeVersion             string        `json:"masterKubeVersion"`
    66  	Name                          string        `json:"name"`
    67  	Region                        string        `json:"region"`
    68  	ResourceGroupID               string        `json:"resourceGroup"`
    69  	State                         string        `json:"state"`
    70  	IsPaid                        bool          `json:"isPaid"`
    71  	Addons                        []Addon       `json:"addons"`
    72  	OwnerEmail                    string        `json:"ownerEmail"`
    73  	Type                          string        `json:"type"`
    74  	TargetVersion                 string        `json:"targetVersion"`
    75  	ServiceSubnet                 string        `json:"serviceSubnet"`
    76  	ResourceGroupName             string        `json:"resourceGroupName"`
    77  	Provider                      string        `json:"provider"`
    78  	PodSubnet                     string        `json:"podSubnet"`
    79  	MultiAzCapable                bool          `json:"multiAzCapable"`
    80  	APIUser                       string        `json:"apiUser"`
    81  	ServerURL                     string        `json:"serverURL"`
    82  	MasterURL                     string        `json:"masterURL"`
    83  	MasterStatus                  string        `json:"masterStatus"`
    84  	DisableAutoUpdate             bool          `json:"disableAutoUpdate"`
    85  	WorkerZones                   []string      `json:"workerZones"`
    86  	Vpcs                          []string      `json:"vpcs"`
    87  	CRN                           string        `json:"crn"`
    88  	VersionEOS                    string        `json:"versionEOS"`
    89  	ServiceEndpoints              Endpoints     `json:"serviceEndpoints"`
    90  	PrivateServiceEndpointEnabled bool          `json:"privateServiceEndpointEnabled"`
    91  	PrivateServiceEndpointURL     string        `json:"privateServiceEndpointURL"`
    92  	PublicServiceEndpointEnabled  bool          `json:"publicServiceEndpointEnabled"`
    93  	PublicServiceEndpointURL      string        `json:"publicServiceEndpointURL"`
    94  	Lifecycle                     LifeCycleInfo `json:"lifecycle"`
    95  	WorkerCount                   int           `json:"workerCount"`
    96  	Ingress                       IngresInfo    `json:"ingress"`
    97  	Features                      Feat          `json:"features"`
    98  	ImageSecurityEnabled          bool          `json:"imageSecurityEnabled"`
    99  	VirtualPrivateEndpointURL     string        `json:"virtualPrivateEndpointURL"`
   100  }
   101  type Feat struct {
   102  	KeyProtectEnabled bool `json:"keyProtectEnabled"`
   103  	PullSecretApplied bool `json:"pullSecretApplied"`
   104  }
   105  type IngresInfo struct {
   106  	HostName   string `json:"hostname"`
   107  	SecretName string `json:"secretName"`
   108  }
   109  type LifeCycleInfo struct {
   110  	ModifiedDate             string `json:"modifiedDate"`
   111  	MasterStatus             string `json:"masterStatus"`
   112  	MasterStatusModifiedDate string `json:"masterStatusModifiedDate"`
   113  	MasterHealth             string `json:"masterHealth"`
   114  	MasterState              string `json:"masterState"`
   115  }
   116  
   117  // ClusterTargetHeader ...
   118  type ClusterTargetHeader struct {
   119  	AccountID     string
   120  	ResourceGroup string
   121  	Provider      string // supported providers e.g vpc-classic , vpc-gen2, satellite
   122  }
   123  type Endpoints struct {
   124  	PrivateServiceEndpointEnabled bool   `json:"privateServiceEndpointEnabled"`
   125  	PrivateServiceEndpointURL     string `json:"privateServiceEndpointURL"`
   126  	PublicServiceEndpointEnabled  bool   `json:"publicServiceEndpointEnabled"`
   127  	PublicServiceEndpointURL      string `json:"publicServiceEndpointURL"`
   128  }
   129  
   130  type Addon struct {
   131  	Name    string `json:"name"`
   132  	Version string `json:"version"`
   133  }
   134  
   135  // ClusterCreateResponse ...
   136  type ClusterCreateResponse struct {
   137  	ID string `json:"clusterID"`
   138  }
   139  
   140  // Clusters interface
   141  type Clusters interface {
   142  	Create(params ClusterCreateRequest, target ClusterTargetHeader) (ClusterCreateResponse, error)
   143  	List(target ClusterTargetHeader) ([]ClusterInfo, error)
   144  	Delete(name string, target ClusterTargetHeader, deleteDependencies ...bool) error
   145  	GetCluster(name string, target ClusterTargetHeader) (*ClusterInfo, error)
   146  	GetClusterConfigDetail(name, homeDir string, admin bool, target ClusterTargetHeader, endpointType string) (containerv1.ClusterKeyInfo, error)
   147  	StoreConfigDetail(name, baseDir string, admin bool, createCalicoConfig bool, target ClusterTargetHeader, endpointType string) (string, containerv1.ClusterKeyInfo, error)
   148  	EnableImageSecurityEnforcement(name string, target ClusterTargetHeader) error
   149  	DisableImageSecurityEnforcement(name string, target ClusterTargetHeader) error
   150  	//TODO Add other opertaions
   151  }
   152  type clusters struct {
   153  	client     *client.Client
   154  	pathPrefix string
   155  }
   156  
   157  const (
   158  	accountIDHeader     = "X-Auth-Resource-Account"
   159  	resourceGroupHeader = "X-Auth-Resource-Group"
   160  )
   161  
   162  // ToMap ...
   163  func (c ClusterTargetHeader) ToMap() map[string]string {
   164  	m := make(map[string]string, 3)
   165  	m[accountIDHeader] = c.AccountID
   166  	m[resourceGroupHeader] = c.ResourceGroup
   167  	return m
   168  }
   169  
   170  func newClusterAPI(c *client.Client) Clusters {
   171  	return &clusters{
   172  		client: c,
   173  		//pathPrefix: "/v2/vpc/",
   174  	}
   175  }
   176  
   177  // List ...
   178  func (r *clusters) List(target ClusterTargetHeader) ([]ClusterInfo, error) {
   179  	clusters := []ClusterInfo{}
   180  	var err error
   181  	if target.Provider != "satellite" {
   182  		getClustersPath := "/v2/vpc/getClusters"
   183  		if len(target.Provider) > 0 {
   184  			getClustersPath = fmt.Sprintf(getClustersPath+"?provider=%s", url.QueryEscape(target.Provider))
   185  		}
   186  		_, err := r.client.Get(getClustersPath, &clusters, target.ToMap())
   187  		if err != nil {
   188  			return nil, err
   189  		}
   190  	}
   191  	if len(target.Provider) == 0 || target.Provider == "satellite" {
   192  		// get satellite clusters
   193  		satelliteClusters := []ClusterInfo{}
   194  		_, err = r.client.Get("/v2/satellite/getClusters", &satelliteClusters, target.ToMap())
   195  		if err != nil && target.Provider == "satellite" {
   196  			// return error only when provider is satellite. Else ignore error and return VPC clusters
   197  			trace.Logger.Println("Unable to get the satellite clusters ", err)
   198  			return nil, err
   199  		}
   200  		clusters = append(clusters, satelliteClusters...)
   201  	}
   202  	return clusters, nil
   203  }
   204  
   205  // Create ...
   206  func (r *clusters) Create(params ClusterCreateRequest, target ClusterTargetHeader) (ClusterCreateResponse, error) {
   207  	var cluster ClusterCreateResponse
   208  	_, err := r.client.Post("/v2/vpc/createCluster", params, &cluster, target.ToMap())
   209  	return cluster, err
   210  }
   211  
   212  // Delete ...
   213  func (r *clusters) Delete(name string, target ClusterTargetHeader, deleteDependencies ...bool) error {
   214  	var rawURL string
   215  	if len(deleteDependencies) != 0 {
   216  		rawURL = fmt.Sprintf("/v1/clusters/%s?deleteResources=%t", name, deleteDependencies[0])
   217  	} else {
   218  		rawURL = fmt.Sprintf("/v1/clusters/%s", name)
   219  	}
   220  	_, err := r.client.Delete(rawURL, target.ToMap())
   221  	return err
   222  }
   223  
   224  // GetClusterByIDorName
   225  func (r *clusters) GetCluster(name string, target ClusterTargetHeader) (*ClusterInfo, error) {
   226  	ClusterInfo := &ClusterInfo{}
   227  	rawURL := fmt.Sprintf("/v2/getCluster?cluster=%s&v1-compatible", name)
   228  	_, err := r.client.Get(rawURL, &ClusterInfo, target.ToMap())
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  
   233  	return ClusterInfo, err
   234  }
   235  func (r *ClusterInfo) IsStagingSatelliteCluster() bool {
   236  	return strings.Index(r.ServerURL, "stg") > 0 && r.Provider == "satellite"
   237  }
   238  
   239  // FindWithOutShowResourcesCompatible ...
   240  func (r *clusters) FindWithOutShowResourcesCompatible(name string, target ClusterTargetHeader) (ClusterInfo, error) {
   241  	rawURL := fmt.Sprintf("/v2/getCluster?v1-compatible&cluster=%s", name)
   242  	cluster := ClusterInfo{}
   243  	_, err := r.client.Get(rawURL, &cluster, target.ToMap())
   244  	if err != nil {
   245  		return cluster, err
   246  	}
   247  	// Handle VPC cluster.  ServerURL is blank for v2/vpc clusters
   248  	if cluster.ServerURL == "" {
   249  		cluster.ServerURL = cluster.MasterURL
   250  	}
   251  
   252  	// Workaround for ServiceEndpoints: armada-api returns different structure for different providers (classic vs VPC)
   253  	if !cluster.ServiceEndpoints.PrivateServiceEndpointEnabled && cluster.PrivateServiceEndpointEnabled {
   254  		cluster.ServiceEndpoints.PrivateServiceEndpointEnabled = cluster.PrivateServiceEndpointEnabled
   255  	}
   256  	if cluster.ServiceEndpoints.PrivateServiceEndpointURL == "" && cluster.PrivateServiceEndpointURL != "" {
   257  		cluster.ServiceEndpoints.PrivateServiceEndpointURL = cluster.PrivateServiceEndpointURL
   258  	}
   259  	if !cluster.ServiceEndpoints.PublicServiceEndpointEnabled && cluster.PublicServiceEndpointEnabled {
   260  		cluster.ServiceEndpoints.PublicServiceEndpointEnabled = cluster.PublicServiceEndpointEnabled
   261  	}
   262  	if cluster.ServiceEndpoints.PublicServiceEndpointURL == "" && cluster.PublicServiceEndpointURL != "" {
   263  		cluster.ServiceEndpoints.PublicServiceEndpointURL = cluster.PublicServiceEndpointURL
   264  	}
   265  
   266  	return cluster, err
   267  }
   268  
   269  // GetClusterConfigDetail ...
   270  func (r *clusters) GetClusterConfigDetail(name, dir string, admin bool, target ClusterTargetHeader, endpointType string) (containerv1.ClusterKeyInfo, error) {
   271  	clusterkey := containerv1.ClusterKeyInfo{}
   272  	// Block to add token for openshift clusters (This can be temporary until iks team handles openshift clusters)
   273  	clusterInfo, err := r.FindWithOutShowResourcesCompatible(name, target)
   274  	if err != nil {
   275  		// Assuming an error means that this is a vpc cluster, and we're returning existing kubeconfig
   276  		// When we add support for vpcs on openshift clusters, we may want revisit this
   277  		return clusterkey, err
   278  	}
   279  
   280  	if !helpers.FileExists(dir) {
   281  		return clusterkey, fmt.Errorf("Path: %q, to download the config doesn't exist", dir)
   282  	}
   283  	postBody := map[string]interface{}{
   284  		"cluster": name,
   285  		"format":  "zip",
   286  	}
   287  	rawURL := fmt.Sprintf("/v2/applyRBACAndGetKubeconfig")
   288  	if admin {
   289  		postBody["admin"] = true
   290  	}
   291  	if clusterInfo.Provider == "satellite" {
   292  		postBody["endpointType"] = "link"
   293  		postBody["admin"] = true
   294  	} else if endpointType != "" {
   295  		postBody["endpointType"] = endpointType
   296  	}
   297  	resultDir := containerv1.ComputeClusterConfigDir(dir, name, admin)
   298  	const kubeConfigName = "config.yml"
   299  	err = os.MkdirAll(resultDir, 0755)
   300  	if err != nil {
   301  		return clusterkey, fmt.Errorf("Error creating directory to download the cluster config")
   302  	}
   303  	downloadPath := filepath.Join(resultDir, "config.zip")
   304  	trace.Logger.Println("Will download the kubeconfig at", downloadPath)
   305  
   306  	var out *os.File
   307  	if out, err = os.Create(downloadPath); err != nil {
   308  		return clusterkey, err
   309  	}
   310  	defer out.Close()
   311  	defer helpers.RemoveFile(downloadPath)
   312  	_, err = r.client.Post(rawURL, postBody, out, target.ToMap())
   313  	if err != nil {
   314  		return clusterkey, err
   315  	}
   316  	trace.Logger.Println("Downloaded the kubeconfig at", downloadPath)
   317  	if err = helpers.Unzip(downloadPath, resultDir); err != nil {
   318  		return clusterkey, err
   319  	}
   320  	defer helpers.RemoveFilesWithPattern(resultDir, "[^(.yml)|(.pem)]$")
   321  	var kubeyml string
   322  	files, _ := ioutil.ReadDir(resultDir)
   323  
   324  	for _, f := range files {
   325  		if !strings.HasSuffix(f.Name(), ".zip") {
   326  			fileContent, _ := ioutil.ReadFile(resultDir + "/" + f.Name())
   327  			if f.Name() == "admin-key.pem" {
   328  				clusterkey.AdminKey = string(fileContent)
   329  			}
   330  			if f.Name() == "admin.pem" {
   331  				clusterkey.Admin = string(fileContent)
   332  			}
   333  			if strings.HasPrefix(f.Name(), "ca") && strings.HasSuffix(f.Name(), ".pem") {
   334  				clusterkey.ClusterCACertificate = string(fileContent)
   335  			}
   336  			old := filepath.Join(resultDir, f.Name())
   337  			new := filepath.Join(resultDir, f.Name())
   338  			if strings.HasSuffix(f.Name(), ".yaml") {
   339  				new = filepath.Join(path.Clean(resultDir), "/", path.Clean(kubeConfigName))
   340  				kubeyml = new
   341  			}
   342  			err := os.Rename(old, new)
   343  			if err != nil {
   344  				return clusterkey, fmt.Errorf("Couldn't rename: %q", err)
   345  			}
   346  		}
   347  	}
   348  	if resultDir == "" {
   349  		return clusterkey, errors.New("Unable to locate kube config in zip archive")
   350  	}
   351  
   352  	kubefile, _ := ioutil.ReadFile(kubeyml)
   353  	var yamlConfig containerv1.ConfigFile
   354  	err = yaml.Unmarshal(kubefile, &yamlConfig)
   355  	if err != nil {
   356  		fmt.Printf("Error parsing YAML file: %s\n", err)
   357  	}
   358  	if len(yamlConfig.Clusters) != 0 {
   359  		clusterkey.Host = yamlConfig.Clusters[0].Cluster.Server
   360  	}
   361  	if len(yamlConfig.Users) != 0 {
   362  		clusterkey.Token = yamlConfig.Users[0].User.AuthProvider.Config.IDToken
   363  	}
   364  
   365  	// Block to add token for openshift clusters (This can be temporary until iks team handles openshift clusters)
   366  	clusterInfo, err = r.FindWithOutShowResourcesCompatible(name, target)
   367  	if err != nil {
   368  		// Assuming an error means that this is a vpc cluster, and we're returning existing kubeconfig
   369  		// When we add support for vpcs on openshift clusters, we may want revisit this
   370  		clusterkey.FilePath, _ = filepath.Abs(kubeyml)
   371  		return clusterkey, err
   372  	}
   373  	if clusterInfo.Type == "openshift" && clusterInfo.Provider != "satellite" {
   374  		trace.Logger.Println("Debug: type is openshift trying login to get token")
   375  		var yamlConfig []byte
   376  		if yamlConfig, err = ioutil.ReadFile(kubeyml); err != nil {
   377  			return clusterkey, err
   378  		}
   379  		yamlConfig, clusterkey.Host, err = r.FetchOCTokenForKubeConfig(yamlConfig, &clusterInfo, clusterInfo.IsStagingSatelliteCluster(), endpointType)
   380  		if err != nil {
   381  			return clusterkey, err
   382  		}
   383  		err = ioutil.WriteFile(kubeyml, yamlConfig, 0644) // 0644 is irrelevant here, since file already exists.
   384  		if err != nil {
   385  			return clusterkey, err
   386  		}
   387  		openshiftyml, _ := ioutil.ReadFile(kubeyml)
   388  		var openshiftyaml containerv1.ConfigFileOpenshift
   389  		err = yaml.Unmarshal(openshiftyml, &openshiftyaml)
   390  		if err != nil {
   391  			fmt.Printf("Error parsing YAML file: %s\n", err)
   392  		}
   393  		openshiftusers := openshiftyaml.Users
   394  		for _, usr := range openshiftusers {
   395  			if strings.HasPrefix(usr.Name, "IAM") {
   396  				clusterkey.Token = usr.User.Token
   397  			}
   398  		}
   399  		clusterkey.ClusterCACertificate = ""
   400  
   401  	}
   402  	clusterkey.FilePath, _ = filepath.Abs(kubeyml)
   403  	return clusterkey, err
   404  }
   405  
   406  // StoreConfigDetail ...
   407  func (r *clusters) StoreConfigDetail(name, dir string, admin, createCalicoConfig bool, target ClusterTargetHeader, endpointType string) (string, containerv1.ClusterKeyInfo, error) {
   408  	clusterkey := containerv1.ClusterKeyInfo{}
   409  	clusterInfo, err := r.FindWithOutShowResourcesCompatible(name, target)
   410  	if err != nil {
   411  		return "", clusterkey, err
   412  	}
   413  	postBody := map[string]interface{}{
   414  		"cluster": name,
   415  		"format":  "zip",
   416  	}
   417  
   418  	var calicoConfig string
   419  	if !helpers.FileExists(dir) {
   420  		return "", clusterkey, fmt.Errorf("Path: %q, to download the config doesn't exist", dir)
   421  	}
   422  	rawURL := fmt.Sprintf("/v2/applyRBACAndGetKubeconfig")
   423  	if admin {
   424  		postBody["admin"] = true
   425  	}
   426  	if clusterInfo.Provider == "satellite" {
   427  		postBody["endpointType"] = "link"
   428  		postBody["admin"] = true
   429  	} else if endpointType != "" {
   430  		postBody["endpointType"] = endpointType
   431  	}
   432  	if createCalicoConfig {
   433  		postBody["network"] = true
   434  	}
   435  	resultDir := containerv1.ComputeClusterConfigDir(dir, name, admin)
   436  	err = os.MkdirAll(resultDir, 0755)
   437  	if err != nil {
   438  		return "", clusterkey, fmt.Errorf("Error creating directory to download the cluster config")
   439  	}
   440  	downloadPath := filepath.Join(resultDir, "config.zip")
   441  	trace.Logger.Println("Will download the kubeconfig at", downloadPath)
   442  
   443  	var out *os.File
   444  	if out, err = os.Create(downloadPath); err != nil {
   445  		return "", clusterkey, err
   446  	}
   447  	defer out.Close()
   448  	defer helpers.RemoveFile(downloadPath)
   449  	_, err = r.client.Post(rawURL, postBody, out, target.ToMap())
   450  	if err != nil {
   451  		return "", clusterkey, err
   452  	}
   453  	trace.Logger.Println("Downloaded the kubeconfig at", downloadPath)
   454  	if err = helpers.Unzip(downloadPath, resultDir); err != nil {
   455  		return "", clusterkey, err
   456  	}
   457  	trace.Logger.Println("Downloaded the kubec", resultDir)
   458  
   459  	unzipConfigPath := resultDir
   460  	trace.Logger.Println("Located unzipped directory: ", unzipConfigPath)
   461  	files, _ := ioutil.ReadDir(unzipConfigPath)
   462  	for _, f := range files {
   463  		if !strings.HasSuffix(f.Name(), ".zip") {
   464  			fileContent, _ := ioutil.ReadFile(unzipConfigPath + "/" + f.Name())
   465  			if f.Name() == "admin-key.pem" {
   466  				clusterkey.AdminKey = string(fileContent)
   467  			}
   468  			if f.Name() == "admin.pem" {
   469  				clusterkey.Admin = string(fileContent)
   470  			}
   471  			if strings.HasPrefix(f.Name(), "ca") && strings.HasSuffix(f.Name(), ".pem") {
   472  				clusterkey.ClusterCACertificate = string(fileContent)
   473  			}
   474  			old := filepath.Join(unzipConfigPath, f.Name())
   475  			new := filepath.Join(unzipConfigPath, f.Name())
   476  			err := os.Rename(old, new)
   477  			if err != nil {
   478  				return "", clusterkey, fmt.Errorf("Couldn't rename: %q", err)
   479  			}
   480  		}
   481  	}
   482  	baseDirFiles, err := ioutil.ReadDir(resultDir)
   483  	if err != nil {
   484  		return "", clusterkey, err
   485  	}
   486  
   487  	if createCalicoConfig {
   488  		// Proccess calico golang template file if it exists
   489  		calicoConfig, err = containerv1.GenerateCalicoConfig(resultDir)
   490  		if err != nil {
   491  			return "", clusterkey, err
   492  		}
   493  	}
   494  	var kubeconfigFileName string
   495  	for _, baseDirFile := range baseDirFiles {
   496  		if strings.Contains(baseDirFile.Name(), ".yaml") {
   497  			kubeconfigFileName = fmt.Sprintf("%s/%s", resultDir, baseDirFile.Name())
   498  			break
   499  		}
   500  	}
   501  	if kubeconfigFileName == "" {
   502  		return "", clusterkey, errors.New("Unable to locate kube config in zip archive")
   503  	}
   504  	kubefile, _ := ioutil.ReadFile(kubeconfigFileName)
   505  	var yamlConfig containerv1.ConfigFile
   506  	err = yaml.Unmarshal(kubefile, &yamlConfig)
   507  	if err != nil {
   508  		fmt.Printf("Error parsing YAML file: %s\n", err)
   509  	}
   510  	if len(yamlConfig.Clusters) != 0 {
   511  		clusterkey.Host = yamlConfig.Clusters[0].Cluster.Server
   512  	}
   513  	if len(yamlConfig.Users) != 0 {
   514  		clusterkey.Token = yamlConfig.Users[0].User.AuthProvider.Config.IDToken
   515  	}
   516  
   517  	// Block to add token for openshift clusters (This can be temporary until iks team handles openshift clusters)
   518  	clusterInfo, err = r.FindWithOutShowResourcesCompatible(name, target)
   519  	if err != nil {
   520  		// Assuming an error means that this is a vpc cluster, and we're returning existing kubeconfig
   521  		// When we add support for vpcs on openshift clusters, we may want revisit this
   522  		clusterkey.FilePath = kubeconfigFileName
   523  		return calicoConfig, clusterkey, nil
   524  	}
   525  
   526  	if clusterInfo.Type == "openshift" && clusterInfo.Provider != "satellite" {
   527  		trace.Logger.Println("Cluster Type is openshift trying login to get token")
   528  		var yamlConfig []byte
   529  		if yamlConfig, err = ioutil.ReadFile(kubeconfigFileName); err != nil {
   530  			return "", clusterkey, err
   531  		}
   532  		yamlConfig, clusterkey.Host, err = r.FetchOCTokenForKubeConfig(yamlConfig, &clusterInfo, clusterInfo.IsStagingSatelliteCluster(), endpointType)
   533  		if err != nil {
   534  			return "", clusterkey, err
   535  		}
   536  		err = ioutil.WriteFile(kubeconfigFileName, yamlConfig, 0644) // check about permissions and truncate
   537  		if err != nil {
   538  			return "", clusterkey, err
   539  		}
   540  		openshiftyml, _ := ioutil.ReadFile(kubeconfigFileName)
   541  		var openshiftyaml containerv1.ConfigFileOpenshift
   542  		err = yaml.Unmarshal(openshiftyml, &openshiftyaml)
   543  		if err != nil {
   544  			fmt.Printf("Error parsing YAML file: %s\n", err)
   545  		}
   546  		openshiftusers := openshiftyaml.Users
   547  		for _, usr := range openshiftusers {
   548  			if strings.HasPrefix(usr.Name, "IAM") {
   549  				clusterkey.Token = usr.User.Token
   550  			}
   551  		}
   552  		clusterkey.ClusterCACertificate = ""
   553  
   554  	}
   555  	clusterkey.FilePath = kubeconfigFileName
   556  	return calicoConfig, clusterkey, nil
   557  }
   558  
   559  func (r *clusters) EnableImageSecurityEnforcement(name string, target ClusterTargetHeader) error {
   560  	rawURL := "/v2/enableImageSecurity"
   561  	body := map[string]string{"cluster": name}
   562  	_, err := r.client.Post(rawURL, body, nil, target.ToMap())
   563  	return err
   564  }
   565  
   566  func (r *clusters) DisableImageSecurityEnforcement(name string, target ClusterTargetHeader) error {
   567  	rawURL := "/v2/disableImageSecurity"
   568  	body := map[string]string{"cluster": name}
   569  	_, err := r.client.Post(rawURL, body, nil, target.ToMap())
   570  	return err
   571  }