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

odo init filters devfile stacks by supported architectures #7004

Merged
Merged
18 changes: 10 additions & 8 deletions cmd/odo/alizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ func TestOdoAlizer(t *testing.T) {
alizerClient := alizer.NewMockClient(ctrl)
path := "/"
alizerClient.EXPECT().DetectFramework(gomock.Any(), path).
Return(
model.DevFileType{
Return(alizer.DetectedFramework{
Type: model.DevFileType{
Name: "framework-name",
},
"1.1.1",
api.Registry{
DefaultVersion: "1.1.1",
Registry: api.Registry{
Name: "TheRegistryName",
},
},
nil,
)
alizerClient.EXPECT().DetectPorts(path).Return([]int{8080, 3000}, nil)
Expand Down Expand Up @@ -92,14 +93,15 @@ func TestOdoAlizer(t *testing.T) {
alizerClient := alizer.NewMockClient(ctrl)
path := "/"
alizerClient.EXPECT().DetectFramework(gomock.Any(), path).
Return(
model.DevFileType{
Return(alizer.DetectedFramework{
Type: model.DevFileType{
Name: "framework-name",
},
"1.1.1",
api.Registry{
DefaultVersion: "1.1.1",
Registry: api.Registry{
Name: "TheRegistryName",
},
},
nil,
)
alizerClient.EXPECT().DetectPorts(path).Return([]int{8080, 3000}, nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $ odo init
Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Supported architectures: all
Language: JavaScript
Project type: Node.js
Application ports: 8080
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ $ odo init
\__/

Interactive mode enabled, please answer the following questions:
? Select architectures to filter by: [Use arrows to move, space to select, <right> to all, <left> to none, type to filter]
> [x] amd64
[ ] arm64
[ ] ppc64le
[ ] s390x
? Select architectures to filter by: amd64
? Select language: Java
? Select project type: Maven Java
✓ Downloading devfile "java-maven" from registry "DefaultDevfileRegistry" [4s]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ $ odo init
Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Supported architectures: all
Language: .NET
Project type: dotnet
The devfile "dotnet50:1.0.3" from the registry "DefaultDevfileRegistry" will be downloaded.
? Is this correct? No
? Select architectures to filter by: [Use arrows to move, space to select, <right> to all, <left> to none, type to filter]
> [x] amd64
[ ] arm64
[ ] ppc64le
[ ] s390x
? Select architectures to filter by: amd64
? Select language: .NET
? Select project type: .NET 6.0
✓ Downloading devfile "dotnet60" from registry "DefaultDevfileRegistry" [3s]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $ odo init
Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Supported architectures: all
Language: Go
Project type: Go
Application ports: 8080
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $ odo init
Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Supported architectures: all
Language: Java
Project type: springboot
The devfile "java-springboot:1.2.0" from the registry "DefaultDevfileRegistry" will be downloaded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $ odo init
Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Supported architectures: all
Language: JavaScript
Project type: Node.js
Application ports: 3000
Expand Down
14 changes: 10 additions & 4 deletions pkg/alizer/alizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ func NewAlizerClient(registryClient registry.Client) *Alizer {

// DetectFramework uses the alizer library in order to detect the devfile
// to use depending on the files in the path
func (o *Alizer) DetectFramework(ctx context.Context, path string) (_ model.DevFileType, defaultVersion string, _ api.Registry, _ error) {
func (o *Alizer) DetectFramework(ctx context.Context, path string) (DetectedFramework, error) {
types := []model.DevFileType{}
components, err := o.registryClient.ListDevfileStacks(ctx, "", "", "", false, false)
if err != nil {
return model.DevFileType{}, defaultVersion, api.Registry{}, err
return DetectedFramework{}, err
}
for _, component := range components.Items {
types = append(types, model.DevFileType{
Expand All @@ -45,15 +45,21 @@ func (o *Alizer) DetectFramework(ctx context.Context, path string) (_ model.DevF
}
typ, err := recognizer.SelectDevFileFromTypes(path, types)
if err != nil {
return model.DevFileType{}, defaultVersion, api.Registry{}, err
return DetectedFramework{}, err
}
// Get the default stack version that will be downloaded
var defaultVersion string
for _, version := range components.Items[typ].Versions {
if version.IsDefault {
defaultVersion = version.Version
}
}
return types[typ], defaultVersion, components.Items[typ].Registry, nil
return DetectedFramework{
Type: types[typ],
DefaultVersion: defaultVersion,
Registry: components.Items[typ].Registry,
Architectures: components.Items[typ].Architectures,
}, nil
}

// DetectName retrieves the name of the project (if available).
Expand Down
8 changes: 4 additions & 4 deletions pkg/alizer/alizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,18 @@ func TestDetectFramework(t *testing.T) {
registryClient.EXPECT().ListDevfileStacks(ctx, "", "", "", false, false).Return(list, nil)
alizerClient := NewAlizerClient(registryClient)
// Run function DetectFramework
detected, _, registry, err := alizerClient.DetectFramework(ctx, tt.args.path)

detected, err := alizerClient.DetectFramework(ctx, tt.args.path)
if !tt.wantErr == (err != nil) {
t.Errorf("unexpected error %v, wantErr %v", err, tt.wantErr)
return
}

if detected.Name != tt.wantedDevfile {
if detected.Type.Name != tt.wantedDevfile {
t.Errorf("unexpected devfile %v, wantedDevfile %v", detected, tt.wantedDevfile)
}
if registry.Name != tt.wantedRegistry {
t.Errorf("unexpected registry %v, wantedRegistry %v", registry, tt.wantedRegistry)
if detected.Registry.Name != tt.wantedRegistry {
t.Errorf("unexpected registry %v, wantedRegistry %v", detected.Registry, tt.wantedRegistry)
}
})
}
Expand Down
10 changes: 8 additions & 2 deletions pkg/alizer/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import (
"context"

"github.com/devfile/alizer/pkg/apis/model"

"github.com/redhat-developer/odo/pkg/api"
)

type DetectedFramework struct {
Type model.DevFileType
DefaultVersion string
Registry api.Registry
Architectures []string
}

type Client interface {
DetectFramework(ctx context.Context, path string) (_ model.DevFileType, defaultVersion string, _ api.Registry, _ error)
DetectFramework(ctx context.Context, path string) (DetectedFramework, error)
DetectName(path string) (string, error)
DetectPorts(path string) ([]int, error)
}
12 changes: 4 additions & 8 deletions pkg/alizer/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/api/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ type DetectionResult struct {
DevfileVersion string `json:"devfileVersion,omitempty"`
// Name represents the project/application name as detected by alizer
Name string `json:"name,omitempty"`
// Architectures represent the architectures with which the Devfile must be compatible with.
Architectures []string `json:"architectures,omitempty"`
}
28 changes: 23 additions & 5 deletions pkg/init/asker/asker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,36 @@ func NewSurveyAsker() *Survey {
return &Survey{}
}

func (o *Survey) AskLanguage(langs []string) (string, error) {
func (o *Survey) AskArchitectures(archs []string, selectedDefault []string) ([]string, error) {
question := &survey.MultiSelect{
Message: "Select architectures to filter by:",
Options: archs,
Default: selectedDefault,
}
var answer []string
err := survey.AskOne(question, &answer)
if err != nil {
return nil, err
}
return answer, nil
}

func (o *Survey) AskLanguage(langs []string) (bool, string, error) {
sort.Strings(langs)
langs = append(langs, GOBACK)
question := &survey.Select{
Message: "Select language:",
Options: langs,
}
var answer string
err := survey.AskOne(question, &answer)
var answerPos int
err := survey.AskOne(question, &answerPos)
if err != nil {
return "", err
return false, "", err
}
return answer, nil
if answerPos == len(langs)-1 {
return true, "", nil
}
return false, langs[answerPos], nil
}

func (o *Survey) AskType(types registry.TypesWithDetails) (back bool, _ api.DevfileStack, _ error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/init/asker/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import (

// Asker interactively asks for information to the user
type Asker interface {
// AskLanguage asks for a language, from a list of language names. The language name is returned
AskLanguage(langs []string) (string, error)
// AskArchitectures asks for a selection of architectures from a list of architecture names
AskArchitectures(archs []string, selectedDefault []string) ([]string, error)

// AskLanguage asks for a language, from a list of language names.
// back is returned as true if the user selected to go back, or the language name is returned
AskLanguage(langs []string) (back bool, result string, err error)

// AskType asks for a Devfile type, or to go back. back is returned as true if the user selected to go back,
// or the selected type is returned
Expand Down
24 changes: 20 additions & 4 deletions pkg/init/asker/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 14 additions & 5 deletions pkg/init/backend/alizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package backend
import (
"context"
"fmt"
"github.com/redhat-developer/odo/pkg/log"
"strconv"
"strings"

"github.com/redhat-developer/odo/pkg/log"

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

Expand Down Expand Up @@ -34,6 +35,13 @@ func (o *AlizerBackend) Validate(flags map[string]string, fs filesystem.Filesyst
return nil
}

func archList(archs []string) string {
if len(archs) == 0 {
return "all"
}
return strings.Join(archs, ", ")
}

// SelectDevfile calls the Alizer to detect the devfile and asks for confirmation to the user
func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]string, fs filesystem.Filesystem, dir string) (*api.DetectionResult, error) {
type result struct {
Expand All @@ -47,12 +55,13 @@ func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]stri
location, err := func() (location *api.DetectionResult, err error) {
spinner := log.Spinnerf("Determining a Devfile for the current directory")
defer spinner.End(err == nil)
selected, defaultVersion, registry, err := o.alizerClient.DetectFramework(ctx, dir)
detected, err := o.alizerClient.DetectFramework(ctx, dir)
if err != nil {
return nil, err
}

msg := fmt.Sprintf("Based on the files in the current directory odo detected\nLanguage: %s\nProject type: %s", selected.Language, selected.ProjectType)
msg := fmt.Sprintf("Based on the files in the current directory odo detected\nSupported architectures: %s\nLanguage: %s\nProject type: %s",
archList(detected.Architectures), detected.Type.Language, detected.Type.ProjectType)

appPorts, err := o.alizerClient.DetectPorts(dir)
if err != nil {
Expand All @@ -68,15 +77,15 @@ func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]stri
}

fmt.Println(msg)
fmt.Printf("The devfile \"%s:%s\" from the registry %q will be downloaded.\n", selected.Name, defaultVersion, registry.Name)
fmt.Printf("The devfile \"%s:%s\" from the registry %q will be downloaded.\n", detected.Type.Name, detected.DefaultVersion, detected.Registry.Name)
confirm, err := o.askerClient.AskCorrect()
if err != nil {
return nil, err
}
if !confirm {
return nil, nil
}
return alizer.NewDetectionResult(selected, registry, appPorts, defaultVersion, ""), nil
return alizer.NewDetectionResult(detected.Type, detected.Registry, appPorts, detected.DefaultVersion, ""), nil
}()
resultChan <- result{
location: location,
Expand Down
Loading