mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
odo init filters devfile stacks by supported architectures (#7004)
* Add --architecture flag * Ask architecture during interactive mode * Display architectures of detected Devfile * Fix integration tests * Fix automated doc * Fix e2e tests * Ignore empty lines on doc automation tests * Update pkg/odo/cli/registry/registry.go Co-authored-by: Armel Soro <armel@rm3l.org> * Fix Architectures field in API * Change "select architectures" prompt --------- Co-authored-by: Armel Soro <armel@rm3l.org>
This commit is contained in:
@@ -52,14 +52,15 @@ func TestOdoAlizer(t *testing.T) {
|
|||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
path := "/"
|
path := "/"
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), path).
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), path).
|
||||||
Return(
|
Return(alizer.DetectedFramework{
|
||||||
model.DevFileType{
|
Type: model.DevFileType{
|
||||||
Name: "framework-name",
|
Name: "framework-name",
|
||||||
},
|
},
|
||||||
"1.1.1",
|
DefaultVersion: "1.1.1",
|
||||||
api.Registry{
|
Registry: api.Registry{
|
||||||
Name: "TheRegistryName",
|
Name: "TheRegistryName",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
alizerClient.EXPECT().DetectPorts(path).Return([]int{8080, 3000}, nil)
|
alizerClient.EXPECT().DetectPorts(path).Return([]int{8080, 3000}, nil)
|
||||||
@@ -92,14 +93,15 @@ func TestOdoAlizer(t *testing.T) {
|
|||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
path := "/"
|
path := "/"
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), path).
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), path).
|
||||||
Return(
|
Return(alizer.DetectedFramework{
|
||||||
model.DevFileType{
|
Type: model.DevFileType{
|
||||||
Name: "framework-name",
|
Name: "framework-name",
|
||||||
},
|
},
|
||||||
"1.1.1",
|
DefaultVersion: "1.1.1",
|
||||||
api.Registry{
|
Registry: api.Registry{
|
||||||
Name: "TheRegistryName",
|
Name: "TheRegistryName",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
alizerClient.EXPECT().DetectPorts(path).Return([]int{8080, 3000}, nil)
|
alizerClient.EXPECT().DetectPorts(path).Return([]int{8080, 3000}, nil)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ $ odo init
|
|||||||
Interactive mode enabled, please answer the following questions:
|
Interactive mode enabled, please answer the following questions:
|
||||||
✓ Determining a Devfile for the current directory [1s]
|
✓ Determining a Devfile for the current directory [1s]
|
||||||
Based on the files in the current directory odo detected
|
Based on the files in the current directory odo detected
|
||||||
|
Supported architectures: all
|
||||||
Language: JavaScript
|
Language: JavaScript
|
||||||
Project type: Node.js
|
Project type: Node.js
|
||||||
Application ports: 8080
|
Application ports: 8080
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ $ odo init
|
|||||||
\__/
|
\__/
|
||||||
|
|
||||||
Interactive mode enabled, please answer the following questions:
|
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 language: Java
|
||||||
? Select project type: Maven Java
|
? Select project type: Maven Java
|
||||||
✓ Downloading devfile "java-maven" from registry "DefaultDevfileRegistry" [4s]
|
✓ Downloading devfile "java-maven" from registry "DefaultDevfileRegistry" [4s]
|
||||||
|
|||||||
@@ -9,10 +9,17 @@ $ odo init
|
|||||||
Interactive mode enabled, please answer the following questions:
|
Interactive mode enabled, please answer the following questions:
|
||||||
✓ Determining a Devfile for the current directory [1s]
|
✓ Determining a Devfile for the current directory [1s]
|
||||||
Based on the files in the current directory odo detected
|
Based on the files in the current directory odo detected
|
||||||
|
Supported architectures: all
|
||||||
Language: .NET
|
Language: .NET
|
||||||
Project type: dotnet
|
Project type: dotnet
|
||||||
The devfile "dotnet50:1.0.3" from the registry "DefaultDevfileRegistry" will be downloaded.
|
The devfile "dotnet50:1.0.3" from the registry "DefaultDevfileRegistry" will be downloaded.
|
||||||
? Is this correct? No
|
? 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 language: .NET
|
||||||
? Select project type: .NET 6.0
|
? Select project type: .NET 6.0
|
||||||
✓ Downloading devfile "dotnet60" from registry "DefaultDevfileRegistry" [3s]
|
✓ Downloading devfile "dotnet60" from registry "DefaultDevfileRegistry" [3s]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ $ odo init
|
|||||||
Interactive mode enabled, please answer the following questions:
|
Interactive mode enabled, please answer the following questions:
|
||||||
✓ Determining a Devfile for the current directory [1s]
|
✓ Determining a Devfile for the current directory [1s]
|
||||||
Based on the files in the current directory odo detected
|
Based on the files in the current directory odo detected
|
||||||
|
Supported architectures: all
|
||||||
Language: Go
|
Language: Go
|
||||||
Project type: Go
|
Project type: Go
|
||||||
Application ports: 8080
|
Application ports: 8080
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ $ odo init
|
|||||||
Interactive mode enabled, please answer the following questions:
|
Interactive mode enabled, please answer the following questions:
|
||||||
✓ Determining a Devfile for the current directory [1s]
|
✓ Determining a Devfile for the current directory [1s]
|
||||||
Based on the files in the current directory odo detected
|
Based on the files in the current directory odo detected
|
||||||
|
Supported architectures: all
|
||||||
Language: Java
|
Language: Java
|
||||||
Project type: springboot
|
Project type: springboot
|
||||||
The devfile "java-springboot:1.2.0" from the registry "DefaultDevfileRegistry" will be downloaded.
|
The devfile "java-springboot:1.2.0" from the registry "DefaultDevfileRegistry" will be downloaded.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ $ odo init
|
|||||||
Interactive mode enabled, please answer the following questions:
|
Interactive mode enabled, please answer the following questions:
|
||||||
✓ Determining a Devfile for the current directory [1s]
|
✓ Determining a Devfile for the current directory [1s]
|
||||||
Based on the files in the current directory odo detected
|
Based on the files in the current directory odo detected
|
||||||
|
Supported architectures: all
|
||||||
Language: JavaScript
|
Language: JavaScript
|
||||||
Project type: Node.js
|
Project type: Node.js
|
||||||
Application ports: 3000
|
Application ports: 3000
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ func NewAlizerClient(registryClient registry.Client) *Alizer {
|
|||||||
|
|
||||||
// DetectFramework uses the alizer library in order to detect the devfile
|
// DetectFramework uses the alizer library in order to detect the devfile
|
||||||
// to use depending on the files in the path
|
// 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{}
|
types := []model.DevFileType{}
|
||||||
components, err := o.registryClient.ListDevfileStacks(ctx, "", "", "", false, false)
|
components, err := o.registryClient.ListDevfileStacks(ctx, "", "", "", false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return model.DevFileType{}, defaultVersion, api.Registry{}, err
|
return DetectedFramework{}, err
|
||||||
}
|
}
|
||||||
for _, component := range components.Items {
|
for _, component := range components.Items {
|
||||||
types = append(types, model.DevFileType{
|
types = append(types, model.DevFileType{
|
||||||
@@ -45,15 +45,21 @@ func (o *Alizer) DetectFramework(ctx context.Context, path string) (_ model.DevF
|
|||||||
}
|
}
|
||||||
typ, err := recognizer.SelectDevFileFromTypes(path, types)
|
typ, err := recognizer.SelectDevFileFromTypes(path, types)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return model.DevFileType{}, defaultVersion, api.Registry{}, err
|
return DetectedFramework{}, err
|
||||||
}
|
}
|
||||||
// Get the default stack version that will be downloaded
|
// Get the default stack version that will be downloaded
|
||||||
|
var defaultVersion string
|
||||||
for _, version := range components.Items[typ].Versions {
|
for _, version := range components.Items[typ].Versions {
|
||||||
if version.IsDefault {
|
if version.IsDefault {
|
||||||
defaultVersion = version.Version
|
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).
|
// DetectName retrieves the name of the project (if available).
|
||||||
|
|||||||
@@ -119,18 +119,18 @@ func TestDetectFramework(t *testing.T) {
|
|||||||
registryClient.EXPECT().ListDevfileStacks(ctx, "", "", "", false, false).Return(list, nil)
|
registryClient.EXPECT().ListDevfileStacks(ctx, "", "", "", false, false).Return(list, nil)
|
||||||
alizerClient := NewAlizerClient(registryClient)
|
alizerClient := NewAlizerClient(registryClient)
|
||||||
// Run function DetectFramework
|
// 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) {
|
if !tt.wantErr == (err != nil) {
|
||||||
t.Errorf("unexpected error %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("unexpected error %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if detected.Name != tt.wantedDevfile {
|
if detected.Type.Name != tt.wantedDevfile {
|
||||||
t.Errorf("unexpected devfile %v, wantedDevfile %v", detected, tt.wantedDevfile)
|
t.Errorf("unexpected devfile %v, wantedDevfile %v", detected, tt.wantedDevfile)
|
||||||
}
|
}
|
||||||
if registry.Name != tt.wantedRegistry {
|
if detected.Registry.Name != tt.wantedRegistry {
|
||||||
t.Errorf("unexpected registry %v, wantedRegistry %v", registry, tt.wantedRegistry)
|
t.Errorf("unexpected registry %v, wantedRegistry %v", detected.Registry, tt.wantedRegistry)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,18 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/devfile/alizer/pkg/apis/model"
|
"github.com/devfile/alizer/pkg/apis/model"
|
||||||
|
|
||||||
"github.com/redhat-developer/odo/pkg/api"
|
"github.com/redhat-developer/odo/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DetectedFramework struct {
|
||||||
|
Type model.DevFileType
|
||||||
|
DefaultVersion string
|
||||||
|
Registry api.Registry
|
||||||
|
Architectures []string
|
||||||
|
}
|
||||||
|
|
||||||
type Client interface {
|
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)
|
DetectName(path string) (string, error)
|
||||||
DetectPorts(path string) ([]int, error)
|
DetectPorts(path string) ([]int, error)
|
||||||
}
|
}
|
||||||
|
|||||||
12
pkg/alizer/mock.go
generated
12
pkg/alizer/mock.go
generated
@@ -8,9 +8,7 @@ import (
|
|||||||
context "context"
|
context "context"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
model "github.com/devfile/alizer/pkg/apis/model"
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
api "github.com/redhat-developer/odo/pkg/api"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockClient is a mock of Client interface.
|
// MockClient is a mock of Client interface.
|
||||||
@@ -37,14 +35,12 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DetectFramework mocks base method.
|
// DetectFramework mocks base method.
|
||||||
func (m *MockClient) DetectFramework(ctx context.Context, path string) (model.DevFileType, string, api.Registry, error) {
|
func (m *MockClient) DetectFramework(ctx context.Context, path string) (DetectedFramework, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "DetectFramework", ctx, path)
|
ret := m.ctrl.Call(m, "DetectFramework", ctx, path)
|
||||||
ret0, _ := ret[0].(model.DevFileType)
|
ret0, _ := ret[0].(DetectedFramework)
|
||||||
ret1, _ := ret[1].(string)
|
ret1, _ := ret[1].(error)
|
||||||
ret2, _ := ret[2].(api.Registry)
|
return ret0, ret1
|
||||||
ret3, _ := ret[3].(error)
|
|
||||||
return ret0, ret1, ret2, ret3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DetectFramework indicates an expected call of DetectFramework.
|
// DetectFramework indicates an expected call of DetectFramework.
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ type DetectionResult struct {
|
|||||||
DevfileVersion string `json:"devfileVersion,omitempty"`
|
DevfileVersion string `json:"devfileVersion,omitempty"`
|
||||||
// Name represents the project/application name as detected by alizer
|
// Name represents the project/application name as detected by alizer
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
// Architectures represent the architectures with which the Devfile must be compatible with.
|
||||||
|
Architectures []string `json:"architectures,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,18 +24,36 @@ func NewSurveyAsker() *Survey {
|
|||||||
return &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)
|
sort.Strings(langs)
|
||||||
|
langs = append(langs, GOBACK)
|
||||||
question := &survey.Select{
|
question := &survey.Select{
|
||||||
Message: "Select language:",
|
Message: "Select language:",
|
||||||
Options: langs,
|
Options: langs,
|
||||||
}
|
}
|
||||||
var answer string
|
var answerPos int
|
||||||
err := survey.AskOne(question, &answer)
|
err := survey.AskOne(question, &answerPos)
|
||||||
if err != nil {
|
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) {
|
func (o *Survey) AskType(types registry.TypesWithDetails) (back bool, _ api.DevfileStack, _ error) {
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ import (
|
|||||||
|
|
||||||
// Asker interactively asks for information to the user
|
// Asker interactively asks for information to the user
|
||||||
type Asker interface {
|
type Asker interface {
|
||||||
// AskLanguage asks for a language, from a list of language names. The language name is returned
|
// AskArchitectures asks for a selection of architectures from a list of architecture names
|
||||||
AskLanguage(langs []string) (string, error)
|
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,
|
// 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
|
// or the selected type is returned
|
||||||
|
|||||||
24
pkg/init/asker/mock.go
generated
24
pkg/init/asker/mock.go
generated
@@ -66,6 +66,21 @@ func (mr *MockAskerMockRecorder) AskAddPort() *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskAddPort", reflect.TypeOf((*MockAsker)(nil).AskAddPort))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskAddPort", reflect.TypeOf((*MockAsker)(nil).AskAddPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AskArchitectures mocks base method.
|
||||||
|
func (m *MockAsker) AskArchitectures(archs, selectedDefault []string) ([]string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "AskArchitectures", archs, selectedDefault)
|
||||||
|
ret0, _ := ret[0].([]string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// AskArchitectures indicates an expected call of AskArchitectures.
|
||||||
|
func (mr *MockAskerMockRecorder) AskArchitectures(archs, selectedDefault interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskArchitectures", reflect.TypeOf((*MockAsker)(nil).AskArchitectures), archs, selectedDefault)
|
||||||
|
}
|
||||||
|
|
||||||
// AskContainerName mocks base method.
|
// AskContainerName mocks base method.
|
||||||
func (m *MockAsker) AskContainerName(containers []string) (string, error) {
|
func (m *MockAsker) AskContainerName(containers []string) (string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@@ -97,12 +112,13 @@ func (mr *MockAskerMockRecorder) AskCorrect() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AskLanguage mocks base method.
|
// AskLanguage mocks base method.
|
||||||
func (m *MockAsker) AskLanguage(langs []string) (string, error) {
|
func (m *MockAsker) AskLanguage(langs []string) (bool, string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "AskLanguage", langs)
|
ret := m.ctrl.Call(m, "AskLanguage", langs)
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(bool)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(string)
|
||||||
return ret0, ret1
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
}
|
}
|
||||||
|
|
||||||
// AskLanguage indicates an expected call of AskLanguage.
|
// AskLanguage indicates an expected call of AskLanguage.
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ package backend
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/redhat-developer/odo/pkg/log"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/redhat-developer/odo/pkg/log"
|
||||||
|
|
||||||
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||||
"github.com/devfile/library/v2/pkg/devfile/parser"
|
"github.com/devfile/library/v2/pkg/devfile/parser"
|
||||||
|
|
||||||
@@ -34,6 +35,13 @@ func (o *AlizerBackend) Validate(flags map[string]string, fs filesystem.Filesyst
|
|||||||
return nil
|
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
|
// 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) {
|
func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]string, fs filesystem.Filesystem, dir string) (*api.DetectionResult, error) {
|
||||||
type result struct {
|
type result struct {
|
||||||
@@ -47,12 +55,13 @@ func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]stri
|
|||||||
location, err := func() (location *api.DetectionResult, err error) {
|
location, err := func() (location *api.DetectionResult, err error) {
|
||||||
spinner := log.Spinnerf("Determining a Devfile for the current directory")
|
spinner := log.Spinnerf("Determining a Devfile for the current directory")
|
||||||
defer spinner.End(err == nil)
|
defer spinner.End(err == nil)
|
||||||
selected, defaultVersion, registry, err := o.alizerClient.DetectFramework(ctx, dir)
|
detected, err := o.alizerClient.DetectFramework(ctx, dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
appPorts, err := o.alizerClient.DetectPorts(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -68,7 +77,7 @@ func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(msg)
|
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()
|
confirm, err := o.askerClient.AskCorrect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -76,7 +85,7 @@ func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]stri
|
|||||||
if !confirm {
|
if !confirm {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return alizer.NewDetectionResult(selected, registry, appPorts, defaultVersion, ""), nil
|
return alizer.NewDetectionResult(detected.Type, detected.Registry, appPorts, detected.DefaultVersion, ""), nil
|
||||||
}()
|
}()
|
||||||
resultChan <- result{
|
resultChan <- result{
|
||||||
location: location,
|
location: location,
|
||||||
|
|||||||
@@ -53,11 +53,7 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(model.DevFileType{
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(alizer.DetectedFramework{}, errors.New("unable to detect framework"))
|
||||||
Name: "a-devfile-name",
|
|
||||||
}, "1.0.0", api.Registry{
|
|
||||||
Name: "a-registry",
|
|
||||||
}, errors.New("unable to detect framework"))
|
|
||||||
return alizerClient
|
return alizerClient
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -77,11 +73,7 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(model.DevFileType{
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(alizer.DetectedFramework{}, nil)
|
||||||
Name: "a-devfile-name",
|
|
||||||
}, "1.0.0", api.Registry{
|
|
||||||
Name: "a-registry",
|
|
||||||
}, nil)
|
|
||||||
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, errors.New("unable to detect ports"))
|
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, errors.New("unable to detect ports"))
|
||||||
return alizerClient
|
return alizerClient
|
||||||
},
|
},
|
||||||
@@ -102,10 +94,14 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(model.DevFileType{
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(alizer.DetectedFramework{
|
||||||
Name: "a-devfile-name",
|
Type: model.DevFileType{
|
||||||
}, "1.0.0", api.Registry{
|
Name: "a-devfile-name",
|
||||||
Name: "a-registry",
|
},
|
||||||
|
DefaultVersion: "1.0.0",
|
||||||
|
Registry: api.Registry{
|
||||||
|
Name: "a-registry",
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, nil)
|
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, nil)
|
||||||
return alizerClient
|
return alizerClient
|
||||||
@@ -127,10 +123,14 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(model.DevFileType{
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(alizer.DetectedFramework{
|
||||||
Name: "a-devfile-name",
|
Type: model.DevFileType{
|
||||||
}, "1.0.0", api.Registry{
|
Name: "a-devfile-name",
|
||||||
Name: "a-registry",
|
},
|
||||||
|
DefaultVersion: "1.0.0",
|
||||||
|
Registry: api.Registry{
|
||||||
|
Name: "a-registry",
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, nil)
|
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, nil)
|
||||||
return alizerClient
|
return alizerClient
|
||||||
@@ -156,7 +156,7 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(model.DevFileType{}, "", api.Registry{}, nil)
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(alizer.DetectedFramework{}, nil)
|
||||||
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, nil)
|
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return(nil, nil)
|
||||||
return alizerClient
|
return alizerClient
|
||||||
},
|
},
|
||||||
@@ -177,10 +177,14 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
|
||||||
alizerClient := alizer.NewMockClient(ctrl)
|
alizerClient := alizer.NewMockClient(ctrl)
|
||||||
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(model.DevFileType{
|
alizerClient.EXPECT().DetectFramework(gomock.Any(), gomock.Any()).Return(alizer.DetectedFramework{
|
||||||
Name: "a-devfile-name",
|
Type: model.DevFileType{
|
||||||
}, "1.0.0", api.Registry{
|
Name: "a-devfile-name",
|
||||||
Name: "a-registry",
|
},
|
||||||
|
DefaultVersion: "1.0.0",
|
||||||
|
Registry: api.Registry{
|
||||||
|
Name: "a-registry",
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return([]int{1234, 5678}, nil)
|
alizerClient.EXPECT().DetectPorts(gomock.Any()).Return([]int{1234, 5678}, nil)
|
||||||
return alizerClient
|
return alizerClient
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/redhat-developer/odo/pkg/registry"
|
"github.com/redhat-developer/odo/pkg/registry"
|
||||||
|
|
||||||
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||||
|
"github.com/devfile/api/v2/pkg/devfile"
|
||||||
"github.com/devfile/library/v2/pkg/devfile/parser"
|
"github.com/devfile/library/v2/pkg/devfile/parser"
|
||||||
"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
|
"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
|
||||||
dfutil "github.com/devfile/library/v2/pkg/util"
|
dfutil "github.com/devfile/library/v2/pkg/util"
|
||||||
@@ -30,6 +31,7 @@ const (
|
|||||||
FLAG_DEVFILE_PATH = "devfile-path"
|
FLAG_DEVFILE_PATH = "devfile-path"
|
||||||
FLAG_DEVFILE_VERSION = "devfile-version"
|
FLAG_DEVFILE_VERSION = "devfile-version"
|
||||||
FLAG_RUN_PORT = "run-port"
|
FLAG_RUN_PORT = "run-port"
|
||||||
|
FLAG_ARCHITECTURE = "architecture"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FlagsBackend is a backend that will extract all needed information from flags passed to the command
|
// FlagsBackend is a backend that will extract all needed information from flags passed to the command
|
||||||
@@ -39,6 +41,13 @@ type FlagsBackend struct {
|
|||||||
|
|
||||||
var _ InitBackend = (*FlagsBackend)(nil)
|
var _ InitBackend = (*FlagsBackend)(nil)
|
||||||
|
|
||||||
|
var knownArchitectures []string = []string{
|
||||||
|
string(devfile.AMD64),
|
||||||
|
string(devfile.ARM64),
|
||||||
|
string(devfile.PPC64LE),
|
||||||
|
string(devfile.S390X),
|
||||||
|
}
|
||||||
|
|
||||||
func NewFlagsBackend(registryClient registry.Client) *FlagsBackend {
|
func NewFlagsBackend(registryClient registry.Client) *FlagsBackend {
|
||||||
return &FlagsBackend{
|
return &FlagsBackend{
|
||||||
registryClient: registryClient,
|
registryClient: registryClient,
|
||||||
@@ -97,15 +106,37 @@ Please use 'odo preference <add/remove> registry'' command to configure devfile
|
|||||||
return errors.New("--starter parameter cannot be used when the directory is not empty")
|
return errors.New("--starter parameter cannot be used when the directory is not empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
archs, err := parseStringArrayFlagValue(flags[FLAG_ARCHITECTURE])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, arch := range archs {
|
||||||
|
if !isKnownArch(arch) {
|
||||||
|
return fmt.Errorf("value %q is not valid for flag --architecture. Possible values are: %s", arch, strings.Join(knownArchitectures, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isKnownArch(arch string) bool {
|
||||||
|
for _, known := range knownArchitectures {
|
||||||
|
if known == arch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (o *FlagsBackend) SelectDevfile(ctx context.Context, flags map[string]string, _ filesystem.Filesystem, _ string) (*api.DetectionResult, error) {
|
func (o *FlagsBackend) SelectDevfile(ctx context.Context, flags map[string]string, _ filesystem.Filesystem, _ string) (*api.DetectionResult, error) {
|
||||||
|
// This has been validated before
|
||||||
|
archs, _ := parseStringArrayFlagValue(flags[FLAG_ARCHITECTURE])
|
||||||
return &api.DetectionResult{
|
return &api.DetectionResult{
|
||||||
Devfile: flags[FLAG_DEVFILE],
|
Devfile: flags[FLAG_DEVFILE],
|
||||||
DevfileRegistry: flags[FLAG_DEVFILE_REGISTRY],
|
DevfileRegistry: flags[FLAG_DEVFILE_REGISTRY],
|
||||||
DevfilePath: flags[FLAG_DEVFILE_PATH],
|
DevfilePath: flags[FLAG_DEVFILE_PATH],
|
||||||
DevfileVersion: flags[FLAG_DEVFILE_VERSION],
|
DevfileVersion: flags[FLAG_DEVFILE_VERSION],
|
||||||
|
Architectures: archs,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,16 +181,16 @@ func (o FlagsBackend) HandleApplicationPorts(devfileobj parser.DevfileObj, _ []i
|
|||||||
|
|
||||||
func setPortsForFlag(devfileobj parser.DevfileObj, flags map[string]string, flagName string) (parser.DevfileObj, error) {
|
func setPortsForFlag(devfileobj parser.DevfileObj, flags map[string]string, flagName string) (parser.DevfileObj, error) {
|
||||||
flagVal := flags[flagName]
|
flagVal := flags[flagName]
|
||||||
// Repeatable flags are formatted as "[val1,val2]"
|
|
||||||
if !(strings.HasPrefix(flagVal, "[") && strings.HasSuffix(flagVal, "]")) {
|
split, err := parseStringArrayFlagValue(flagVal)
|
||||||
|
if err != nil || len(split) == 0 {
|
||||||
return devfileobj, nil
|
return devfileobj, nil
|
||||||
}
|
}
|
||||||
portsStr := flagVal[1 : len(flagVal)-1]
|
|
||||||
|
|
||||||
var ports []int
|
var ports []int
|
||||||
split := strings.Split(portsStr, ",")
|
|
||||||
for _, s := range split {
|
for _, s := range split {
|
||||||
p, err := strconv.Atoi(s)
|
var p int
|
||||||
|
p, err = strconv.Atoi(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return parser.DevfileObj{}, fmt.Errorf("invalid value for %s (%q): %w", flagName, s, err)
|
return parser.DevfileObj{}, fmt.Errorf("invalid value for %s (%q): %w", flagName, s, err)
|
||||||
}
|
}
|
||||||
@@ -216,3 +247,15 @@ func setPortsForFlag(devfileobj parser.DevfileObj, flags map[string]string, flag
|
|||||||
}
|
}
|
||||||
return devfileobj, nil
|
return devfileobj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseStringArrayFlagValue(flagVal string) ([]string, error) {
|
||||||
|
if flagVal == "" {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
// Repeatable flags are formatted as "[val1,val2]"
|
||||||
|
if !(strings.HasPrefix(flagVal, "[") && strings.HasSuffix(flagVal, "]")) {
|
||||||
|
return nil, fmt.Errorf("malformed value %q", flagVal)
|
||||||
|
}
|
||||||
|
portsStr := flagVal[1 : len(flagVal)-1]
|
||||||
|
return strings.Split(portsStr, ","), nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ func TestFlagsBackend_SelectDevfile(t *testing.T) {
|
|||||||
Devfile: "adevfile",
|
Devfile: "adevfile",
|
||||||
DevfilePath: "apath",
|
DevfilePath: "apath",
|
||||||
DevfileRegistry: "aregistry",
|
DevfileRegistry: "aregistry",
|
||||||
|
Architectures: []string{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||||
"github.com/devfile/library/v2/pkg/devfile/parser"
|
"github.com/devfile/library/v2/pkg/devfile/parser"
|
||||||
@@ -22,7 +23,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
STATE_ASK_LANG = iota
|
STATE_ASK_ARCHITECTURES = iota
|
||||||
|
STATE_ASK_LANG
|
||||||
STATE_ASK_TYPE
|
STATE_ASK_TYPE
|
||||||
STATE_ASK_VERSION
|
STATE_ASK_VERSION
|
||||||
STATE_END
|
STATE_END
|
||||||
@@ -51,22 +53,36 @@ func (o *InteractiveBackend) Validate(flags map[string]string, fs filesystem.Fil
|
|||||||
|
|
||||||
func (o *InteractiveBackend) SelectDevfile(ctx context.Context, flags map[string]string, _ filesystem.Filesystem, _ string) (*api.DetectionResult, error) {
|
func (o *InteractiveBackend) SelectDevfile(ctx context.Context, flags map[string]string, _ filesystem.Filesystem, _ string) (*api.DetectionResult, error) {
|
||||||
result := &api.DetectionResult{}
|
result := &api.DetectionResult{}
|
||||||
devfileEntries, _ := o.registryClient.ListDevfileStacks(ctx, "", "", "", false, false)
|
var devfileEntries registry.DevfileStackList
|
||||||
|
state := STATE_ASK_ARCHITECTURES
|
||||||
langs := devfileEntries.GetLanguages()
|
|
||||||
state := STATE_ASK_LANG
|
|
||||||
var lang string
|
var lang string
|
||||||
|
archs := []string{"amd64"}
|
||||||
var err error
|
var err error
|
||||||
var details api.DevfileStack
|
var details api.DevfileStack
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
switch state {
|
switch state {
|
||||||
|
|
||||||
case STATE_ASK_LANG:
|
case STATE_ASK_ARCHITECTURES:
|
||||||
lang, err = o.askerClient.AskLanguage(langs)
|
archs, err = o.askerClient.AskArchitectures(knownArchitectures, archs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
state = STATE_ASK_LANG
|
||||||
|
|
||||||
|
case STATE_ASK_LANG:
|
||||||
|
filter := strings.Join(archs, ",")
|
||||||
|
devfileEntries, _ = o.registryClient.ListDevfileStacks(ctx, "", "", filter, false, false)
|
||||||
|
langs := devfileEntries.GetLanguages()
|
||||||
|
var back bool
|
||||||
|
back, lang, err = o.askerClient.AskLanguage(langs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if back {
|
||||||
|
state = STATE_ASK_ARCHITECTURES
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
state = STATE_ASK_TYPE
|
state = STATE_ASK_TYPE
|
||||||
|
|
||||||
case STATE_ASK_TYPE:
|
case STATE_ASK_TYPE:
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ func TestInteractiveBackend_SelectDevfile(t *testing.T) {
|
|||||||
fields: fields{
|
fields: fields{
|
||||||
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
|
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
|
||||||
client := asker.NewMockAsker(ctrl)
|
client := asker.NewMockAsker(ctrl)
|
||||||
client.EXPECT().AskLanguage(gomock.Any()).Return("java", nil)
|
client.EXPECT().AskArchitectures(knownArchitectures, []string{"amd64"}).Return([]string{"amd64"}, nil)
|
||||||
|
client.EXPECT().AskLanguage(gomock.Any()).Return(false, "java", nil)
|
||||||
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
|
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
|
||||||
Name: "a-devfile-name",
|
Name: "a-devfile-name",
|
||||||
Registry: api.Registry{
|
Registry: api.Registry{
|
||||||
@@ -57,13 +58,14 @@ func TestInteractiveBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "selection with back",
|
name: "selection with back on language selection",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
|
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
|
||||||
client := asker.NewMockAsker(ctrl)
|
client := asker.NewMockAsker(ctrl)
|
||||||
client.EXPECT().AskLanguage(gomock.Any()).Return("java", nil)
|
client.EXPECT().AskArchitectures(knownArchitectures, []string{"amd64"}).Return([]string{"amd64", "arm64"}, nil)
|
||||||
client.EXPECT().AskType(gomock.Any()).Return(true, api.DevfileStack{}, nil)
|
client.EXPECT().AskLanguage(gomock.Any()).Return(true, "", nil)
|
||||||
client.EXPECT().AskLanguage(gomock.Any()).Return("go", nil)
|
client.EXPECT().AskArchitectures(knownArchitectures, []string{"amd64", "arm64"}).Return([]string{"arm64"}, nil)
|
||||||
|
client.EXPECT().AskLanguage(gomock.Any()).Return(false, "go", nil)
|
||||||
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
|
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
|
||||||
Name: "a-devfile-name",
|
Name: "a-devfile-name",
|
||||||
Registry: api.Registry{
|
Registry: api.Registry{
|
||||||
@@ -74,7 +76,35 @@ func TestInteractiveBackend_SelectDevfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
buildCatalogClient: func(ctrl *gomock.Controller) registry.Client {
|
buildCatalogClient: func(ctrl *gomock.Controller) registry.Client {
|
||||||
client := registry.NewMockClient(ctrl)
|
client := registry.NewMockClient(ctrl)
|
||||||
client.EXPECT().ListDevfileStacks(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
|
client.EXPECT().ListDevfileStacks(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(2)
|
||||||
|
return client
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: &api.DetectionResult{
|
||||||
|
Devfile: "a-devfile-name",
|
||||||
|
DevfileRegistry: "MyRegistry1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "selection with back on type selection",
|
||||||
|
fields: fields{
|
||||||
|
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
|
||||||
|
client := asker.NewMockAsker(ctrl)
|
||||||
|
client.EXPECT().AskArchitectures(knownArchitectures, []string{"amd64"}).Return([]string{"amd64"}, nil)
|
||||||
|
client.EXPECT().AskLanguage(gomock.Any()).Return(false, "java", nil)
|
||||||
|
client.EXPECT().AskType(gomock.Any()).Return(true, api.DevfileStack{}, nil)
|
||||||
|
client.EXPECT().AskLanguage(gomock.Any()).Return(false, "go", nil)
|
||||||
|
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
|
||||||
|
Name: "a-devfile-name",
|
||||||
|
Registry: api.Registry{
|
||||||
|
Name: "MyRegistry1",
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
return client
|
||||||
|
},
|
||||||
|
buildCatalogClient: func(ctrl *gomock.Controller) registry.Client {
|
||||||
|
client := registry.NewMockClient(ctrl)
|
||||||
|
client.EXPECT().ListDevfileStacks(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(2)
|
||||||
return client
|
return client
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ var _initFlags = []string{
|
|||||||
backend.FLAG_DEVFILE_PATH,
|
backend.FLAG_DEVFILE_PATH,
|
||||||
backend.FLAG_DEVFILE_VERSION,
|
backend.FLAG_DEVFILE_VERSION,
|
||||||
backend.FLAG_RUN_PORT,
|
backend.FLAG_RUN_PORT,
|
||||||
|
backend.FLAG_ARCHITECTURE,
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInitClient(fsys filesystem.Filesystem, preferenceClient preference.Client, registryClient registry.Client, alizerClient alizer.Client) *InitClient {
|
func NewInitClient(fsys filesystem.Filesystem, preferenceClient preference.Client, registryClient registry.Client, alizerClient alizer.Client) *InitClient {
|
||||||
@@ -137,7 +138,7 @@ func (o *InitClient) DownloadDevfile(ctx context.Context, devfileLocation *api.D
|
|||||||
if devfileLocation.DevfileVersion != "" {
|
if devfileLocation.DevfileVersion != "" {
|
||||||
devfile = fmt.Sprintf("%s:%s", devfileLocation.Devfile, devfileLocation.DevfileVersion)
|
devfile = fmt.Sprintf("%s:%s", devfileLocation.Devfile, devfileLocation.DevfileVersion)
|
||||||
}
|
}
|
||||||
return destDevfile, o.downloadFromRegistry(ctx, devfileLocation.DevfileRegistry, devfile, destDir)
|
return destDevfile, o.downloadFromRegistry(ctx, devfileLocation.DevfileRegistry, devfile, destDir, devfileLocation.Architectures)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,10 +186,14 @@ func (o *InitClient) downloadDirect(URL string, dest string) error {
|
|||||||
|
|
||||||
// downloadFromRegistry downloads a devfile from the provided registry and saves it in dest
|
// downloadFromRegistry downloads a devfile from the provided registry and saves it in dest
|
||||||
// If registryName is empty, will try to download the devfile from the list of registries in preferences
|
// If registryName is empty, will try to download the devfile from the list of registries in preferences
|
||||||
func (o *InitClient) downloadFromRegistry(ctx context.Context, registryName string, devfile string, dest string) error {
|
// The architectures value indicates to download a Devfile compatible with all of these architectures
|
||||||
|
func (o *InitClient) downloadFromRegistry(ctx context.Context, registryName string, devfile string, dest string, architectures []string) error {
|
||||||
// setting NewIndexSchema ensures that the Devfile library pulls registry based on the stack version
|
// setting NewIndexSchema ensures that the Devfile library pulls registry based on the stack version
|
||||||
registryOptions := segment.GetRegistryOptions(ctx)
|
registryOptions := segment.GetRegistryOptions(ctx)
|
||||||
registryOptions.NewIndexSchema = true
|
registryOptions.NewIndexSchema = true
|
||||||
|
if len(architectures) > 0 {
|
||||||
|
registryOptions.Filter.Architectures = architectures
|
||||||
|
}
|
||||||
|
|
||||||
var downloadSpinner *log.Status
|
var downloadSpinner *log.Status
|
||||||
var forceRegistry bool
|
var forceRegistry bool
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||||
|
"github.com/devfile/registry-support/registry-library/library"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
"github.com/redhat-developer/odo/pkg/api"
|
"github.com/redhat-developer/odo/pkg/api"
|
||||||
@@ -25,6 +26,7 @@ func TestInitClient_downloadFromRegistry(t *testing.T) {
|
|||||||
registryName string
|
registryName string
|
||||||
devfile string
|
devfile string
|
||||||
dest string
|
dest string
|
||||||
|
archs []string
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -52,7 +54,12 @@ func TestInitClient_downloadFromRegistry(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
client.EXPECT().GetDevfileRegistries(gomock.Eq("Registry1")).Return(registryList, nil).Times(1)
|
client.EXPECT().GetDevfileRegistries(gomock.Eq("Registry1")).Return(registryList, nil).Times(1)
|
||||||
client.EXPECT().PullStackFromRegistry("http://registry1", "java", gomock.Any(), gomock.Any()).Return(nil).Times(1)
|
client.EXPECT().PullStackFromRegistry("http://registry1", "java", gomock.Any(), library.RegistryOptions{
|
||||||
|
Telemetry: library.TelemetryData{
|
||||||
|
Client: "odo",
|
||||||
|
},
|
||||||
|
NewIndexSchema: true,
|
||||||
|
}).Return(nil).Times(1)
|
||||||
return client
|
return client
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -63,6 +70,46 @@ func TestInitClient_downloadFromRegistry(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Download devfile from one specific Registry where devfile is present and arch is passed",
|
||||||
|
fields: fields{
|
||||||
|
preferenceClient: func(ctrl *gomock.Controller) preference.Client {
|
||||||
|
client := preference.NewMockClient(ctrl)
|
||||||
|
return client
|
||||||
|
},
|
||||||
|
registryClient: func(ctrl *gomock.Controller) registry.Client {
|
||||||
|
client := registry.NewMockClient(ctrl)
|
||||||
|
registryList := []api.Registry{
|
||||||
|
{
|
||||||
|
Name: "Registry0",
|
||||||
|
URL: "http://registry0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Registry1",
|
||||||
|
URL: "http://registry1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
client.EXPECT().GetDevfileRegistries(gomock.Eq("Registry1")).Return(registryList, nil).Times(1)
|
||||||
|
client.EXPECT().PullStackFromRegistry("http://registry1", "java", gomock.Any(), library.RegistryOptions{
|
||||||
|
Telemetry: library.TelemetryData{
|
||||||
|
Client: "odo",
|
||||||
|
},
|
||||||
|
Filter: library.RegistryFilter{
|
||||||
|
Architectures: []string{"arm64"},
|
||||||
|
},
|
||||||
|
NewIndexSchema: true,
|
||||||
|
}).Return(nil).Times(1)
|
||||||
|
return client
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
registryName: "Registry1",
|
||||||
|
devfile: "java",
|
||||||
|
dest: ".",
|
||||||
|
archs: []string{"arm64"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Fail to download devfile from one specific Registry where devfile is absent",
|
name: "Fail to download devfile from one specific Registry where devfile is absent",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
@@ -167,7 +214,7 @@ func TestInitClient_downloadFromRegistry(t *testing.T) {
|
|||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = envcontext.WithEnvConfig(ctx, config.Configuration{})
|
ctx = envcontext.WithEnvConfig(ctx, config.Configuration{})
|
||||||
if err := o.downloadFromRegistry(ctx, tt.args.registryName, tt.args.devfile, tt.args.dest); (err != nil) != tt.wantErr {
|
if err := o.downloadFromRegistry(ctx, tt.args.registryName, tt.args.devfile, tt.args.dest, tt.args.archs); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("InitClient.downloadFromRegistry() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("InitClient.downloadFromRegistry() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (o *AlizerOptions) Run(ctx context.Context) (err error) {
|
|||||||
// RunForJsonOutput contains the logic for the odo command
|
// RunForJsonOutput contains the logic for the odo command
|
||||||
func (o *AlizerOptions) RunForJsonOutput(ctx context.Context) (out interface{}, err error) {
|
func (o *AlizerOptions) RunForJsonOutput(ctx context.Context) (out interface{}, err error) {
|
||||||
workingDir := odocontext.GetWorkingDirectory(ctx)
|
workingDir := odocontext.GetWorkingDirectory(ctx)
|
||||||
df, defaultVersion, reg, err := o.clientset.AlizerClient.DetectFramework(ctx, workingDir)
|
detected, err := o.clientset.AlizerClient.DetectFramework(ctx, workingDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ func (o *AlizerOptions) RunForJsonOutput(ctx context.Context) (out interface{},
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
result := alizer.NewDetectionResult(df, reg, appPorts, defaultVersion, name)
|
result := alizer.NewDetectionResult(detected.Type, detected.Registry, appPorts, detected.DefaultVersion, name)
|
||||||
return []api.DetectionResult{*result}, nil
|
return []api.DetectionResult{*result}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ var initExample = templates.Examples(`
|
|||||||
|
|
||||||
# Bootstrap a new component and download a starter project
|
# Bootstrap a new component and download a starter project
|
||||||
%[1]s --name my-app --devfile nodejs --starter nodejs-starter
|
%[1]s --name my-app --devfile nodejs --starter nodejs-starter
|
||||||
|
|
||||||
|
# Bootstrap a new component with a specific devfile from registry for a specific architecture
|
||||||
|
%[1]s --name my-app --devfile nodejs --architecture s390x
|
||||||
`)
|
`)
|
||||||
|
|
||||||
type InitOptions struct {
|
type InitOptions struct {
|
||||||
@@ -285,6 +288,7 @@ func NewCmdInit(name, fullName string, testClientset clientset.Clientset) *cobra
|
|||||||
initCmd.Flags().String(backend.FLAG_STARTER, "", "name of the starter project")
|
initCmd.Flags().String(backend.FLAG_STARTER, "", "name of the starter project")
|
||||||
initCmd.Flags().String(backend.FLAG_DEVFILE_PATH, "", "path to a devfile. This is an alternative to using devfile from Devfile registry. It can be local filesystem path or http(s) URL")
|
initCmd.Flags().String(backend.FLAG_DEVFILE_PATH, "", "path to a devfile. This is an alternative to using devfile from Devfile registry. It can be local filesystem path or http(s) URL")
|
||||||
initCmd.Flags().String(backend.FLAG_DEVFILE_VERSION, "", "version of the devfile stack; use \"latest\" to dowload the latest stack")
|
initCmd.Flags().String(backend.FLAG_DEVFILE_VERSION, "", "version of the devfile stack; use \"latest\" to dowload the latest stack")
|
||||||
|
initCmd.Flags().StringArray(backend.FLAG_ARCHITECTURE, []string{}, "Architecture supported. Can be one or multiple values from amd64, arm64, ppc64le, s390x. Default is amd64.")
|
||||||
initCmd.Flags().StringArray(backend.FLAG_RUN_PORT, []string{}, "ports used by the application (via the 'run' command)")
|
initCmd.Flags().StringArray(backend.FLAG_RUN_PORT, []string{}, "ports used by the application (via the 'run' command)")
|
||||||
|
|
||||||
commonflags.UseOutputFlag(initCmd)
|
commonflags.UseOutputFlag(initCmd)
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ var Example = ` # Get all devfile components
|
|||||||
# Filter by name and devfile registry
|
# Filter by name and devfile registry
|
||||||
%[1]s --filter nodejs --devfile-registry DefaultDevfileRegistry
|
%[1]s --filter nodejs --devfile-registry DefaultDevfileRegistry
|
||||||
|
|
||||||
# Filter by architecture
|
# Show the Devfiles supporting both architectures
|
||||||
%[1]s --filter amd64
|
%[1]s --filter amd64,arm64
|
||||||
|
|
||||||
# Show more details from a specific devfile
|
# Show more details from a specific devfile
|
||||||
%[1]s --details --devfile nodejs
|
%[1]s --details --devfile nodejs
|
||||||
@@ -120,7 +120,7 @@ func NewCmdRegistry(name, fullName string, testClientset clientset.Clientset) *c
|
|||||||
clientset.Add(listCmd, clientset.REGISTRY)
|
clientset.Add(listCmd, clientset.REGISTRY)
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
listCmd.Flags().StringVar(&o.filterFlag, "filter", "", "Filter based on the name or description or supported architecture of the component")
|
listCmd.Flags().StringVar(&o.filterFlag, "filter", "", "Comma-separated list of terms for filtering. Search is done using a logical AND against the name or description or supported architectures of the component.")
|
||||||
listCmd.Flags().StringVar(&o.devfileFlag, "devfile", "", "Only the specific Devfile component")
|
listCmd.Flags().StringVar(&o.devfileFlag, "devfile", "", "Only the specific Devfile component")
|
||||||
listCmd.Flags().StringVar(&o.registryFlag, "devfile-registry", "", "Only show components from the specific Devfile registry")
|
listCmd.Flags().StringVar(&o.registryFlag, "devfile-registry", "", "Only show components from the specific Devfile registry")
|
||||||
listCmd.Flags().BoolVar(&o.detailsFlag, "details", false, "Show details of a Devfile, to be used only with --devfile")
|
listCmd.Flags().BoolVar(&o.detailsFlag, "details", false, "Show details of a Devfile, to be used only with --devfile")
|
||||||
|
|||||||
@@ -283,32 +283,37 @@ func (o RegistryClient) ListDevfileStacks(ctx context.Context, registryName, dev
|
|||||||
|
|
||||||
devfiles := []api.DevfileStack{}
|
devfiles := []api.DevfileStack{}
|
||||||
|
|
||||||
|
devfileLoop:
|
||||||
for _, devfile := range registryDevfiles {
|
for _, devfile := range registryDevfiles {
|
||||||
|
|
||||||
// Add the "priority" of the registry to the devfile
|
// Add the "priority" of the registry to the devfile
|
||||||
devfile.Registry.Priority = priorityNumber
|
devfile.Registry.Priority = priorityNumber
|
||||||
|
|
||||||
if filterFlag != "" {
|
if filterFlag != "" {
|
||||||
archs := append(make([]string, 0, len(devfile.Architectures)), devfile.Architectures...)
|
filters := strings.Split(filterFlag, ",")
|
||||||
if len(archs) == 0 {
|
for _, filter := range filters {
|
||||||
// Devfiles with no architectures are compatible with all architectures.
|
filter = strings.TrimSpace(filter)
|
||||||
archs = append(archs,
|
archs := append(make([]string, 0, len(devfile.Architectures)), devfile.Architectures...)
|
||||||
string(apidevfile.AMD64),
|
if len(archs) == 0 {
|
||||||
string(apidevfile.ARM64),
|
// Devfiles with no architectures are compatible with all architectures.
|
||||||
string(apidevfile.PPC64LE),
|
archs = append(archs,
|
||||||
string(apidevfile.S390X),
|
string(apidevfile.AMD64),
|
||||||
)
|
string(apidevfile.ARM64),
|
||||||
}
|
string(apidevfile.PPC64LE),
|
||||||
containsArch := func(s string) bool {
|
string(apidevfile.S390X),
|
||||||
for _, arch := range archs {
|
)
|
||||||
if strings.Contains(arch, s) {
|
}
|
||||||
return true
|
containsArch := func(s string) bool {
|
||||||
}
|
for _, arch := range archs {
|
||||||
|
if strings.Contains(arch, s) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !strings.Contains(devfile.Name, filter) && !strings.Contains(devfile.Description, filter) && !containsArch(filter) {
|
||||||
|
continue devfileLoop
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !strings.Contains(devfile.Name, filterFlag) && !strings.Contains(devfile.Description, filterFlag) && !containsArch(filterFlag) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ var _ = Describe("doc command reference odo init", Label(helper.LabelNoCluster),
|
|||||||
It("Empty directory", func() {
|
It("Empty directory", func() {
|
||||||
args := []string{"odo", "init"}
|
args := []string{"odo", "init"}
|
||||||
out, err := helper.RunInteractive(args, []string{"ODO_LOG_LEVEL=0"}, func(ctx helper.InteractiveContext) {
|
out, err := helper.RunInteractive(args, []string{"ODO_LOG_LEVEL=0"}, func(ctx helper.InteractiveContext) {
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Java")
|
helper.SendLine(ctx, "Java")
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,9 @@ var _ = Describe("User guides: Quickstart test", func() {
|
|||||||
helper.ExpectString(ctx, "Is this correct?")
|
helper.ExpectString(ctx, "Is this correct?")
|
||||||
helper.SendLine(ctx, "No")
|
helper.SendLine(ctx, "No")
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, ".")
|
helper.SendLine(ctx, ".")
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ var _ = Describe("E2E Test", func() {
|
|||||||
command := []string{"odo", "init"}
|
command := []string{"odo", "init"}
|
||||||
_, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
_, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "JavaScript")
|
helper.SendLine(ctx, "JavaScript")
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ func StripSpinner(docString string) (returnString string) {
|
|||||||
line := sc.Text()
|
line := sc.Text()
|
||||||
// trim any special character present in the line
|
// trim any special character present in the line
|
||||||
line = strings.TrimFunc(line, unicode.IsSpace)
|
line = strings.TrimFunc(line, unicode.IsSpace)
|
||||||
|
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// This check is to avoid spinner statements in the cmd output
|
// This check is to avoid spinner statements in the cmd output
|
||||||
// currently it does so for init and dev
|
// currently it does so for init and dev
|
||||||
// e.g. " • Syncing file changes ..."
|
// e.g. " • Syncing file changes ..."
|
||||||
@@ -92,6 +97,9 @@ func GetMDXContent(filePath string) (mdxContent string) {
|
|||||||
for fileScanner.Scan() {
|
for fileScanner.Scan() {
|
||||||
line := fileScanner.Text()
|
line := fileScanner.Text()
|
||||||
line = strings.TrimFunc(line, unicode.IsSpace)
|
line = strings.TrimFunc(line, unicode.IsSpace)
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
mdxContent += line + "\n"
|
mdxContent += line + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ var _ = Describe("odo deploy interactive command tests", func() {
|
|||||||
It("should not fail but fallback to the interactive mode", func() {
|
It("should not fail but fallback to the interactive mode", func() {
|
||||||
_, err := helper.RunInteractive([]string{"odo", "deploy"}, nil, func(ctx helper.InteractiveContext) {
|
_, err := helper.RunInteractive([]string{"odo", "deploy"}, nil, func(ctx helper.InteractiveContext) {
|
||||||
helper.ExpectString(ctx, "Could not determine a Devfile based on the files in the current directory")
|
helper.ExpectString(ctx, "Could not determine a Devfile based on the files in the current directory")
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
ctx.StopCommand()
|
ctx.StopCommand()
|
||||||
})
|
})
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
|
|||||||
@@ -165,6 +165,9 @@ var _ = Describe("odo dev interactive command tests", func() {
|
|||||||
output, _ := helper.RunInteractive([]string{"odo", "dev", "--random-ports"}, nil, func(ctx helper.InteractiveContext) {
|
output, _ := helper.RunInteractive([]string{"odo", "dev", "--random-ports"}, nil, func(ctx helper.InteractiveContext) {
|
||||||
helper.ExpectString(ctx, "Could not determine a Devfile based on the files in the current directory")
|
helper.ExpectString(ctx, "Could not determine a Devfile based on the files in the current directory")
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Python")
|
helper.SendLine(ctx, "Python")
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
|
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Go")
|
helper.SendLine(ctx, "Go")
|
||||||
|
|
||||||
@@ -97,6 +100,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
command := []string{"odo", "init"}
|
command := []string{"odo", "init"}
|
||||||
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Javascript")
|
helper.SendLine(ctx, "Javascript")
|
||||||
|
|
||||||
@@ -148,6 +154,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
command := []string{"odo", "init"}
|
command := []string{"odo", "init"}
|
||||||
_, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
_, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Go")
|
helper.SendLine(ctx, "Go")
|
||||||
|
|
||||||
@@ -192,6 +201,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
|
|
||||||
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Go")
|
helper.SendLine(ctx, "Go")
|
||||||
|
|
||||||
@@ -230,6 +242,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
|
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Go")
|
helper.SendLine(ctx, "Go")
|
||||||
|
|
||||||
@@ -265,6 +280,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
|
|
||||||
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Go")
|
helper.SendLine(ctx, "Go")
|
||||||
|
|
||||||
@@ -301,6 +319,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
|
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "java")
|
helper.SendLine(ctx, "java")
|
||||||
|
|
||||||
@@ -395,6 +416,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
welcomingMsgs := strings.Split(odolog.Stitle(messages.InitializingNewComponent, messages.NoSourceCodeDetected, "odo version: "+version.VERSION), "\n")
|
welcomingMsgs := strings.Split(odolog.Stitle(messages.InitializingNewComponent, messages.NoSourceCodeDetected, "odo version: "+version.VERSION), "\n")
|
||||||
|
|
||||||
output, err := testRunner(language, welcomingMsgs, func(ctx helper.InteractiveContext) {
|
output, err := testRunner(language, welcomingMsgs, func(ctx helper.InteractiveContext) {
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, language)
|
helper.SendLine(ctx, language)
|
||||||
|
|
||||||
@@ -547,6 +571,9 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
|
|
||||||
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
|
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, ".NET")
|
helper.SendLine(ctx, ".NET")
|
||||||
|
|
||||||
@@ -643,7 +670,7 @@ var _ = Describe("odo init interactive command tests", func() {
|
|||||||
_, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
|
_, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
|
||||||
helper.ExpectString(ctx, "Could not determine a Devfile based on the files in the current directory")
|
helper.ExpectString(ctx, "Could not determine a Devfile based on the files in the current directory")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
ctx.StopCommand()
|
ctx.StopCommand()
|
||||||
})
|
})
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
@@ -689,6 +716,9 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
|
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
|
||||||
|
helper.ExpectString(ctx, "Select architectures")
|
||||||
|
helper.SendLine(ctx, "")
|
||||||
|
|
||||||
helper.ExpectString(ctx, "Select language")
|
helper.ExpectString(ctx, "Select language")
|
||||||
helper.SendLine(ctx, "Java")
|
helper.SendLine(ctx, "Java")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user