Skip to content

Commit

Permalink
Merge rancher/shepherd branch 'release/v2.9' commit:47c902ebe45243a00…
Browse files Browse the repository at this point in the history
…f0ac7357eb167921c61424e into cnrancher release/v2.9-ent
  • Loading branch information
jianghang8421 committed Oct 25, 2024
2 parents abfa0a5 + 47c902e commit 5448651
Show file tree
Hide file tree
Showing 11 changed files with 406 additions and 189 deletions.
8 changes: 8 additions & 0 deletions clients/corral/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ type Packages struct {
HasCustomRepo string `json:"hasCustomRepo" yaml:"hasCustomRepo"`
}

// Args is a struct that contains arguments to a corral create command, and any updates to the config
// that should be applied before creating the corral
type Args struct {
Name string
PackageName string
Updates map[string]string
}

// PackagesConfig is a function that reads in the corral package object from the config file
func PackagesConfig() *Packages {
var corralPackages Packages
Expand Down
142 changes: 135 additions & 7 deletions clients/corral/corral.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"regexp"
"strings"
"sync"
"time"

"github.com/pkg/errors"
"github.com/rancher/shepherd/pkg/session"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/wait"
)

const (
Expand Down Expand Up @@ -70,29 +74,153 @@ func SetCustomRepo(repo string) error {

// CreateCorral creates a corral taking the corral name, the package path, and a debug set so if someone wants to view the
// corral create log
func CreateCorral(ts *session.Session, corralName, packageName string, debug bool, cleanup bool) ([]byte, error) {
func CreateCorral(ts *session.Session, corralName, packageName string, debug, cleanup bool) ([]byte, error) {
command, err := startCorral(ts, corralName, packageName, debug, cleanup)
if err != nil {
return nil, err
}

return runAndWaitOnCommand(command)
}

func runAndWaitOnCommand(command *exec.Cmd) ([]byte, error) {
err := command.Wait()
var msg []byte
if command.Stdout != nil {
msg = command.Stdout.(*bytes.Buffer).Bytes()
}

if msg != nil {
logrus.Infof("Stdout: %s", string(msg))
}

return msg, errors.Wrap(err, "Debug: "+string(msg))
}

func startCorral(ts *session.Session, corralName, packageName string, debug, cleanup bool) (*exec.Cmd, error) {
ts.RegisterCleanupFunc(func() error {
return DeleteCorral(corralName)
})

args := []string{"create"}

if !cleanup {
args = append(args, skipCleanupFlag)
}
if debug {
args = append(args, debugFlag)
}

args = append(args, corralName, packageName)
logrus.Infof("Creating corral with the following parameters: %v", args)
// complicated, but running the command in a way that allows us to
// capture the output and error(s) and print it to the console
msg, err := exec.Command("corral", args...).CombinedOutput()
logrus.Infof("Corral create output: %s", string(msg))

cmdToRun := exec.Command("corral", args...)

// create a buffer for stdout/stderr so we can read from it later. commands initiate this to nil by default.
var b bytes.Buffer
cmdToRun.Stdout = &b
cmdToRun.Stderr = &b
err := cmdToRun.Start()
if err != nil {
return nil, err
}

// this ensures corral is completely initiated. Otherwise, race conditions occur.
err = waitForCorralConfig(corralName)
if err != nil {
return nil, err
}

return cmdToRun, err
}

func waitForCorralConfig(corralName string) error {
backoff := wait.Backoff{
Duration: 1 * time.Second,
Factor: 1.1,
Jitter: 0.1,
Steps: 10,
}

homeDir, err := os.UserHomeDir()
if err != nil {
return nil, errors.Wrap(err, "Unable to create corral: "+string(msg))
return err
}

corralOSPath := homeDir + "/.corral/corrals/" + corralName + "/corral.yaml"

return wait.ExponentialBackoff(backoff, func() (finished bool, err error) {
_, err = os.Stat(corralOSPath)
if err != nil {
return false, nil
}

fileContents, err := os.ReadFile(corralOSPath)
if err != nil {
return false, nil
}

if len(string(fileContents)) <= 0 {
return false, nil
}

return true, err
})
}

// CreateMultipleCorrals creates corrals taking the corral name, the package path, and a debug set so if someone wants to view the
// corral create log. Using this function implies calling WaitOnCorralWithCombinedOutput to get the output once finished.
func CreateMultipleCorrals(ts *session.Session, commands []Args, debug, cleanup bool) ([][]byte, error) {
var waitGroup sync.WaitGroup

var msgs [][]byte
var errStrings []string

for _, currentCommand := range commands {
// break out of any error that comes up before we run the waitGroup, to avoid running if we're already in an error state.
for key, value := range currentCommand.Updates {
logrus.Info(key, ": ", value)
err := UpdateCorralConfig(key, value)
if err != nil {
errStrings = append(errStrings, fmt.Sprint(err.Error(), "Unable to update corral: "+currentCommand.Name+" for "+key+": "+value))
break
}
}

cmdToRun, err := startCorral(ts, currentCommand.Name, currentCommand.PackageName, debug, cleanup)
if err != nil {
errStrings = append(errStrings, err.Error())
break
}

waitGroup.Add(1)

go func() {
defer waitGroup.Done()

msg, err := runAndWaitOnCommand(cmdToRun)
if err != nil {
errStrings = append(errStrings, err.Error())
}

msgs = append(msgs, msg)
}()

}

waitGroup.Wait()

var formattedError error
var longString string
if len(errStrings) > 0 {
for _, err := range errStrings {
longString += err
}
formattedError = fmt.Errorf(longString)
}

return msg, nil
logrus.Info("done with registration")
return msgs, formattedError
}

// DeleteCorral deletes a corral based on the corral name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ const (
)

type EKSClusterConfigSpec struct {
AmazonCredentialSecret string `json:"amazonCredentialSecret,omitempty" yaml:"amazonCredentialSecret,omitempty"`
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
EBSCSIDriver *bool `json:"ebsCSIDriver,omitempty" yaml:"ebsCSIDriver,omitempty"`
Imported bool `json:"imported,omitempty" yaml:"imported,omitempty"`
KmsKey *string `json:"kmsKey,omitempty" yaml:"kmsKey,omitempty"`
KubernetesVersion *string `json:"kubernetesVersion,omitempty" yaml:"kubernetesVersion,omitempty"`
LoggingTypes []string `json:"loggingTypes,omitempty" yaml:"loggingTypes,omitempty"`
NodeGroups []NodeGroup `json:"nodeGroups,omitempty" yaml:"nodeGroups,omitempty"`
PrivateAccess *bool `json:"privateAccess,omitempty" yaml:"privateAccess,omitempty"`
PublicAccess *bool `json:"publicAccess,omitempty" yaml:"publicAccess,omitempty"`
PublicAccessSources []string `json:"publicAccessSources,omitempty" yaml:"publicAccessSources,omitempty"`
Region string `json:"region,omitempty" yaml:"region,omitempty"`
SecretsEncryption *bool `json:"secretsEncryption,omitempty" yaml:"secretsEncryption,omitempty"`
SecurityGroups []string `json:"securityGroups,omitempty" yaml:"securityGroups,omitempty"`
ServiceRole *string `json:"serviceRole,omitempty" yaml:"serviceRole,omitempty"`
Subnets []string `json:"subnets,omitempty" yaml:"subnets,omitempty"`
Tags map[string]string `json:"tags,omitempty" yaml:"tags,omitempty"`
AmazonCredentialSecret string `json:"amazonCredentialSecret,omitempty" yaml:"amazonCredentialSecret,omitempty"`
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
EBSCSIDriver *bool `json:"ebsCSIDriver,omitempty" yaml:"ebsCSIDriver,omitempty"`
Imported bool `json:"imported,omitempty" yaml:"imported,omitempty"`
KmsKey *string `json:"kmsKey,omitempty" yaml:"kmsKey,omitempty"`
KubernetesVersion *string `json:"kubernetesVersion,omitempty" yaml:"kubernetesVersion,omitempty"`
LoggingTypes *[]string `json:"loggingTypes,omitempty" yaml:"loggingTypes,omitempty"`
NodeGroups []NodeGroup `json:"nodeGroups,omitempty" yaml:"nodeGroups,omitempty"`
PrivateAccess *bool `json:"privateAccess,omitempty" yaml:"privateAccess,omitempty"`
PublicAccess *bool `json:"publicAccess,omitempty" yaml:"publicAccess,omitempty"`
PublicAccessSources *[]string `json:"publicAccessSources,omitempty" yaml:"publicAccessSources,omitempty"`
Region string `json:"region,omitempty" yaml:"region,omitempty"`
SecretsEncryption *bool `json:"secretsEncryption,omitempty" yaml:"secretsEncryption,omitempty"`
SecurityGroups *[]string `json:"securityGroups,omitempty" yaml:"securityGroups,omitempty"`
ServiceRole *string `json:"serviceRole,omitempty" yaml:"serviceRole,omitempty"`
Subnets *[]string `json:"subnets,omitempty" yaml:"subnets,omitempty"`
Tags *map[string]string `json:"tags,omitempty" yaml:"tags,omitempty"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ type GKEClusterConfigSpec struct {
IPAllocationPolicy *GKEIPAllocationPolicy `json:"ipAllocationPolicy,omitempty" yaml:"ipAllocationPolicy,omitempty"`
Imported bool `json:"imported,omitempty" yaml:"imported,omitempty"`
KubernetesVersion *string `json:"kubernetesVersion,omitempty" yaml:"kubernetesVersion,omitempty"`
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
Locations []string `json:"locations,omitempty" yaml:"locations,omitempty"`
Labels *map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
Locations *[]string `json:"locations,omitempty" yaml:"locations,omitempty"`
LoggingService *string `json:"loggingService,omitempty" yaml:"loggingService,omitempty"`
MaintenanceWindow *string `json:"maintenanceWindow,omitempty" yaml:"maintenanceWindow,omitempty"`
MasterAuthorizedNetworksConfig *GKEMasterAuthorizedNetworksConfig `json:"masterAuthorizedNetworks,omitempty" yaml:"masterAuthorizedNetworks,omitempty"`
Expand Down
40 changes: 20 additions & 20 deletions clients/rancher/generated/management/v3/zz_generated_node_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@ const (
)

type NodeGroup struct {
Arm *bool `json:"arm,omitempty" yaml:"arm,omitempty"`
DesiredSize *int64 `json:"desiredSize,omitempty" yaml:"desiredSize,omitempty"`
DiskSize *int64 `json:"diskSize,omitempty" yaml:"diskSize,omitempty"`
Ec2SshKey *string `json:"ec2SshKey,omitempty" yaml:"ec2SshKey,omitempty"`
Gpu *bool `json:"gpu,omitempty" yaml:"gpu,omitempty"`
ImageID *string `json:"imageId,omitempty" yaml:"imageId,omitempty"`
InstanceType *string `json:"instanceType,omitempty" yaml:"instanceType,omitempty"`
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
LaunchTemplate *LaunchTemplate `json:"launchTemplate,omitempty" yaml:"launchTemplate,omitempty"`
MaxSize *int64 `json:"maxSize,omitempty" yaml:"maxSize,omitempty"`
MinSize *int64 `json:"minSize,omitempty" yaml:"minSize,omitempty"`
NodeRole *string `json:"nodeRole,omitempty" yaml:"nodeRole,omitempty"`
NodegroupName *string `json:"nodegroupName,omitempty" yaml:"nodegroupName,omitempty"`
RequestSpotInstances *bool `json:"requestSpotInstances,omitempty" yaml:"requestSpotInstances,omitempty"`
ResourceTags map[string]string `json:"resourceTags,omitempty" yaml:"resourceTags,omitempty"`
SpotInstanceTypes []string `json:"spotInstanceTypes,omitempty" yaml:"spotInstanceTypes,omitempty"`
Subnets []string `json:"subnets,omitempty" yaml:"subnets,omitempty"`
Tags map[string]string `json:"tags,omitempty" yaml:"tags,omitempty"`
UserData *string `json:"userData,omitempty" yaml:"userData,omitempty"`
Version *string `json:"version,omitempty" yaml:"version,omitempty"`
Arm *bool `json:"arm,omitempty" yaml:"arm,omitempty"`
DesiredSize *int64 `json:"desiredSize,omitempty" yaml:"desiredSize,omitempty"`
DiskSize *int64 `json:"diskSize,omitempty" yaml:"diskSize,omitempty"`
Ec2SshKey *string `json:"ec2SshKey,omitempty" yaml:"ec2SshKey,omitempty"`
Gpu *bool `json:"gpu,omitempty" yaml:"gpu,omitempty"`
ImageID *string `json:"imageId,omitempty" yaml:"imageId,omitempty"`
InstanceType *string `json:"instanceType,omitempty" yaml:"instanceType,omitempty"`
Labels *map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
LaunchTemplate *LaunchTemplate `json:"launchTemplate,omitempty" yaml:"launchTemplate,omitempty"`
MaxSize *int64 `json:"maxSize,omitempty" yaml:"maxSize,omitempty"`
MinSize *int64 `json:"minSize,omitempty" yaml:"minSize,omitempty"`
NodeRole *string `json:"nodeRole,omitempty" yaml:"nodeRole,omitempty"`
NodegroupName *string `json:"nodegroupName,omitempty" yaml:"nodegroupName,omitempty"`
RequestSpotInstances *bool `json:"requestSpotInstances,omitempty" yaml:"requestSpotInstances,omitempty"`
ResourceTags *map[string]string `json:"resourceTags,omitempty" yaml:"resourceTags,omitempty"`
SpotInstanceTypes *[]string `json:"spotInstanceTypes,omitempty" yaml:"spotInstanceTypes,omitempty"`
Subnets *[]string `json:"subnets,omitempty" yaml:"subnets,omitempty"`
Tags *map[string]string `json:"tags,omitempty" yaml:"tags,omitempty"`
UserData *string `json:"userData,omitempty" yaml:"userData,omitempty"`
Version *string `json:"version,omitempty" yaml:"version,omitempty"`
}
Loading

0 comments on commit 5448651

Please sign in to comment.