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

Devfile v2 command group impl + Odo catalog list components #3291

Merged
merged 16 commits into from
Jun 27, 2020
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
121 changes: 14 additions & 107 deletions pkg/catalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import (
"github.com/openshift/odo/pkg/preference"

imagev1 "github.com/openshift/api/image/v1"
"github.com/openshift/odo/pkg/devfile/adapters/common"
"github.com/openshift/odo/pkg/log"
"github.com/openshift/odo/pkg/occlient"
"github.com/openshift/odo/pkg/util"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
)
Expand Down Expand Up @@ -94,8 +92,8 @@ func convertURL(URL string) (string, error) {

const indexPath = "/devfiles/index.json"

// getDevfileIndexEntries retrieves the devfile entries associated with the specified registry
func getDevfileIndexEntries(registry Registry) ([]DevfileIndexEntry, error) {
// getRegistryDevfiles retrieves the registry's index devfile entries
func getRegistryDevfiles(registry Registry) ([]DevfileComponentType, error) {
var devfileIndex []DevfileIndexEntry

URL, err := convertURL(registry.URL)
Expand All @@ -114,72 +112,20 @@ func getDevfileIndexEntries(registry Registry) ([]DevfileIndexEntry, error) {
return nil, errors.Wrapf(err, "Unable to unmarshal the devfile index.json from %s", indexLink)
}

for i := range devfileIndex {
devfileIndex[i].Registry = registry
}

return devfileIndex, nil
}

// GetDevfile loads the devfile
func GetDevfile(devfileLink string) (Devfile, error) {
var devfile Devfile

yamlBytes, err := util.HTTPGetRequest(devfileLink)
if err != nil {
return Devfile{}, errors.Wrapf(err, "Unable to download the devfile from %s", devfileLink)
}

err = yaml.Unmarshal(yamlBytes, &devfile)
if err != nil {
return Devfile{}, errors.Wrapf(err, "Unable to unmarshal the devfile from %s", devfileLink)
}

return devfile, nil
}

// IsDevfileComponentSupported checks if the devfile is supported
// The supported devfile should satisfy the following conditions:
// 1. Devfile has dockerimage as component type
// 2. Devfile has alias
// 3. Devfile has run command
// 4. Devfile has build command
func IsDevfileComponentSupported(devfile Devfile) bool {
hasDockerImage := false
hasAlias := false
hasRunCommand := false
hasBuildCommand := false

for _, component := range devfile.Components {
if hasDockerImage && hasAlias {
break
}

if !hasDockerImage {
hasDockerImage = strings.Contains(component.Type, "dockerimage")
}

if !hasAlias {
hasAlias = len(component.Alias) > 0
}
}

for _, command := range devfile.Commands {
if hasRunCommand && hasBuildCommand {
break
}
var registryDevfiles []DevfileComponentType

if !hasRunCommand {
hasRunCommand = strings.Contains(strings.ToLower(command.Name), string(common.DefaultDevfileRunCommand))
for _, devfileIndexEntry := range devfileIndex {
stackDevfile := DevfileComponentType{
Name: devfileIndexEntry.Name,
DisplayName: devfileIndexEntry.DisplayName,
Description: devfileIndexEntry.Description,
Link: devfileIndexEntry.Links.Link,
Registry: registry,
}

registryDevfiles = append(registryDevfiles, stackDevfile)
}

if hasDockerImage && hasAlias && hasRunCommand {
return true
}

return false
return registryDevfiles, nil
}

// ListDevfileComponents lists all the available devfile components
Expand All @@ -198,66 +144,27 @@ func ListDevfileComponents(registryName string) (DevfileComponentTypeList, error
}

// first retrieve the indices for each registry, concurrently
registryIndices := make([]DevfileIndexEntry, 0, 20)
devfileIndicesMutex := &sync.Mutex{}
retrieveRegistryIndices := util.NewConcurrentTasks(len(catalogDevfileList.DevfileRegistries))
for _, reg := range catalogDevfileList.DevfileRegistries {
// Load the devfile registry index.json
registry := reg // needed to prevent the lambda from capturing the value
retrieveRegistryIndices.Add(util.ConcurrentTask{ToRun: func(errChannel chan error) {
indexEntries, err := getDevfileIndexEntries(registry)
registryDevfiles, err := getRegistryDevfiles(registry)
if err != nil {
log.Warningf("Registry %s is not set up properly with error: %v", registry.Name, err)
return
}

devfileIndicesMutex.Lock()
registryIndices = append(registryIndices, indexEntries...)
catalogDevfileList.Items = append(catalogDevfileList.Items, registryDevfiles...)
devfileIndicesMutex.Unlock()
}})
}
if err := retrieveRegistryIndices.Run(); err != nil {
return *catalogDevfileList, err
}

// 1. Load each devfile concurrently from the previously retrieved devfile index entries
// 2. Populate devfile components with devfile data
// 3. Add devfile component types to the catalog devfile list
retrieveDevfiles := util.NewConcurrentTasks(len(registryIndices))
devfileMutex := &sync.Mutex{}
for _, index := range registryIndices {
// Load the devfile
devfileIndex := index // needed to prevent the lambda from capturing the value
link := devfileIndex.Registry.URL + devfileIndex.Links.Link
retrieveDevfiles.Add(util.ConcurrentTask{ToRun: func(errChannel chan error) {

// Note that this issues an HTTP get per devfile entry in the catalog, while doing it concurrently instead of
// sequentially improves the performance, caching that information would improve the performance even more
devfile, err := GetDevfile(link)
if err != nil {
log.Warningf("Registry %s is not set up properly with error: %v", devfileIndex.Registry.Name, err)
return
}

// Populate devfile component with devfile data and form devfile component list
catalogDevfile := DevfileComponentType{
Name: strings.TrimSuffix(devfile.MetaData.GenerateName, "-"),
DisplayName: devfileIndex.DisplayName,
Description: devfileIndex.Description,
Link: devfileIndex.Links.Link,
Support: IsDevfileComponentSupported(devfile),
Registry: devfileIndex.Registry,
}

devfileMutex.Lock()
catalogDevfileList.Items = append(catalogDevfileList.Items, catalogDevfile)
devfileMutex.Unlock()
}})
}
if err := retrieveDevfiles.Run(); err != nil {
return *catalogDevfileList, err
}

return *catalogDevfileList, nil
}

Expand Down
Loading