odo registry -o json (#5739)

* Doc odo registry

* JSON output

* Move structure for JSON output to api package

* Doc for json output

* Add integration tests

* Review

* Do not rely on devfile version for tests as it is too unstable
This commit is contained in:
Philippe Martin
2022-05-16 13:45:22 +02:00
committed by GitHub
parent f287ba13e8
commit a26aa6a398
30 changed files with 1695 additions and 1469 deletions

View File

@@ -156,16 +156,14 @@ The `odo list` command returns information about components running on a specifi
The `components` field lists the components either deployed in the cluster, or defined in the local Devfile.
The `componentsInDevfile` field lists the names of components present in the `components` list that are defined in the local Devfile.
The `componentInDevfile` field gives the name of the component present in the `components` list that is defined in the local Devfile, or is empty if no local Devfile is present.
In this example, the `component2` component is running in Deploy mode, and the command has been executed from a directory containing a Devfile defining a `component1` component, not running.
```bash
$ odo list --namespace project1
{
"componentsInDevfile": [
"component1"
],
"componentInDevfile": "component1",
"components": [
{
"name": "component2",
@@ -183,5 +181,77 @@ $ odo list --namespace project1
}
]
}
```
## odo registry -o json
The `odo registry` command lists all the Devfile stacks from Devfile registries. You can get the available flag in the [registry command reference](registry.md).
The default output will return information found into the registry index for stacks:
```shell
$ odo registry -o json
[
{
"name": "python-django",
"displayName": "Django",
"description": "Python3.7 with Django",
"registry": {
"name": "DefaultDevfileRegistry",
"url": "https://registry.devfile.io",
"secure": false
},
"language": "python",
"tags": [
"Python",
"pip",
"Django"
],
"projectType": "django",
"version": "1.0.0",
"starterProjects": [
"django-example"
]
}, [...]
]
```
Using the `--details` flag, you will also get information about the Devfile:
```shell
$ odo registry --details -o json
[
{
"name": "python-django",
"displayName": "Django",
"description": "Python3.7 with Django",
"registry": {
"name": "DefaultDevfileRegistry",
"url": "https://registry.devfile.io",
"secure": false
},
"language": "python",
"tags": [
"Python",
"pip",
"Django"
],
"projectType": "django",
"version": "1.0.0",
"starterProjects": [
"django-example"
],
"devfileData": {
"devfile": {
"schemaVersion": "2.0.0",
[ devfile.yaml file content ]
},
"supportedOdoFeatures": {
"dev": true,
"deploy": false,
"debug": true
}
},
}, [...]
]
```

View File

@@ -0,0 +1,107 @@
---
title: odo registry
sidebar_position: 1
---
The `odo registry` command lists all the Devfile stacks from Devfile registries.
The Devfile registries that are taken into account are the registries added with the command
`odo preference registry`.
## Available Flags
By default, `odo registry` lists all the Devfile stacks from all the Devfile registries.
These flags let you filter the listed Devfile stacks:
* `--devfile <name>` to list the Devfile stacks with this exact name
* `--devfile-registry <name>` to list the Devfile stack of this registry (this is the `name` used
when adding the registry to the preferences with `odo preference registry add <name> <url>`)
* `--filter <term>` to list the Devfile for which the term is found in the devfile name or description
By default, the name, registry and description
of the Devfile stacks are displayed on a table.
This flag lets you change the content of the output:
* `--details` to display details about the Devfile stacks
* `-o json` to output the information in a JSON format
## Examples
For these examples, we consider we have two registries in our preferences:
```
shell
$ odo preference registry list
NAME URL SECURE
Staging https://registry.stage.devfile.io No
DefaultDevfileRegistry https://registry.devfile.io No
```
To get the complete list of accessible Devfile stacks:
```shell
$ odo registry
NAME REGISTRY DESCRIPTION
dotnet50 Staging Stack with .NET 5.0
dotnet50 DefaultDevfileRegistry Stack with .NET 5.0
dotnet60 Staging Stack with .NET 6.0
dotnet60 DefaultDevfileRegistry Stack with .NET 6.0
dotnetcore31 Staging Stack with .NET Core 3.1
dotnetcore31 DefaultDevfileRegistry Stack with .NET Core 3.1
go Staging Stack with the latest Go version
go DefaultDevfileRegistry Stack with the latest Go version
java-maven Staging Upstream Maven and OpenJDK 11
java-maven DefaultDevfileRegistry Upstream Maven and OpenJDK 11
[...]
```
To list the Devfile stacks from the Staging registry only:
```shell
$ odo registry --devfile-registry Staging
NAME REGISTRY DESCRIPTION
dotnet50 Staging Stack with .NET 5.0
dotnet60 Staging Stack with .NET 6.0
dotnetcore31 Staging Stack with .NET Core 3.1
go Staging Stack with the latest Go version
java-maven Staging Upstream Maven and OpenJDK 11
[...]
```
To list the Devfile stacks related to Maven:
```shell
$ odo registry --filter Maven
NAME REGISTRY DESCRIPTION
java-maven Staging Upstream Maven and OpenJDK 11
java-maven DefaultDevfileRegistry Upstream Maven and OpenJDK 11
java-openliberty Staging Java application Maven-built stack using...
java-openliberty DefaultDevfileRegistry Java application Maven-built stack using...
java-websphereliberty Staging Java application Maven-built stack using...
java-websphereliberty DefaultDevfileRegistry Java application Maven-built stack using...
java-wildfly-bootable-jar Staging Java stack with WildFly in bootable Jar ...
java-wildfly-bootable-jar DefaultDevfileRegistry Java stack with WildFly in bootable Jar ...
```
To get the details of the `java-maven` Devfile in the Staging registry:
```shell
$ odo registry --devfile java-maven --devfile-registry Staging --details
Name: java-maven
Display Name: Maven Java
Registry: Staging
Registry URL: https://registry.stage.devfile.io
Version: 1.1.0
Description: Upstream Maven and OpenJDK 11
Tags: Java, Maven
Project Type: maven
Language: java
Starter Projects:
- springbootproject
Supported odo Features:
- Dev: Y
- Deploy: N
- Debug: Y
```

View File

@@ -20,11 +20,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(path string) (recognizer.DevFileType, registry.Registry, error) {
func (o *Alizer) DetectFramework(path string) (recognizer.DevFileType, api.Registry, error) {
types := []recognizer.DevFileType{}
components, err := o.registryClient.ListDevfileStacks("", "", "", false)
if err != nil {
return recognizer.DevFileType{}, registry.Registry{}, err
return recognizer.DevFileType{}, api.Registry{}, err
}
for _, component := range components.Items {
types = append(types, recognizer.DevFileType{
@@ -36,7 +36,7 @@ func (o *Alizer) DetectFramework(path string) (recognizer.DevFileType, registry.
}
typ, err := recognizer.SelectDevFileFromTypes(path, types)
if err != nil {
return recognizer.DevFileType{}, registry.Registry{}, err
return recognizer.DevFileType{}, api.Registry{}, err
}
// TODO(feloy): This part won't be necessary when SelectDevFileFromTypes returns the index
@@ -51,7 +51,7 @@ func (o *Alizer) DetectFramework(path string) (recognizer.DevFileType, registry.
return typ, registry, nil
}
func GetDevfileLocationFromDetection(typ recognizer.DevFileType, registry registry.Registry) *api.DevfileLocation {
func GetDevfileLocationFromDetection(typ recognizer.DevFileType, registry api.Registry) *api.DevfileLocation {
return &api.DevfileLocation{
Devfile: typ.Name,
DevfileRegistry: registry.Name,

View File

@@ -6,6 +6,7 @@ import (
"testing"
"github.com/golang/mock/gomock"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/registry"
)
@@ -17,13 +18,13 @@ func GetTestProjectPath(folder string) string {
return filepath.Join(basepath, "..", "..", "tests/examples/source/", folder)
}
var types = []registry.DevfileStack{
var types = []api.DevfileStack{
{
Name: "java-maven",
Language: "java",
ProjectType: "maven",
Tags: []string{"Java", "Maven"},
Registry: registry.Registry{
Registry: api.Registry{
Name: "registry1",
},
},
@@ -32,7 +33,7 @@ var types = []registry.DevfileStack{
Language: "java",
ProjectType: "quarkus",
Tags: []string{"Java", "Quarkus"},
Registry: registry.Registry{
Registry: api.Registry{
Name: "registry1",
},
},
@@ -41,7 +42,7 @@ var types = []registry.DevfileStack{
Language: "java",
ProjectType: "wildfly",
Tags: []string{"Java", "WildFly"},
Registry: registry.Registry{
Registry: api.Registry{
Name: "registry2",
},
},
@@ -50,7 +51,7 @@ var types = []registry.DevfileStack{
Language: "javascript",
ProjectType: "nodejs",
Tags: []string{"NodeJS", "Express", "ubi8"},
Registry: registry.Registry{
Registry: api.Registry{
Name: "registry2",
},
},
@@ -59,7 +60,7 @@ var types = []registry.DevfileStack{
Language: "python",
ProjectType: "python",
Tags: []string{"Python", "pip"},
Registry: registry.Registry{
Registry: api.Registry{
Name: "registry3",
},
},

View File

@@ -2,9 +2,9 @@ package alizer
import (
"github.com/redhat-developer/alizer/go/pkg/apis/recognizer"
"github.com/redhat-developer/odo/pkg/registry"
"github.com/redhat-developer/odo/pkg/api"
)
type Client interface {
DetectFramework(path string) (recognizer.DevFileType, registry.Registry, error)
DetectFramework(path string) (recognizer.DevFileType, api.Registry, error)
}

View File

@@ -9,7 +9,7 @@ import (
gomock "github.com/golang/mock/gomock"
recognizer "github.com/redhat-developer/alizer/go/pkg/apis/recognizer"
registry "github.com/redhat-developer/odo/pkg/registry"
api "github.com/redhat-developer/odo/pkg/api"
)
// MockClient is a mock of Client interface.
@@ -36,11 +36,11 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
}
// DetectFramework mocks base method.
func (m *MockClient) DetectFramework(path string) (recognizer.DevFileType, registry.Registry, error) {
func (m *MockClient) DetectFramework(path string) (recognizer.DevFileType, api.Registry, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DetectFramework", path)
ret0, _ := ret[0].(recognizer.DevFileType)
ret1, _ := ret[1].(registry.Registry)
ret1, _ := ret[1].(api.Registry)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}

24
pkg/api/registry.go Normal file
View File

@@ -0,0 +1,24 @@
package api
// Registry is the main struct of devfile registry
type Registry struct {
Name string `json:"name"`
URL string `json:"url"`
Secure bool `json:"secure"`
// Priority of the registry for listing purposes. The higher the number, the higher the priority
Priority int `json:"-"`
}
// DevfileStack is the main struct for devfile stack
type DevfileStack struct {
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Registry Registry `json:"registry"`
Language string `json:"language"`
Tags []string `json:"tags"`
ProjectType string `json:"projectType"`
Version string `json:"version"`
StarterProjects []string `json:"starterProjects"`
DevfileData *DevfileData `json:"devfileData,omitempty"`
}

View File

@@ -5,79 +5,36 @@
package backend
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
reflect "reflect"
)
// MockAddBindingBackend is a mock of AddBindingBackend interface
// MockAddBindingBackend is a mock of AddBindingBackend interface.
type MockAddBindingBackend struct {
ctrl *gomock.Controller
recorder *MockAddBindingBackendMockRecorder
}
// MockAddBindingBackendMockRecorder is the mock recorder for MockAddBindingBackend
// MockAddBindingBackendMockRecorder is the mock recorder for MockAddBindingBackend.
type MockAddBindingBackendMockRecorder struct {
mock *MockAddBindingBackend
}
// NewMockAddBindingBackend creates a new mock instance
// NewMockAddBindingBackend creates a new mock instance.
func NewMockAddBindingBackend(ctrl *gomock.Controller) *MockAddBindingBackend {
mock := &MockAddBindingBackend{ctrl: ctrl}
mock.recorder = &MockAddBindingBackendMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockAddBindingBackend) EXPECT() *MockAddBindingBackendMockRecorder {
return m.recorder
}
// Validate mocks base method
func (m *MockAddBindingBackend) Validate(flags map[string]string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validate", flags)
ret0, _ := ret[0].(error)
return ret0
}
// Validate indicates an expected call of Validate
func (mr *MockAddBindingBackendMockRecorder) Validate(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockAddBindingBackend)(nil).Validate), flags)
}
// SelectServiceInstance mocks base method
func (m *MockAddBindingBackend) SelectServiceInstance(serviceName string, serviceMap map[string]unstructured.Unstructured) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SelectServiceInstance", serviceName, serviceMap)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SelectServiceInstance indicates an expected call of SelectServiceInstance
func (mr *MockAddBindingBackendMockRecorder) SelectServiceInstance(serviceName, serviceMap interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectServiceInstance", reflect.TypeOf((*MockAddBindingBackend)(nil).SelectServiceInstance), serviceName, serviceMap)
}
// AskBindingName mocks base method
func (m *MockAddBindingBackend) AskBindingName(defaultName string, flags map[string]string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindingName", defaultName, flags)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AskBindingName indicates an expected call of AskBindingName
func (mr *MockAddBindingBackendMockRecorder) AskBindingName(defaultName, flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindingName", reflect.TypeOf((*MockAddBindingBackend)(nil).AskBindingName), defaultName, flags)
}
// AskBindAsFiles mocks base method
// AskBindAsFiles mocks base method.
func (m *MockAddBindingBackend) AskBindAsFiles(flags map[string]string) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindAsFiles", flags)
@@ -86,8 +43,52 @@ func (m *MockAddBindingBackend) AskBindAsFiles(flags map[string]string) (bool, e
return ret0, ret1
}
// AskBindAsFiles indicates an expected call of AskBindAsFiles
// AskBindAsFiles indicates an expected call of AskBindAsFiles.
func (mr *MockAddBindingBackendMockRecorder) AskBindAsFiles(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindAsFiles", reflect.TypeOf((*MockAddBindingBackend)(nil).AskBindAsFiles), flags)
}
// AskBindingName mocks base method.
func (m *MockAddBindingBackend) AskBindingName(defaultName string, flags map[string]string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindingName", defaultName, flags)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AskBindingName indicates an expected call of AskBindingName.
func (mr *MockAddBindingBackendMockRecorder) AskBindingName(defaultName, flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindingName", reflect.TypeOf((*MockAddBindingBackend)(nil).AskBindingName), defaultName, flags)
}
// SelectServiceInstance mocks base method.
func (m *MockAddBindingBackend) SelectServiceInstance(serviceName string, serviceMap map[string]unstructured.Unstructured) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SelectServiceInstance", serviceName, serviceMap)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SelectServiceInstance indicates an expected call of SelectServiceInstance.
func (mr *MockAddBindingBackendMockRecorder) SelectServiceInstance(serviceName, serviceMap interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectServiceInstance", reflect.TypeOf((*MockAddBindingBackend)(nil).SelectServiceInstance), serviceName, serviceMap)
}
// Validate mocks base method.
func (m *MockAddBindingBackend) Validate(flags map[string]string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validate", flags)
ret0, _ := ret[0].(error)
return ret0
}
// Validate indicates an expected call of Validate.
func (mr *MockAddBindingBackendMockRecorder) Validate(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockAddBindingBackend)(nil).Validate), flags)
}

View File

@@ -5,109 +5,37 @@
package binding
import (
reflect "reflect"
parser "github.com/devfile/library/pkg/devfile/parser"
gomock "github.com/golang/mock/gomock"
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
reflect "reflect"
)
// MockClient is a mock of Client interface
// MockClient is a mock of Client interface.
type MockClient struct {
ctrl *gomock.Controller
recorder *MockClientMockRecorder
}
// MockClientMockRecorder is the mock recorder for MockClient
// MockClientMockRecorder is the mock recorder for MockClient.
type MockClientMockRecorder struct {
mock *MockClient
}
// NewMockClient creates a new mock instance
// NewMockClient creates a new mock instance.
func NewMockClient(ctrl *gomock.Controller) *MockClient {
mock := &MockClient{ctrl: ctrl}
mock.recorder = &MockClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockClient) EXPECT() *MockClientMockRecorder {
return m.recorder
}
// GetFlags mocks base method
func (m *MockClient) GetFlags(flags map[string]string) map[string]string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetFlags", flags)
ret0, _ := ret[0].(map[string]string)
return ret0
}
// GetFlags indicates an expected call of GetFlags
func (mr *MockClientMockRecorder) GetFlags(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlags", reflect.TypeOf((*MockClient)(nil).GetFlags), flags)
}
// Validate mocks base method
func (m *MockClient) Validate(flags map[string]string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validate", flags)
ret0, _ := ret[0].(error)
return ret0
}
// Validate indicates an expected call of Validate
func (mr *MockClientMockRecorder) Validate(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockClient)(nil).Validate), flags)
}
// SelectServiceInstance mocks base method
func (m *MockClient) SelectServiceInstance(flags map[string]string, serviceMap map[string]unstructured.Unstructured) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SelectServiceInstance", flags, serviceMap)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SelectServiceInstance indicates an expected call of SelectServiceInstance
func (mr *MockClientMockRecorder) SelectServiceInstance(flags, serviceMap interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectServiceInstance", reflect.TypeOf((*MockClient)(nil).SelectServiceInstance), flags, serviceMap)
}
// AskBindingName mocks base method
func (m *MockClient) AskBindingName(serviceName, componentName string, flags map[string]string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindingName", serviceName, componentName, flags)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AskBindingName indicates an expected call of AskBindingName
func (mr *MockClientMockRecorder) AskBindingName(serviceName, componentName, flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindingName", reflect.TypeOf((*MockClient)(nil).AskBindingName), serviceName, componentName, flags)
}
// AskBindAsFiles mocks base method
func (m *MockClient) AskBindAsFiles(flags map[string]string) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindAsFiles", flags)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AskBindAsFiles indicates an expected call of AskBindAsFiles
func (mr *MockClientMockRecorder) AskBindAsFiles(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindAsFiles", reflect.TypeOf((*MockClient)(nil).AskBindAsFiles), flags)
}
// AddBinding mocks base method
// AddBinding mocks base method.
func (m *MockClient) AddBinding(bindingName string, bindAsFiles bool, unstructuredService unstructured.Unstructured, obj parser.DevfileObj, componentContext string) (parser.DevfileObj, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddBinding", bindingName, bindAsFiles, unstructuredService, obj, componentContext)
@@ -116,13 +44,57 @@ func (m *MockClient) AddBinding(bindingName string, bindAsFiles bool, unstructur
return ret0, ret1
}
// AddBinding indicates an expected call of AddBinding
// AddBinding indicates an expected call of AddBinding.
func (mr *MockClientMockRecorder) AddBinding(bindingName, bindAsFiles, unstructuredService, obj, componentContext interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBinding", reflect.TypeOf((*MockClient)(nil).AddBinding), bindingName, bindAsFiles, unstructuredService, obj, componentContext)
}
// GetServiceInstances mocks base method
// AskBindAsFiles mocks base method.
func (m *MockClient) AskBindAsFiles(flags map[string]string) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindAsFiles", flags)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AskBindAsFiles indicates an expected call of AskBindAsFiles.
func (mr *MockClientMockRecorder) AskBindAsFiles(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindAsFiles", reflect.TypeOf((*MockClient)(nil).AskBindAsFiles), flags)
}
// AskBindingName mocks base method.
func (m *MockClient) AskBindingName(serviceName, componentName string, flags map[string]string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskBindingName", serviceName, componentName, flags)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AskBindingName indicates an expected call of AskBindingName.
func (mr *MockClientMockRecorder) AskBindingName(serviceName, componentName, flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskBindingName", reflect.TypeOf((*MockClient)(nil).AskBindingName), serviceName, componentName, flags)
}
// GetFlags mocks base method.
func (m *MockClient) GetFlags(flags map[string]string) map[string]string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetFlags", flags)
ret0, _ := ret[0].(map[string]string)
return ret0
}
// GetFlags indicates an expected call of GetFlags.
func (mr *MockClientMockRecorder) GetFlags(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlags", reflect.TypeOf((*MockClient)(nil).GetFlags), flags)
}
// GetServiceInstances mocks base method.
func (m *MockClient) GetServiceInstances() (map[string]unstructured.Unstructured, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceInstances")
@@ -131,8 +103,37 @@ func (m *MockClient) GetServiceInstances() (map[string]unstructured.Unstructured
return ret0, ret1
}
// GetServiceInstances indicates an expected call of GetServiceInstances
// GetServiceInstances indicates an expected call of GetServiceInstances.
func (mr *MockClientMockRecorder) GetServiceInstances() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceInstances", reflect.TypeOf((*MockClient)(nil).GetServiceInstances))
}
// SelectServiceInstance mocks base method.
func (m *MockClient) SelectServiceInstance(flags map[string]string, serviceMap map[string]unstructured.Unstructured) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SelectServiceInstance", flags, serviceMap)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SelectServiceInstance indicates an expected call of SelectServiceInstance.
func (mr *MockClientMockRecorder) SelectServiceInstance(flags, serviceMap interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectServiceInstance", reflect.TypeOf((*MockClient)(nil).SelectServiceInstance), flags, serviceMap)
}
// Validate mocks base method.
func (m *MockClient) Validate(flags map[string]string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validate", flags)
ret0, _ := ret[0].(error)
return ret0
}
// Validate indicates an expected call of Validate.
func (mr *MockClientMockRecorder) Validate(flags interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockClient)(nil).Validate), flags)
}

View File

@@ -40,31 +40,31 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
}
// Start mocks base method.
func (m *MockClient) Start(devfileObj parser.DevfileObj, platformContext kubernetes.KubernetesContext, ignorePaths []string, path string) error {
func (m *MockClient) Start(devfileObj parser.DevfileObj, platformContext kubernetes.KubernetesContext, ignorePaths []string, path string, debug bool) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Start", devfileObj, platformContext, ignorePaths, path)
ret := m.ctrl.Call(m, "Start", devfileObj, platformContext, ignorePaths, path, debug)
ret0, _ := ret[0].(error)
return ret0
}
// Start indicates an expected call of Start.
func (mr *MockClientMockRecorder) Start(devfileObj, platformContext, ignorePaths, path interface{}) *gomock.Call {
func (mr *MockClientMockRecorder) Start(devfileObj, platformContext, ignorePaths, path, debug interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockClient)(nil).Start), devfileObj, platformContext, ignorePaths, path)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockClient)(nil).Start), devfileObj, platformContext, ignorePaths, path, debug)
}
// Watch mocks base method.
func (m *MockClient) Watch(devfileObj parser.DevfileObj, path string, ignorePaths []string, out io.Writer, h Handler, ctx context.Context) error {
func (m *MockClient) Watch(devfileObj parser.DevfileObj, path string, ignorePaths []string, out io.Writer, h Handler, ctx context.Context, debug bool) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Watch", devfileObj, path, ignorePaths, out, h, ctx)
ret := m.ctrl.Call(m, "Watch", devfileObj, path, ignorePaths, out, h, ctx, debug)
ret0, _ := ret[0].(error)
return ret0
}
// Watch indicates an expected call of Watch.
func (mr *MockClientMockRecorder) Watch(devfileObj, path, ignorePaths, out, h, ctx interface{}) *gomock.Call {
func (mr *MockClientMockRecorder) Watch(devfileObj, path, ignorePaths, out, h, ctx, debug interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockClient)(nil).Watch), devfileObj, path, ignorePaths, out, h, ctx)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockClient)(nil).Watch), devfileObj, path, ignorePaths, out, h, ctx, debug)
}
// MockHandler is a mock of Handler interface.

