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