diff --git a/pkg/k8s/errors.go b/pkg/k8s/errors.go index 7f468d4..23bc950 100644 --- a/pkg/k8s/errors.go +++ b/pkg/k8s/errors.go @@ -81,6 +81,7 @@ var ( ErrGettingReplicaSet = &Error{Code: "ErrorGettingReplicaSet", Message: "failed to get ReplicaSet %s"} ErrCreatingReplicaSet = &Error{Code: "ErrorCreatingReplicaSet", Message: "failed to create ReplicaSet"} ErrDeletingReplicaSet = &Error{Code: "ErrorDeletingReplicaSet", Message: "failed to delete ReplicaSet %s"} + ErrCheckingReplicaSetExists = &Error{Code: "ErrorCheckingReplicaSetExists", Message: "failed to check if ReplicaSet %s exists"} ErrWaitingForReplicaSet = &Error{Code: "ErrorWaitingForReplicaSet", Message: "error waiting for ReplicaSet to delete"} ErrDeployingReplicaSet = &Error{Code: "ErrorDeployingReplicaSet", Message: "failed to deploy ReplicaSet"} ErrPreparingPodSpec = &Error{Code: "ErrorPreparingPodSpec", Message: "failed to prepare pod spec"} diff --git a/pkg/k8s/k8s_pod.go b/pkg/k8s/k8s_pod.go index 39af08c..d3c9f1e 100644 --- a/pkg/k8s/k8s_pod.go +++ b/pkg/k8s/k8s_pod.go @@ -370,12 +370,11 @@ func buildPodVolumes(name string, volumesAmount, filesAmount int) ([]v1.Volume, } // buildContainerVolumes generates a volume mount configuration for a container based on the given name and volumes. -func buildContainerVolumes(name string, volumes []*Volume, files []*File) ([]v1.VolumeMount, error) { +func buildContainerVolumes(name string, volumes []*Volume) ([]v1.VolumeMount, error) { var containerVolumes []v1.VolumeMount - var containerFiles []v1.VolumeMount // return empty slice if no volumes or files are specified - if len(volumes) == 0 && len(files) == 0 { + if len(volumes) == 0 { return containerVolumes, nil } @@ -390,6 +389,24 @@ func buildContainerVolumes(name string, volumes []*Volume, files []*File) ([]v1. } } + return containerVolumes, nil +} + +// buildInitContainerVolumes generates a volume mount configuration for an init container based on the given name and volumes. +func buildInitContainerVolumes(name string, volumes []*Volume, files []*File) ([]v1.VolumeMount, error) { + if len(volumes) == 0 && len(files) == 0 { + return []v1.VolumeMount{}, nil // return empty slice if no volumes are specified + } + + var containerFiles []v1.VolumeMount + + containerVolumes := []v1.VolumeMount{ + { + Name: name, + MountPath: knuuPath, // set the path to "/knuu" as per the requirements + }, + } + if len(files) != 0 { // iterate over the files map, add each file to the containerFiles n := 0 @@ -406,40 +423,29 @@ func buildContainerVolumes(name string, volumes []*Volume, files []*File) ([]v1. return append(containerVolumes, containerFiles...), nil } -// buildInitContainerVolumes generates a volume mount configuration for an init container based on the given name and volumes. -func buildInitContainerVolumes(name string, volumes []*Volume) ([]v1.VolumeMount, error) { - if len(volumes) == 0 { - return []v1.VolumeMount{}, nil // return empty slice if no volumes are specified - } - - containerVolumes := []v1.VolumeMount{ - { - Name: name, - MountPath: knuuPath, // set the path to "/knuu" as per the requirements - }, - } - - return containerVolumes, nil -} - // buildInitContainerCommand generates a command for an init container based on the given name and volumes. func buildInitContainerCommand(volumes []*Volume, files []*File) ([]string, error) { var commands = []string{"sh", "-c"} dirsProcessed := make(map[string]bool) - baseCmd := fmt.Sprintf("mkdir -p %s && ", knuuPath) - cmds := []string{baseCmd} + baseCmd := "set -xe && " + createKnuuPath := fmt.Sprintf("mkdir -p %s && ", knuuPath) + cmds := []string{baseCmd, createKnuuPath} + // for each file, get the directory and create the parent directory if it doesn't exist for _, file := range files { // get the directory of the file folder := filepath.Dir(file.Dest) if _, processed := dirsProcessed[folder]; !processed { knuuFolder := fmt.Sprintf("%s%s", knuuPath, folder) - parentDirCmd := fmt.Sprintf("mkdir -p %s && chmod -R 777 %s && ", knuuFolder, knuuFolder) + parentDirCmd := fmt.Sprintf("mkdir -p %s && ", knuuFolder) cmds = append(cmds, parentDirCmd) dirsProcessed[folder] = true } + copyFileToKnuu := fmt.Sprintf("cp %s %s && ", file.Dest, filepath.Join(knuuPath, file.Dest)) + cmds = append(cmds, copyFileToKnuu) } + // for each volume, copy the contents of the volume to the knuu volume for i, volume := range volumes { knuuVolumePath := fmt.Sprintf("%s%s", knuuPath, volume.Path) cmd := fmt.Sprintf("if [ -d %s ] && [ \"$(ls -A %s)\" ]; then cp -r %s/* %s && chown -R %d:%d %s", volume.Path, volume.Path, volume.Path, knuuVolumePath, volume.Owner, volume.Owner, knuuVolumePath) @@ -501,7 +507,7 @@ func prepareContainer(config ContainerConfig) (v1.Container, error) { podEnv := buildEnv(config.Env) // Build container volumes from the given map - containerVolumes, err := buildContainerVolumes(config.Name, config.Volumes, config.Files) + containerVolumes, err := buildContainerVolumes(config.Name, config.Volumes) if err != nil { return v1.Container{}, ErrBuildingContainerVolumes.Wrap(err) } @@ -532,7 +538,7 @@ func prepareInitContainers(config ContainerConfig, init bool) ([]v1.Container, e return nil, nil } - initContainerVolumes, err := buildInitContainerVolumes(config.Name, config.Volumes) + initContainerVolumes, err := buildInitContainerVolumes(config.Name, config.Volumes, config.Files) if err != nil { return nil, ErrBuildingInitContainerVolumes.Wrap(err) } diff --git a/pkg/k8s/k8s_replicaset.go b/pkg/k8s/k8s_replicaset.go index f52c230..76373d6 100644 --- a/pkg/k8s/k8s_replicaset.go +++ b/pkg/k8s/k8s_replicaset.go @@ -55,12 +55,13 @@ func (c *Client) ReplaceReplicaSetWithGracePeriod(ctx context.Context, ReplicaSe case <-ctx.Done(): return nil, ctx.Err() case <-ticker.C: - _, err := c.getReplicaSet(ctx, ReplicaSetConfig.Name) - if errors.IsNotFound(err) { + exists, err := c.ReplicaSetExists(ctx, ReplicaSetConfig.Name) + if err != nil { + return nil, ErrCheckingReplicaSetExists.WithParams(ReplicaSetConfig.Name).Wrap(err) + } + if !exists { // ReplicaSet has been deleted deleted = true - } else if err != nil { - return nil, ErrWaitingForReplicaSet.Wrap(err) } // If ReplicaSet still exists, wait for the next tick } @@ -91,9 +92,11 @@ func (c *Client) IsReplicaSetRunning(ctx context.Context, name string) (bool, er } func (c *Client) DeleteReplicaSetWithGracePeriod(ctx context.Context, name string, gracePeriodSeconds *int64) error { - _, err := c.getReplicaSet(ctx, name) + exists, err := c.ReplicaSetExists(ctx, name) if err != nil { - // If the ReplicaSet does not exist, skip and return without error + return ErrCheckingReplicaSetExists.WithParams(name).Wrap(err) + } + if !exists { return nil } @@ -169,3 +172,16 @@ func prepareReplicaSet(rsConf ReplicaSetConfig, init bool) (*appv1.ReplicaSet, e logrus.Debugf("Prepared ReplicaSet %s in namespace %s", rsConf.Name, rsConf.Namespace) return rs, nil } + +// ReplicaSetExists checks if a ReplicaSet exists in the namespace that k8s is initialized with. +func (c *Client) ReplicaSetExists(ctx context.Context, name string) (bool, error) { + _, err := c.getReplicaSet(ctx, name) + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, ErrGettingReplicaSet.WithParams(name).Wrap(err) + } + + return true, nil +} diff --git a/pkg/knuu/errors.go b/pkg/knuu/errors.go index eb0cc89..9e27118 100644 --- a/pkg/knuu/errors.go +++ b/pkg/knuu/errors.go @@ -214,4 +214,5 @@ var ( ErrCannotLoadEnv = &Error{Code: "Cannot Load Env", Message: "cannot load env"} ErrMaximumVolumesExceeded = &Error{Code: "MaximumVolumesExceeded", Message: "maximum volumes exceeded for instance '%s'"} ErrCustomResourceDefinitionDoesNotExist = &Error{Code: "CustomResourceDefinitionDoesNotExist", Message: "custom resource definition %s does not exist"} + ErrFileIsNotSubFolderOfVolumes = &Error{Code: "FileIsNotSubFolderOfVolumes", Message: "the file '%s' is not a sub folder of any added volume"} ) diff --git a/pkg/knuu/instance.go b/pkg/knuu/instance.go index b124c61..e863296 100644 --- a/pkg/knuu/instance.go +++ b/pkg/knuu/instance.go @@ -480,6 +480,11 @@ func (i *Instance) AddFile(src string, dest string, chown string) error { return err } case Committed: + // check if the dest is a sub folder of added volumes and print a warning if not + if !i.isSubFolderOfVolumes(dest) { + return ErrFileIsNotSubFolderOfVolumes.WithParams(dest) + } + // only allow files, not folders srcInfo, err := os.Stat(src) if os.IsNotExist(err) || srcInfo.IsDir() { diff --git a/pkg/knuu/instance_helper.go b/pkg/knuu/instance_helper.go index b4ae043..7539d02 100644 --- a/pkg/knuu/instance_helper.go +++ b/pkg/knuu/instance_helper.go @@ -625,3 +625,13 @@ func (i *Instance) addBitTwisterSidecar() error { } return nil } + +// isSubFolderOfVolumes checks if the given path is a subfolder of the volumes +func (i *Instance) isSubFolderOfVolumes(path string) bool { + for _, volume := range i.volumes { + if strings.HasPrefix(path, volume.Path) { + return true + } + } + return false +}