View File

@@ -5,6 +5,7 @@ import (
"sort"
"github.com/AlecAivazis/survey/v2"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/registry"
)
@@ -29,7 +30,7 @@ func (o *Survey) AskLanguage(langs []string) (string, error) {
return answer, nil
}
func (o *Survey) AskType(types registry.TypesWithDetails) (back bool, _ registry.DevfileStack, _ error) {
func (o *Survey) AskType(types registry.TypesWithDetails) (back bool, _ api.DevfileStack, _ error) {
stringTypes := types.GetOrderedLabels()
stringTypes = append(stringTypes, "** GO BACK **")
question := &survey.Select{
@@ -39,10 +40,10 @@ func (o *Survey) AskType(types registry.TypesWithDetails) (back bool, _ registry
var answerPos int
err := survey.AskOne(question, &answerPos)
if err != nil {
return false, registry.DevfileStack{}, err
return false, api.DevfileStack{}, err
}
if answerPos == len(stringTypes)-1 {
return true, registry.DevfileStack{}, nil
return true, api.DevfileStack{}, nil
}
compType, err := types.GetAtOrderedPosition(answerPos)
return false, compType, err

View File

@@ -3,6 +3,7 @@
package asker
import (
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/registry"
)
@@ -13,7 +14,7 @@ type Asker interface {
// 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
AskType(types registry.TypesWithDetails) (back bool, _ registry.DevfileStack, _ error)
AskType(types registry.TypesWithDetails) (back bool, _ api.DevfileStack, _ error)
// AskStarterProject asks for an optional project, from a list of projects. If no project is selected, false is returned.
// Or the index of the selected project is returned

View File

@@ -8,6 +8,7 @@ import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
api "github.com/redhat-developer/odo/pkg/api"
registry "github.com/redhat-developer/odo/pkg/registry"
)
@@ -157,11 +158,11 @@ func (mr *MockAskerMockRecorder) AskStarterProject(projects interface{}) *gomock
}
// AskType mocks base method.
func (m *MockAsker) AskType(types registry.TypesWithDetails) (bool, registry.DevfileStack, error) {
func (m *MockAsker) AskType(types registry.TypesWithDetails) (bool, api.DevfileStack, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AskType", types)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(registry.DevfileStack)
ret1, _ := ret[1].(api.DevfileStack)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/redhat-developer/odo/pkg/alizer"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/init/asker"
"github.com/redhat-developer/odo/pkg/registry"
"github.com/redhat-developer/odo/pkg/testingutil/filesystem"
)
@@ -52,7 +51,7 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
alizerClient := alizer.NewMockClient(ctrl)
alizerClient.EXPECT().DetectFramework(gomock.Any()).Return(recognizer.DevFileType{
Name: "a-devfile-name",
}, registry.Registry{
}, api.Registry{
Name: "a-registry",
}, nil)
return alizerClient
@@ -77,7 +76,7 @@ func TestAlizerBackend_SelectDevfile(t *testing.T) {
},
alizerClient: func(ctrl *gomock.Controller) alizer.Client {
alizerClient := alizer.NewMockClient(ctrl)
alizerClient.EXPECT().DetectFramework(gomock.Any()).Return(recognizer.DevFileType{}, registry.Registry{}, nil)
alizerClient.EXPECT().DetectFramework(gomock.Any()).Return(recognizer.DevFileType{}, api.Registry{}, nil)
return alizerClient
},
},

View File

@@ -48,7 +48,7 @@ func (o *InteractiveBackend) SelectDevfile(flags map[string]string, _ filesystem
state := STATE_ASK_LANG
var lang string
var err error
var details registry.DevfileStack
var details api.DevfileStack
loop:
for {
switch state {

View File

@@ -35,9 +35,9 @@ func TestInteractiveBackend_SelectDevfile(t *testing.T) {
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
client := asker.NewMockAsker(ctrl)
client.EXPECT().AskLanguage(gomock.Any()).Return("java", nil)
client.EXPECT().AskType(gomock.Any()).Return(false, registry.DevfileStack{
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
Name: "a-devfile-name",
Registry: registry.Registry{
Registry: api.Registry{
Name: "MyRegistry1",
},
}, nil)
@@ -60,11 +60,11 @@ func TestInteractiveBackend_SelectDevfile(t *testing.T) {
buildAsker: func(ctrl *gomock.Controller) asker.Asker {
client := asker.NewMockAsker(ctrl)
client.EXPECT().AskLanguage(gomock.Any()).Return("java", nil)
client.EXPECT().AskType(gomock.Any()).Return(true, registry.DevfileStack{}, nil)
client.EXPECT().AskType(gomock.Any()).Return(true, api.DevfileStack{}, nil)
client.EXPECT().AskLanguage(gomock.Any()).Return("go", nil)
client.EXPECT().AskType(gomock.Any()).Return(false, registry.DevfileStack{
client.EXPECT().AskType(gomock.Any()).Return(false, api.DevfileStack{
Name: "a-devfile-name",
Registry: registry.Registry{
Registry: api.Registry{
Name: "MyRegistry1",
},
}, nil)

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,9 @@ import (
"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/machineoutput"
"github.com/redhat-developer/odo/pkg/odo/cmdline"
"github.com/redhat-developer/odo/pkg/odo/genericclioptions"
"github.com/redhat-developer/odo/pkg/odo/genericclioptions/clientset"
@@ -65,15 +67,18 @@ func (o *ListOptions) Complete(cmdline cmdline.Cmdline, args []string) (err erro
return err
}
if o.devfileList.DevfileRegistries == nil {
log.Warning("Please run 'odo preference registry add <registry name> <registry URL>' to add registry for listing devfile components\n")
}
return nil
}
// Validate validates the ListOptions based on completed values
func (o *ListOptions) Validate() error {
if o.devfileList.DevfileRegistries == nil {
if len(o.registryFlag) > 0 {
return fmt.Errorf("the registry %q is not in preferences", o.registryFlag)
}
return fmt.Errorf("no registry in preferences, please add a registry using 'odo preference registry add' command")
}
if len(o.devfileList.Items) == 0 {
return fmt.Errorf("no deployable components found")
}
@@ -86,6 +91,11 @@ func (o *ListOptions) Run(ctx context.Context) (err error) {
return nil
}
// Run contains the logic for the command associated with ListOptions
func (o *ListOptions) RunForJsonOutput(ctx context.Context) (out interface{}, err error) {
return o.devfileList.Items, nil
}
func NewCmdRegistry(name, fullName string) *cobra.Command {
o := NewListOptions()
@@ -102,7 +112,7 @@ func NewCmdRegistry(name, fullName string) *cobra.Command {
clientset.Add(listCmd, clientset.REGISTRY)
// Flags
listCmd.Flags().StringVar(&o.filterFlag, "filter", "", "Filter based on the name of the component")
listCmd.Flags().StringVar(&o.filterFlag, "filter", "", "Filter based on the name or description of the 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().BoolVar(&o.detailsFlag, "details", false, "Show details of each component")
@@ -111,10 +121,11 @@ func NewCmdRegistry(name, fullName string) *cobra.Command {
listCmd.Annotations["command"] = "main"
listCmd.SetUsageTemplate(odoutil.CmdUsageTemplate)
machineoutput.UsedByCommand(listCmd)
return listCmd
}
func (o *ListOptions) printDevfileList(DevfileList []registry.DevfileStack) {
func (o *ListOptions) printDevfileList(DevfileList []api.DevfileStack) {
// Create the table and use our own style
t := table.NewWriter()
@@ -178,9 +189,9 @@ func (o *ListOptions) printDevfileList(DevfileList []registry.DevfileStack) {
log.Sbold("Language"), devfileComponent.Language,
log.Sbold("Starter Projects"), strings.Join(devfileComponent.StarterProjects, "\n - "),
log.Sbold("Supported odo Features"),
boolToYesNo(devfileComponent.SupportedOdoFeatures.Dev),
boolToYesNo(devfileComponent.SupportedOdoFeatures.Deploy),
boolToYesNo(devfileComponent.SupportedOdoFeatures.Debug),
boolToYesNo(devfileComponent.DevfileData.SupportedOdoFeatures.Dev),
boolToYesNo(devfileComponent.DevfileData.SupportedOdoFeatures.Deploy),
boolToYesNo(devfileComponent.DevfileData.SupportedOdoFeatures.Debug),
"\n")
} else {
// Create a simplified row only showing the name, registry and description.

View File

@@ -1,6 +1,10 @@
package registry
import "sort"
import (
"sort"
"github.com/redhat-developer/odo/pkg/api"
)
// GetLanguages returns the list of unique languages, ordered by name,
// from a list of registry items
@@ -27,7 +31,7 @@ func (o *DevfileStackList) GetProjectTypes(language string) TypesWithDetails {
continue
}
if _, found := types[item.DisplayName]; !found {
types[item.DisplayName] = []DevfileStack{}
types[item.DisplayName] = []api.DevfileStack{}
}
types[item.DisplayName] = append(types[item.DisplayName], item)
}

View File

@@ -3,11 +3,13 @@ package registry
import (
"reflect"
"testing"
"github.com/redhat-developer/odo/pkg/api"
)
func TestDevfileStackList_GetLanguages(t *testing.T) {
type fields struct {
Items []DevfileStack
Items []api.DevfileStack
}
tests := []struct {
name string
@@ -21,11 +23,11 @@ func TestDevfileStackList_GetLanguages(t *testing.T) {
{
name: "some devfiles",
fields: fields{
Items: []DevfileStack{
Items: []api.DevfileStack{
{
Name: "devfile4",
DisplayName: "first devfile for lang3",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang3",
@@ -33,7 +35,7 @@ func TestDevfileStackList_GetLanguages(t *testing.T) {
{
Name: "devfile1",
DisplayName: "first devfile for lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
Language: "lang1",
@@ -41,7 +43,7 @@ func TestDevfileStackList_GetLanguages(t *testing.T) {
{
Name: "devfile3",
DisplayName: "another devfile for lang2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang2",
@@ -49,7 +51,7 @@ func TestDevfileStackList_GetLanguages(t *testing.T) {
{
Name: "devfile2",
DisplayName: "second devfile for lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang1",
@@ -73,7 +75,7 @@ func TestDevfileStackList_GetLanguages(t *testing.T) {
func TestDevfileStackList_GetProjectTypes(t *testing.T) {
type fields struct {
Items []DevfileStack
Items []api.DevfileStack
}
type args struct {
language string
@@ -91,11 +93,11 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
{
name: "project types for lang1",
fields: fields{
Items: []DevfileStack{
Items: []api.DevfileStack{
{
Name: "devfile4",
DisplayName: "first devfile for lang3",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang3",
@@ -103,7 +105,7 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
{
Name: "devfile1",
DisplayName: "first devfile for lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang1",
@@ -111,7 +113,7 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
{
Name: "devfile1",
DisplayName: "first devfile for lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
Language: "lang1",
@@ -119,7 +121,7 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
{
Name: "devfile3",
DisplayName: "another devfile for lang2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang2",
@@ -127,7 +129,7 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
{
Name: "devfile2",
DisplayName: "second devfile for lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
Language: "lang1",
@@ -138,12 +140,12 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
language: "lang1",
},
want: TypesWithDetails{
"first devfile for lang1": []DevfileStack{
"first devfile for lang1": []api.DevfileStack{
{
Name: "devfile1",
DisplayName: "first devfile for lang1",
Language: "lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
@@ -151,17 +153,17 @@ func TestDevfileStackList_GetProjectTypes(t *testing.T) {
Name: "devfile1",
DisplayName: "first devfile for lang1",
Language: "lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
},
"second devfile for lang1": []DevfileStack{
"second devfile for lang1": []api.DevfileStack{
{
Name: "devfile2",
DisplayName: "second devfile for lang1",
Language: "lang1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},

View File

@@ -5,12 +5,13 @@ import (
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
dfutil "github.com/devfile/library/pkg/util"
"github.com/devfile/registry-support/registry-library/library"
"github.com/redhat-developer/odo/pkg/api"
)
type Client interface {
PullStackFromRegistry(registry string, stack string, destDir string, options library.RegistryOptions) error
DownloadFileInMemory(params dfutil.HTTPRequestParams) ([]byte, error)
DownloadStarterProject(starterProject *devfilev1.StarterProject, decryptedToken string, contextDir string, verbose bool) error
GetDevfileRegistries(registryName string) ([]Registry, error)
GetDevfileRegistries(registryName string) ([]api.Registry, error)
ListDevfileStacks(registryName, devfileFlag, filterFlag string, detailsFlag bool) (DevfileStackList, error)
}

View File

@@ -11,6 +11,7 @@ import (
util "github.com/devfile/library/pkg/util"
library "github.com/devfile/registry-support/registry-library/library"
gomock "github.com/golang/mock/gomock"
api "github.com/redhat-developer/odo/pkg/api"
)
// MockClient is a mock of Client interface.
@@ -66,10 +67,10 @@ func (mr *MockClientMockRecorder) DownloadStarterProject(starterProject, decrypt
}
// GetDevfileRegistries mocks base method.
func (m *MockClient) GetDevfileRegistries(registryName string) ([]Registry, error) {
func (m *MockClient) GetDevfileRegistries(registryName string) ([]api.Registry, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDevfileRegistries", registryName)
ret0, _ := ret[0].([]Registry)
ret0, _ := ret[0].([]api.Registry)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -81,18 +82,18 @@ func (mr *MockClientMockRecorder) GetDevfileRegistries(registryName interface{})
}
// ListDevfileStacks mocks base method.
func (m *MockClient) ListDevfileStacks(registryName, devfileName, filter string, detailsFlag bool) (DevfileStackList, error) {
func (m *MockClient) ListDevfileStacks(registryName, devfileFlag, filterFlag string, detailsFlag bool) (DevfileStackList, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListDevfileStacks", registryName, devfileName, filter, detailsFlag)
ret := m.ctrl.Call(m, "ListDevfileStacks", registryName, devfileFlag, filterFlag, detailsFlag)
ret0, _ := ret[0].(DevfileStackList)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListDevfileStacks indicates an expected call of ListDevfileStacks.
func (mr *MockClientMockRecorder) ListDevfileStacks(registryName, devfileName, filter, detailsFlag interface{}) *gomock.Call {
func (mr *MockClientMockRecorder) ListDevfileStacks(registryName, devfileFlag, filterFlag, detailsFlag interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListDevfileStacks", reflect.TypeOf((*MockClient)(nil).ListDevfileStacks), registryName, devfileName, filter, detailsFlag)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListDevfileStacks", reflect.TypeOf((*MockClient)(nil).ListDevfileStacks), registryName, devfileFlag, filterFlag, detailsFlag)
}
// PullStackFromRegistry mocks base method.

View File

@@ -56,8 +56,8 @@ func (o RegistryClient) DownloadStarterProject(starterProject *devfilev1.Starter
// GetDevfileRegistries gets devfile registries from preference file,
// if registry name is specified return the specific registry, otherwise return all registries
func (o RegistryClient) GetDevfileRegistries(registryName string) ([]Registry, error) {
var devfileRegistries []Registry
func (o RegistryClient) GetDevfileRegistries(registryName string) ([]api.Registry, error) {
var devfileRegistries []api.Registry
hasName := len(registryName) != 0
if o.preferenceClient.RegistryList() != nil {
@@ -67,7 +67,7 @@ func (o RegistryClient) GetDevfileRegistries(registryName string) ([]Registry, e
registry := registryList[i]
if hasName {
if registryName == registry.Name {
reg := Registry{
reg := api.Registry{
Name: registry.Name,
URL: registry.URL,
Secure: registry.Secure,
@@ -76,7 +76,7 @@ func (o RegistryClient) GetDevfileRegistries(registryName string) ([]Registry, e
return devfileRegistries, nil
}
} else {
reg := Registry{
reg := api.Registry{
Name: registry.Name,
URL: registry.URL,
Secure: registry.Secure,
@@ -112,7 +112,7 @@ func (o RegistryClient) ListDevfileStacks(registryName, devfileFlag, filterFlag
// The 2D slice index is the priority of the registry (highest priority has highest index)
// and the element is the devfile slice that belongs to the registry
registrySlice := make([][]DevfileStack, len(catalogDevfileList.DevfileRegistries))
registrySlice := make([][]api.DevfileStack, len(catalogDevfileList.DevfileRegistries))
for regPriority, reg := range catalogDevfileList.DevfileRegistries {
// Load the devfile registry index.json
registry := reg // Needed to prevent the lambda from capturing the value
@@ -141,7 +141,7 @@ func (o RegistryClient) ListDevfileStacks(registryName, devfileFlag, filterFlag
// manually http get) if the details flag has been passed in.
for priorityNumber, registryDevfiles := range registrySlice {
devfiles := []DevfileStack{}
devfiles := []api.DevfileStack{}
for _, devfile := range registryDevfiles {
@@ -165,7 +165,7 @@ func (o RegistryClient) ListDevfileStacks(registryName, devfileFlag, filterFlag
if err != nil {
return *catalogDevfileList, err
}
devfile.SupportedOdoFeatures = *devfileData.SupportedOdoFeatures
devfile.DevfileData = &devfileData
}
devfiles = append(devfiles, devfile)
@@ -188,7 +188,7 @@ func (o RegistryClient) ListDevfileStacks(registryName, devfileFlag, filterFlag
}
// getRegistryStacks retrieves the registry's index devfile stack entries
func getRegistryStacks(preferenceClient preference.Client, registry Registry) ([]DevfileStack, error) {
func getRegistryStacks(preferenceClient preference.Client, registry api.Registry) ([]api.DevfileStack, error) {
isGithubregistry, err := registryUtil.IsGithubBasedRegistry(registry.URL)
if err != nil {
return nil, err
@@ -204,14 +204,13 @@ func getRegistryStacks(preferenceClient preference.Client, registry Registry) ([
return createRegistryDevfiles(registry, devfileIndex)
}
func createRegistryDevfiles(registry Registry, devfileIndex []indexSchema.Schema) ([]DevfileStack, error) {
registryDevfiles := make([]DevfileStack, 0, len(devfileIndex))
func createRegistryDevfiles(registry api.Registry, devfileIndex []indexSchema.Schema) ([]api.DevfileStack, error) {
registryDevfiles := make([]api.DevfileStack, 0, len(devfileIndex))
for _, devfileIndexEntry := range devfileIndex {
stackDevfile := DevfileStack{
stackDevfile := api.DevfileStack{
Name: devfileIndexEntry.Name,
DisplayName: devfileIndexEntry.DisplayName,
Description: devfileIndexEntry.Description,
Link: devfileIndexEntry.Links["self"],
Registry: registry,
Language: devfileIndexEntry.Language,
Tags: devfileIndexEntry.Tags,

View File

@@ -10,6 +10,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/kylelemons/godebug/pretty"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/preference"
"github.com/redhat-developer/odo/pkg/testingutil/filesystem"
)
@@ -41,12 +42,12 @@ OdoSettings:
tests := []struct {
name string
registryName string
want []Registry
want []api.Registry
}{
{
name: "Case 1: Test get all devfile registries",
registryName: "",
want: []Registry{
want: []api.Registry{
{
Name: "CheDevfileRegistry",
URL: "https://che-devfile-registry.openshift.io/",
@@ -62,7 +63,7 @@ OdoSettings:
{
name: "Case 2: Test get specific devfile registry",
registryName: "CheDevfileRegistry",
want: []Registry{
want: []api.Registry{
{
Name: "CheDevfileRegistry",
URL: "https://che-devfile-registry.openshift.io/",
@@ -149,23 +150,22 @@ func TestListDevfileStacks(t *testing.T) {
name: "Case 1: Test getting ALL registries and looking for nodejs",
registryName: "",
want: DevfileStackList{
DevfileRegistries: []Registry{
DevfileRegistries: []api.Registry{
{
Name: "TestRegistry",
URL: server.URL,
Secure: false,
},
},
Items: []DevfileStack{
Items: []api.DevfileStack{
{
Name: "nodejs",
DisplayName: "NodeJS Angular Web Application",
Description: "Stack for developing NodeJS Angular Web Application",
Registry: Registry{
Registry: api.Registry{
Name: registryName,
URL: server.URL,
},
Link: "/devfiles/angular/devfile.yaml",
Language: "nodejs",
Tags: []string{"NodeJS", "Angular", "Alpine"},
},
@@ -173,11 +173,10 @@ func TestListDevfileStacks(t *testing.T) {
Name: "python",
DisplayName: "Python",
Description: "Python Stack with Python 3.7",
Registry: Registry{
Registry: api.Registry{
Name: registryName,
URL: server.URL,
},
Link: "/devfiles/python/devfile.yaml",
Language: "python",
Tags: []string{"Python", "pip"},
},
@@ -189,23 +188,22 @@ func TestListDevfileStacks(t *testing.T) {
registryName: "TestRegistry",
devfileName: "nodejs",
want: DevfileStackList{
DevfileRegistries: []Registry{
DevfileRegistries: []api.Registry{
{
Name: "TestRegistry",
URL: server.URL,
Secure: false,
},
},
Items: []DevfileStack{
Items: []api.DevfileStack{
{
Name: "nodejs",
DisplayName: "NodeJS Angular Web Application",
Description: "Stack for developing NodeJS Angular Web Application",
Registry: Registry{
Registry: api.Registry{
Name: registryName,
URL: server.URL,
},
Link: "/devfiles/angular/devfile.yaml",
Language: "nodejs",
Tags: []string{"NodeJS", "Angular", "Alpine"},
},
@@ -217,23 +215,22 @@ func TestListDevfileStacks(t *testing.T) {
registryName: "TestRegistry",
filter: "Python Stack",
want: DevfileStackList{
DevfileRegistries: []Registry{
DevfileRegistries: []api.Registry{
{
Name: "TestRegistry",
URL: server.URL,
Secure: false,
},
},
Items: []DevfileStack{
Items: []api.DevfileStack{
{
Name: "python",
DisplayName: "Python",
Description: "Python Stack with Python 3.7",
Registry: Registry{
Registry: api.Registry{
Name: registryName,
URL: server.URL,
},
Link: "/devfiles/python/devfile.yaml",
Language: "python",
Tags: []string{"Python", "pip"},
},
@@ -314,22 +311,21 @@ func TestGetRegistryDevfiles(t *testing.T) {
const registryName = "some registry"
tests := []struct {
name string
registry Registry
want []DevfileStack
registry api.Registry
want []api.DevfileStack
}{
{
name: "Test NodeJS devfile index",
registry: Registry{Name: registryName, URL: server.URL},
want: []DevfileStack{
registry: api.Registry{Name: registryName, URL: server.URL},
want: []api.DevfileStack{
{
Name: "nodejs",
DisplayName: "NodeJS Angular Web Application",
Description: "Stack for developing NodeJS Angular Web Application",
Registry: Registry{
Registry: api.Registry{
Name: registryName,
URL: server.URL,
},
Link: "/devfiles/angular/devfile.yaml",
Language: "nodejs",
Tags: []string{"NodeJS", "Angular", "Alpine"},
},

View File

@@ -2,34 +2,11 @@ package registry
import "github.com/redhat-developer/odo/pkg/api"
// Registry is the main struct of devfile registry
type Registry struct {
Name string
URL string
Secure bool
Priority int // The "priority" of the registry for listing purposes. The higher the number, the higher the priority
}
// DevfileStack is the main struct for devfile catalog components
type DevfileStack struct {
Name string
DisplayName string
Description string
Link string
Registry Registry
Language string
Tags []string
ProjectType string
Version string
StarterProjects []string
SupportedOdoFeatures api.SupportedOdoFeatures
}
// DevfileStackList lists all the Devfile Stacks
type DevfileStackList struct {
DevfileRegistries []Registry
Items []DevfileStack
DevfileRegistries []api.Registry
Items []api.DevfileStack
}
// TypesWithDetails is the list of project types in devfile registries, and their associated devfiles
type TypesWithDetails map[string][]DevfileStack
type TypesWithDetails map[string][]api.DevfileStack

View File

@@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"sort"
"github.com/redhat-developer/odo/pkg/api"
)
// GetOrderedLabels returns a list of labels for a list of project types
@@ -25,7 +27,7 @@ func (types TypesWithDetails) GetOrderedLabels() []string {
// GetAtOrderedPosition returns the project type at the given position,
// when the list of project types is ordered by GetOrderedLabels
func (types TypesWithDetails) GetAtOrderedPosition(pos int) (DevfileStack, error) {
func (types TypesWithDetails) GetAtOrderedPosition(pos int) (api.DevfileStack, error) {
sortedTypes := sortTypes(types)
for _, typ := range sortedTypes {
detailsList := types[typ]
@@ -35,7 +37,7 @@ func (types TypesWithDetails) GetAtOrderedPosition(pos int) (DevfileStack, error
}
return detailsList[pos], nil
}
return DevfileStack{}, errors.New("index not found")
return api.DevfileStack{}, errors.New("index not found")
}
func sortTypes(types TypesWithDetails) []string {

View File

@@ -3,6 +3,8 @@ package registry
import (
"reflect"
"testing"
"github.com/redhat-developer/odo/pkg/api"
)
func TestTypesWithDetails_GetOrderedLabels(t *testing.T) {
@@ -14,24 +16,24 @@ func TestTypesWithDetails_GetOrderedLabels(t *testing.T) {
{
name: "some entries",
types: TypesWithDetails{
"second devfile for lang1": []DevfileStack{
"second devfile for lang1": []api.DevfileStack{
{
Name: "devfile2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
},
"first devfile for lang1": []DevfileStack{
"first devfile for lang1": []api.DevfileStack{
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
@@ -61,30 +63,30 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
name string
types TypesWithDetails
args args
want DevfileStack
want api.DevfileStack
wantErr bool
}{
{
name: "get a pos 0",
types: TypesWithDetails{
"second devfile for lang1": []DevfileStack{
"second devfile for lang1": []api.DevfileStack{
{
Name: "devfile2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
},
"first devfile for lang1": []DevfileStack{
"first devfile for lang1": []api.DevfileStack{
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
@@ -93,9 +95,9 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
args: args{
pos: 0,
},
want: DevfileStack{
want: api.DevfileStack{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
@@ -104,24 +106,24 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
{
name: "get a pos 1",
types: TypesWithDetails{
"second devfile for lang1": []DevfileStack{
"second devfile for lang1": []api.DevfileStack{
{
Name: "devfile2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
},
"first devfile for lang1": []DevfileStack{
"first devfile for lang1": []api.DevfileStack{
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
@@ -130,9 +132,9 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
args: args{
pos: 1,
},
want: DevfileStack{
want: api.DevfileStack{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
@@ -141,24 +143,24 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
{
name: "get a pos 2",
types: TypesWithDetails{
"second devfile for lang1": []DevfileStack{
"second devfile for lang1": []api.DevfileStack{
{
Name: "devfile2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
},
"first devfile for lang1": []DevfileStack{
"first devfile for lang1": []api.DevfileStack{
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
@@ -167,9 +169,9 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
args: args{
pos: 2,
},
want: DevfileStack{
want: api.DevfileStack{
Name: "devfile2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
@@ -178,24 +180,24 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
{
name: "get a pos 4: not found",
types: TypesWithDetails{
"second devfile for lang1": []DevfileStack{
"second devfile for lang1": []api.DevfileStack{
{
Name: "devfile2",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
},
"first devfile for lang1": []DevfileStack{
"first devfile for lang1": []api.DevfileStack{
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry1",
},
},
{
Name: "devfile1",
Registry: Registry{
Registry: api.Registry{
Name: "Registry2",
},
},
@@ -204,7 +206,7 @@ func TestTypesWithDetails_GetAtOrderedPosition(t *testing.T) {
args: args{
pos: 4,
},
want: DevfileStack{},
want: api.DevfileStack{},
wantErr: true,
}}
for _, tt := range tests {

View File

@@ -160,7 +160,7 @@ func GetCliRunner() CliRunner {
// IsJSON returns true if a string is in json format
func IsJSON(s string) bool {
var js map[string]interface{}
var js interface{}
return json.Unmarshal([]byte(s), &js) == nil
}

View File

@@ -125,7 +125,7 @@ var _ = Describe("odo devfile init command tests", func() {
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "devfilePath", filepath.Join(commonVar.Context, "devfile.yaml"))
helper.JsonPathContentIs(stdout, "devfileData.devfile.schemaVersion", "2.0.0")
helper.JsonPathContentIs(stdout, "devfileData.devfile.metadata.name", compName)
helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.dev", "true")
helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.debug", "false")
helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.deploy", "false")

View File

@@ -2,6 +2,7 @@ package devfile
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/redhat-developer/odo/tests/helper"
)
@@ -36,13 +37,50 @@ var _ = Describe("odo devfile registry command tests", func() {
})
It("Should list detailed information regarding nodejs", func() {
output := helper.Cmd("odo", "registry", "--details", "--devfile", "nodejs", "--devfile-registry", "DefaultDevfileRegistry").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"nodejs-starter", "javascript", "Node.js Runtime", "Dev: Y"})
args := []string{"registry", "--details", "--devfile", "nodejs", "--devfile-registry", "DefaultDevfileRegistry"}
By("using human readable output", func() {
output := helper.Cmd("odo", args...).ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"nodejs-starter", "javascript", "Node.js Runtime", "Dev: Y"})
})
By("using JSON output", func() {
args = append(args, "-o", "json")
res := helper.Cmd("odo", args...).ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.name", "nodejs")
helper.JsonPathContentContain(stdout, "0.displayName", "Node")
helper.JsonPathContentContain(stdout, "0.description", "Node")
helper.JsonPathContentContain(stdout, "0.language", "javascript")
helper.JsonPathContentContain(stdout, "0.projectType", "nodejs")
helper.JsonPathContentContain(stdout, "0.starterProjects.0", "nodejs-starter")
helper.JsonPathContentContain(stdout, "0.devfileData.devfile.metadata.name", "nodejs")
helper.JsonPathContentContain(stdout, "0.devfileData.supportedOdoFeatures.dev", "true")
})
})
It("Should list python specifically", func() {
output := helper.Cmd("odo", "registry", "--devfile", "python", "--devfile-registry", "DefaultDevfileRegistry").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"python"})
args := []string{"registry", "--devfile", "python", "--devfile-registry", "DefaultDevfileRegistry"}
By("using human readable output", func() {
output := helper.Cmd("odo", args...).ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"python"})
})
By("using JSON output", func() {
args = append(args, "-o", "json")
res := helper.Cmd("odo", args...).ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.name", "python")
helper.JsonPathContentContain(stdout, "0.displayName", "Python")
helper.JsonPathContentContain(stdout, "0.description", "Python")
helper.JsonPathContentContain(stdout, "0.language", "python")
helper.JsonPathContentContain(stdout, "0.projectType", "python")
helper.JsonPathContentContain(stdout, "0.starterProjects.0", "python-example")
helper.JsonPathContentContain(stdout, "0.devfileData", "")
})
})
It("Should fail with an error with no registries", func() {