Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: include starter projects for $PROJECT_SOURCE path selection #1190

Merged
merged 3 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions pkg/library/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@ package container
import (
"fmt"

"github.com/devfile/devworkspace-operator/pkg/library/overrides"

dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
"github.com/devfile/devworkspace-operator/pkg/library/flatten"
"github.com/devfile/devworkspace-operator/pkg/library/lifecycle"
"github.com/devfile/devworkspace-operator/pkg/library/overrides"
corev1 "k8s.io/api/core/v1"
)

Expand Down Expand Up @@ -65,7 +64,9 @@ func GetKubeContainersFromDevfile(workspace *dw.DevWorkspaceTemplateSpec, securi
if err != nil {
return nil, err
}
handleMountSources(k8sContainer, component.Container, workspace.Projects)
if err := handleMountSources(k8sContainer, component.Container, workspace); err != nil {
return nil, err
}
if overrides.NeedsContainerOverride(&component) {
patchedContainer, err := overrides.ApplyContainerOverrides(&component, k8sContainer)
if err != nil {
Expand All @@ -89,7 +90,9 @@ func GetKubeContainersFromDevfile(workspace *dw.DevWorkspaceTemplateSpec, securi
if err != nil {
return nil, err
}
handleMountSources(k8sContainer, initComponent.Container, workspace.Projects)
if err := handleMountSources(k8sContainer, initComponent.Container, workspace); err != nil {
return nil, err
}
if overrides.NeedsContainerOverride(&initComponent) {
patchedContainer, err := overrides.ApplyContainerOverrides(&initComponent, k8sContainer)
if err != nil {
Expand Down
47 changes: 34 additions & 13 deletions pkg/library/container/mountSources.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/devfile/devworkspace-operator/pkg/constants"
devfileConstants "github.com/devfile/devworkspace-operator/pkg/library/constants"
projectslib "github.com/devfile/devworkspace-operator/pkg/library/projects"
)

// HasMountSources evaluates whether project sources should be mounted in the given container component.
Expand Down Expand Up @@ -53,9 +54,9 @@ func AnyMountSources(devfileComponents []dw.Component) bool {

// handleMountSources adds a volumeMount to a container if the corresponding devfile container has
// mountSources enabled.
func handleMountSources(k8sContainer *corev1.Container, devfileContainer *dw.ContainerComponent, projects []dw.Project) {
func handleMountSources(k8sContainer *corev1.Container, devfileContainer *dw.ContainerComponent, workspace *dw.DevWorkspaceTemplateSpec) error {
if !HasMountSources(devfileContainer) {
return
return nil
}
var sourceMapping string
if vm := getProjectsVolumeMount(k8sContainer); vm != nil {
Expand All @@ -75,7 +76,10 @@ func handleMountSources(k8sContainer *corev1.Container, devfileContainer *dw.Con
})
}

projectsSourcePath := getProjectSourcePath(projects)
projectsSourcePath, err := getProjectSourcePath(workspace)
if err != nil {
return err
}

k8sContainer.Env = append(k8sContainer.Env, corev1.EnvVar{
Name: devfileConstants.ProjectsRootEnvVar,
Expand All @@ -84,20 +88,37 @@ func handleMountSources(k8sContainer *corev1.Container, devfileContainer *dw.Con
Name: devfileConstants.ProjectsSourceEnvVar,
Value: path.Join(sourceMapping, projectsSourcePath),
})

return nil
}

// getProjectSourcePath gets the path, relative to PROJECTS_ROOT, that should be used for the PROJECT_SOURCE env var
func getProjectSourcePath(projects []dw.Project) string {
projectPath := ""
// getProjectSourcePath gets the path, relative to PROJECTS_ROOT, that should be used for the PROJECT_SOURCE env var.
// Returns an error if there was a problem retrieving the selected starter project.
//
// The project source path is determined based on the following priorities:
//
// 1. If the workspace has at least one regular project, the first one will be selected.
// If the first project has a clone path, it will be used, otherwise the project's name will be used as the project source path.
//
// 2. If the workspace has a starter project that is selected, its name will be used as the project source path.
//
// 3. Otherwise, the returned project source path will be an empty string.
func getProjectSourcePath(workspace *dw.DevWorkspaceTemplateSpec) (string, error) {
projects := workspace.Projects
// If there are any projects, return the first one's clone path
if len(projects) > 0 {
firstProject := projects[0]
if firstProject.ClonePath != "" {
projectPath = firstProject.ClonePath
} else {
projectPath = firstProject.Name
}
return projectslib.GetClonePath(&projects[0]), nil
}

// No projects, check if we have a selected starter project
selectedStarterProject, err := projectslib.GetStarterProject(workspace)
if err != nil {
return "", err
} else if selectedStarterProject != nil {
// Starter projects do not allow specifying a clone path, so use the name
return selectedStarterProject.Name, nil
}
return projectPath
return "", nil
}

// getProjectsVolumeMount returns the projects volumeMount in a container, if it is defined; if it does not exist,
Expand Down
8 changes: 8 additions & 0 deletions pkg/library/projects/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ func GetStarterProject(workspace *dw.DevWorkspaceTemplateSpec) (*dw.StarterProje
return nil, fmt.Errorf("selected starter project %s not found in workspace starterProjects", selectedStarterProject)
}

// GetClonePath gets the correct clonePath for a project, given the semantics in devfile/api
func GetClonePath(project *dw.Project) string {
if project.ClonePath != "" {
return project.ClonePath
}
return project.Name
}

func hasContainerComponents(workspace *dw.DevWorkspaceTemplateSpec) bool {
for _, component := range workspace.Components {
if component.Container != nil {
Expand Down
8 changes: 0 additions & 8 deletions project-clone/internal/devfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,6 @@ const (
ProjectSubDir = "subDir"
)

// GetClonePath gets the correct clonePath for a project, given the semantics in devfile/api
func GetClonePath(project *dw.Project) string {
if project.ClonePath != "" {
return project.ClonePath
}
return project.Name
}

// ReadFlattenedDevWorkspace reads the flattened DevWorkspaceTemplateSpec from disk. The location of the flattened
// yaml is determined from the DevWorkspace Operator-provisioned environment variable.
func ReadFlattenedDevWorkspace() (*dw.DevWorkspaceTemplateSpec, error) {
Expand Down
9 changes: 5 additions & 4 deletions project-clone/internal/git/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path"

dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
projectslib "github.com/devfile/devworkspace-operator/pkg/library/projects"

"github.com/devfile/devworkspace-operator/project-clone/internal"
)
Expand All @@ -44,7 +45,7 @@ func SetupGitProject(project dw.Project) error {
func doInitialGitClone(project *dw.Project) error {
// Clone into a temp dir and then move set up project to PROJECTS_ROOT to try and make clone atomic in case
// project-clone container is terminated
tmpClonePath := path.Join(internal.CloneTmpDir, internal.GetClonePath(project))
tmpClonePath := path.Join(internal.CloneTmpDir, projectslib.GetClonePath(project))
err := CloneProject(project, tmpClonePath)
if err != nil {
return fmt.Errorf("failed to clone project: %s", err)
Expand Down Expand Up @@ -83,7 +84,7 @@ func doInitialGitClone(project *dw.Project) error {
}

func setupRemotesForExistingProject(project *dw.Project) error {
projectPath := path.Join(internal.ProjectsRoot, internal.GetClonePath(project))
projectPath := path.Join(internal.ProjectsRoot, projectslib.GetClonePath(project))
repo, err := internal.OpenRepo(projectPath)
if err != nil {
return fmt.Errorf("failed to open existing project in filesystem: %s", err)
Expand All @@ -105,13 +106,13 @@ func copyProjectFromTmpDir(project *dw.Project, tmpClonePath string) error {
return fmt.Errorf("failed to process subDir on project: %w", err)
}
subDirPath := path.Join(tmpClonePath, subDirSubPath)
projectPath := path.Join(internal.ProjectsRoot, internal.GetClonePath(project))
projectPath := path.Join(internal.ProjectsRoot, projectslib.GetClonePath(project))
log.Printf("Moving subdirectory %s in project %s from temporary directory to %s", subDirSubPath, project.Name, projectPath)
if err := os.Rename(subDirPath, projectPath); err != nil {
return fmt.Errorf("failed to move subdirectory of cloned project to %s: %w", internal.ProjectsRoot, err)
}
} else {
projectPath := path.Join(internal.ProjectsRoot, internal.GetClonePath(project))
projectPath := path.Join(internal.ProjectsRoot, projectslib.GetClonePath(project))
log.Printf("Moving cloned project %s from temporary directory %s to %s", project.Name, tmpClonePath, projectPath)
if err := os.Rename(tmpClonePath, projectPath); err != nil {
return fmt.Errorf("failed to move cloned project to %s: %w", internal.ProjectsRoot, err)
Expand Down
5 changes: 3 additions & 2 deletions project-clone/internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"path/filepath"

dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
projectslib "github.com/devfile/devworkspace-operator/pkg/library/projects"
"github.com/go-git/go-git/v5"
)

Expand All @@ -37,7 +38,7 @@ func CheckProjectState(project *dw.Project) (needClone, needRemotes bool, err er
if project.Attributes.Exists(ProjectSubDir) {
return checkSubPathProjectState(project)
}
repo, err := OpenRepo(path.Join(ProjectsRoot, GetClonePath(project)))
repo, err := OpenRepo(path.Join(ProjectsRoot, projectslib.GetClonePath(project)))
if err != nil {
return false, false, err
}
Expand Down Expand Up @@ -105,7 +106,7 @@ func checkSubPathProjectState(project *dw.Project) (needClone, needRemotes bool,
}

// Result here won't be a git repository, so we only check whether the directory exists
clonePath := path.Join(ProjectsRoot, GetClonePath(project))
clonePath := path.Join(ProjectsRoot, projectslib.GetClonePath(project))
stat, err := os.Stat(clonePath)
if err != nil {
if os.IsNotExist(err) {
Expand Down
3 changes: 2 additions & 1 deletion project-clone/internal/zip/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"

projectslib "github.com/devfile/devworkspace-operator/pkg/library/projects"
"github.com/devfile/devworkspace-operator/project-clone/internal"
)

Expand All @@ -40,7 +41,7 @@ func SetupZipProject(project v1alpha2.Project, httpClient *http.Client) error {
return fmt.Errorf("project has no 'zip' source")
}
url := project.Zip.Location
clonePath := internal.GetClonePath(&project)
clonePath := projectslib.GetClonePath(&project)
projectPath := path.Join(internal.ProjectsRoot, clonePath)
if exists, err := internal.DirExists(projectPath); exists {
// Assume project is already set up
Expand Down
1 change: 0 additions & 1 deletion project-clone/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const (
tmpLogFilePath = "/tmp/" + logFileName
)

// TODO: Handle sparse checkout
func main() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might consider also moving GetClonePath to the projects library, since we're doing it both in container and project-clone

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is here because it's the only file in project-clone in this PR, this has nothing to do with removing the TODO (thanks!) :D

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up moving GetClonePath since it made sense anyhow :P

f, err := os.Create(tmpLogFilePath)
if err != nil {
Expand Down
Loading