func GenerateKubeConfig()

in cli/pkg/lifecycle/get_credentials.go [19:125]


func GenerateKubeConfig(fleetProjectId string) (*clientcmdapi.Config, error) {

	// Create a GKE Hub client.
	ctx := context.Background()
	hubClient, err := gkehub.NewService(ctx, option.WithEndpoint("https://gkehub.googleapis.com/v1"))
	if err != nil {
		log.Errorf("Failed to create GKE Hub client: %v", err)
		return nil, err
	}

	// Get a list of all GKE Fleet memberships in the project.
	parent := fmt.Sprintf("projects/%s/locations/-", fleetProjectId)
	req := hubClient.Projects.Locations.Memberships.List(parent)
	memberships, err := req.Do()
	if err != nil {
		log.Errorf("Failed to list memberships: %v", err)
		return nil, err
	}

	// Get the project number for the fleet project needed later in the generate credentials request
	projectNumber, err := getProjectNumber(fleetProjectId)
	if err != nil {
		log.Errorf("Failed to get project number: %v", err)
		return nil, err
	}

	// Create a new kubeconfig.
	config := clientcmdapi.NewConfig()

	// Keep track of failed memberships
	failedMemberships := []string{}

	// Generate credentials for each membership
	for _, membership := range memberships.Resources {
		membershipName := membership.Name
		membershipLocation := extractLocation(membershipName)

		// Create a Gateway Control Client.
		endpoint := "connectgateway.googleapis.com"
		if isRegionalMembership(membershipName) {
			endpoint = membershipLocation + "-" + endpoint // Use regional endpoint
		} else {
			endpoint = "connectgateway.googleapis.com" // Use global endpoint
		}

		// Create a Gateway Control Client with the correct endpoint
		ctx2 := context.Background()
		gcc, err := gateway.NewGatewayControlRESTClient(ctx2, option.WithEndpoint(endpoint))
		if err != nil {
			log.Errorf("Failed to create gateway control client for %s: %v", membershipName, err)
			failedMemberships = append(failedMemberships, membershipName)
			continue // Skip to the next membership
		}
		defer gcc.Close()

		log.Infof("Generating credentials for membership: %s", membershipName)

		// Construct the correct membership name with project number
		membershipName = fmt.Sprintf("projects/%s/locations/%s/memberships/%s",
			projectNumber, membershipLocation, extractMembershipID(membership.Name))

		// Generate credentials for each membership
		req := &gatewaypb.GenerateCredentialsRequest{
			Name: membershipName,
		}
		resp, err := gcc.GenerateCredentials(ctx, req)
		if err != nil {
			log.Errorf("Failed to generate credentials for membership %s: Endpoint: %s, Error: %v", membershipName, endpoint, err)
			failedMemberships = append(failedMemberships, membershipName)
			continue // Skip to the next membership
		}

		// Get the kubeconfig from the response
		kc := resp.GetKubeconfig()

		// Parse the kubeconfig
		parsedConfig, err := clientcmd.Load(kc)
		if err != nil {
			log.Errorf("Failed to load kubeconfig for membership %s: %v", membershipName, err)
			return nil, err
		}

		// Merge the parsed config into the main config
		for key, context := range parsedConfig.Contexts {
			config.Contexts[key] = context
		}
		for key, cluster := range parsedConfig.Clusters {
			config.Clusters[key] = cluster
		}
		for key, authInfo := range parsedConfig.AuthInfos {
			config.AuthInfos[key] = authInfo
		}
	}

	// Write the kubeconfig to a file.
	err = clientcmd.WriteToFile(*config, "kubeconfig")
	if err != nil {
		log.Errorf("Failed to write kubeconfig: %v", err)
		return nil, err
	}
	if len(failedMemberships) > 0 {
		log.Warnf("Failed to generate credentials for the following memberships: %v", failedMemberships)
	} else {
		log.Info("Kubeconfig generated successfully.")
	}
	return config, err
}