From faa0c1311d4e5af575333a780b96d6ebf4284c1b Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Fri, 30 Jun 2023 17:42:13 +0200 Subject: [PATCH 1/4] Add integration tests highlighting the expectations --- tests/helper/helper_generic.go | 7 + .../cmd_describe_component_test.go | 135 ++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/tests/helper/helper_generic.go b/tests/helper/helper_generic.go index d0d8cd5f60a..87d69b78386 100644 --- a/tests/helper/helper_generic.go +++ b/tests/helper/helper_generic.go @@ -355,6 +355,13 @@ func JsonPathContentIsValidUserPort(json string, path string) { )) } +func JsonPathContentHasLen(json string, path string, len int) { + result := gjson.Get(json, path+".#") + intVal, err := strconv.Atoi(result.String()) + Expect(err).ToNot(HaveOccurred()) + Expect(intVal).To(Equal(len), fmt.Sprintf("%q should contain exactly %d elements", path, len)) +} + // GetProjectName sets projectNames based on the name of the test file name (without path and replacing _ with -), line number of current ginkgo execution, and a random string of 3 letters func GetProjectName() string { //Get current test filename and remove file path, file extension and replace undescores with hyphens diff --git a/tests/integration/cmd_describe_component_test.go b/tests/integration/cmd_describe_component_test.go index 3f032fdf8dc..52f744c207a 100644 --- a/tests/integration/cmd_describe_component_test.go +++ b/tests/integration/cmd_describe_component_test.go @@ -131,6 +131,26 @@ var _ = Describe("odo describe component command tests", func() { helper.JsonPathContentIs(jsonContent, "devfileData.supportedOdoFeatures.deploy", "false") helper.JsonPathContentIs(jsonContent, "devfileData.supportedOdoFeatures.debug", "true") helper.JsonPathContentIs(jsonContent, "managedBy", "odo") + + helper.JsonPathContentHasLen(jsonContent, "devfileData.commands", 4) + helper.JsonPathContentIs(jsonContent, "devfileData.commands.0.name", "install") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.0.group", "build") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.0.commandLine", "npm install") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.1.name", "run") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.1.group", "run") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.1.commandLine", "npm start") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.2.name", "debug") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.2.group", "debug") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.2.commandLine", "npm run debug") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.3.name", "test") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.3.group", "test") + helper.JsonPathContentIs(jsonContent, "devfileData.commands.3.commandLine", "npm test") + for i := 0; i <= 3; i++ { + helper.JsonPathContentIs(jsonContent, fmt.Sprintf("devfileData.commands.%d.type", i), "exec") + helper.JsonPathContentIs(jsonContent, fmt.Sprintf("devfileData.commands.%d.isDefault", i), "true") + helper.JsonPathContentIs(jsonContent, fmt.Sprintf("devfileData.commands.%d.component", i), "runtime") + helper.JsonPathContentIs(jsonContent, fmt.Sprintf("devfileData.commands.%d.componentType", i), "container") + } } checkDevfileDescription := func(content string, withUnknown bool) { @@ -144,6 +164,7 @@ var _ = Describe("odo describe component command tests", func() { Expect(content).To(ContainSubstring("Dev: Unknown")) Expect(content).To(ContainSubstring("Debug: Unknown")) Expect(content).To(ContainSubstring("Deploy: Unknown")) + Expect(content).ShouldNot(ContainSubstring("Commands:")) } else { Expect(content).To(ContainSubstring("Display Name: ")) Expect(content).To(ContainSubstring("Language: ")) @@ -153,6 +174,26 @@ var _ = Describe("odo describe component command tests", func() { Expect(content).To(ContainSubstring("Dev: true")) Expect(content).To(ContainSubstring("Debug: true")) Expect(content).To(ContainSubstring("Deploy: false")) + + Expect(content).To(ContainSubstring("Commands:")) + for _, c := range []string{"exec"} { + Expect(content).To(ContainSubstring("Type: " + c)) + } + for _, c := range []string{"runtime"} { + Expect(content).To(ContainSubstring("Component: " + c)) + } + for _, c := range []string{"container"} { + Expect(content).To(ContainSubstring("Component Type: " + c)) + } + for _, c := range []string{"install", "run", "debug", "test"} { + Expect(content).To(ContainSubstring(c)) + } + for _, c := range []string{"build", "run", "debug", "test"} { + Expect(content).To(ContainSubstring("Group: %s", c)) + } + for _, c := range []string{"npm install", "npm start", "npm run debug", "npm test"} { + Expect(content).To(ContainSubstring("Command Line: %q", c)) + } } } @@ -440,6 +481,7 @@ var _ = Describe("odo describe component command tests", func() { helper.JsonPathContentIs(stdout, "runningOn.cluster.deploy", "false") helper.JsonPathDoesNotExist(stdout, "runningOn.podman") } + helper.JsonPathDoesNotExist(stdout, "devfileData.commands") }) }) }) @@ -651,4 +693,97 @@ var _ = Describe("odo describe component command tests", func() { } }) }) + + Context("describe commands in Devfile", Label(helper.LabelUnauth), Label(helper.LabelNoCluster), func() { + + When("initializing a component with different types of commands", func() { + + BeforeEach(func() { + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project"), commonVar.Context) + helper.CopyExampleDevFile( + filepath.Join("source", "devfiles", "nodejs", "devfile-deploy-functional-pods.yaml"), + path.Join(commonVar.Context, "devfile.yaml"), + cmpName) + }) + + It("should describe the Devfile commands in human-readable form", func() { + stdout := helper.Cmd("odo", "describe", "component").ShouldPass().Out() + Expect(stdout).To(ContainSubstring("Commands:")) + for _, c := range []string{"exec", "composite", "apply"} { + Expect(stdout).To(ContainSubstring("Type: " + c)) + } + for _, c := range []string{"runtime", "innerloop-pod", "prod-image", "outerloop-deploy"} { + Expect(stdout).To(ContainSubstring("Component: " + c)) + } + for _, c := range []string{"container", "kubernetes", "image"} { + Expect(stdout).To(ContainSubstring("Component Type: " + c)) + } + for _, c := range []string{ + "install", + "innerloop-pod-command", + "start", + "run", + "build-image", + "deploy-deployment", + "deploy-another-deployment", + "outerloop-pod-command", + "deploy", + } { + Expect(stdout).To(ContainSubstring(c)) + } + for _, c := range []string{"build", "run", "deploy"} { + Expect(stdout).To(ContainSubstring("Group: %s", c)) + } + for _, c := range []string{"npm install", "npm start"} { + Expect(stdout).To(ContainSubstring("Command Line: %q", c)) + } + for _, c := range []string{"quay.io/tkral/devfile-nodejs-deploy:latest"} { + Expect(stdout).To(ContainSubstring("Image Name: %s", c)) + } + }) + + It("should describe the Devfile commands in JSON output", func() { + stdout := helper.Cmd("odo", "describe", "component", "-o", "json").ShouldPass().Out() + Expect(helper.IsJSON(stdout)).To(BeTrue(), fmt.Sprintf("invalid JSON output: %q", stdout)) + + helper.JsonPathContentHasLen(stdout, "devfileData.commands", 9) + + helper.JsonPathContentIs(stdout, "devfileData.commands.0.name", "install") + helper.JsonPathContentIs(stdout, "devfileData.commands.0.group", "build") + helper.JsonPathContentIs(stdout, "devfileData.commands.0.commandLine", "npm install") + helper.JsonPathContentIs(stdout, "devfileData.commands.0.type", "exec") + helper.JsonPathContentIs(stdout, "devfileData.commands.0.isDefault", "true") + helper.JsonPathContentIs(stdout, "devfileData.commands.0.component", "runtime") + helper.JsonPathContentIs(stdout, "devfileData.commands.0.componentType", "container") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.0.imageName") + + helper.JsonPathContentIs(stdout, "devfileData.commands.1.name", "innerloop-pod-command") + helper.JsonPathContentIs(stdout, "devfileData.commands.1.type", "apply") + helper.JsonPathContentIs(stdout, "devfileData.commands.1.component", "innerloop-pod") + helper.JsonPathContentIs(stdout, "devfileData.commands.1.componentType", "kubernetes") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.1.group") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.1.commandLine") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.1.isDefault") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.1.imageName") + + helper.JsonPathContentIs(stdout, "devfileData.commands.4.name", "build-image") + helper.JsonPathContentIs(stdout, "devfileData.commands.4.type", "apply") + helper.JsonPathContentIs(stdout, "devfileData.commands.4.component", "prod-image") + helper.JsonPathContentIs(stdout, "devfileData.commands.4.componentType", "image") + helper.JsonPathContentIs(stdout, "devfileData.commands.4.imageName", "quay.io/tkral/devfile-nodejs-deploy:latest") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.4.group") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.4.commandLine") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.4.isDefault") + + helper.JsonPathContentIs(stdout, "devfileData.commands.8.name", "deploy") + helper.JsonPathContentIs(stdout, "devfileData.commands.8.group", "deploy") + helper.JsonPathContentIs(stdout, "devfileData.commands.8.type", "composite") + helper.JsonPathContentIs(stdout, "devfileData.commands.8.isDefault", "true") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.8.imageName") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.8.commandLine") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.8.component") + helper.JsonPathDoesNotExist(stdout, "devfileData.commands.8.componentType") + }) + }) + }) }) From a5e8e760c1e7fe71c300ec5ae916cc4852dd80df Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Fri, 30 Jun 2023 17:50:13 +0200 Subject: [PATCH 2/4] Add and fill a 'Commands' field from the DevfileData struct returned by `describe` --- pkg/api/devfile-data.go | 39 +++++++++++ pkg/api/utils.go | 101 ++++++++++++++++++++++++++++- pkg/component/describe/describe.go | 10 ++- pkg/libdevfile/libdevfile.go | 14 ++++ pkg/odo/cli/init/init.go | 6 +- pkg/registry/registry.go | 7 +- 6 files changed, 171 insertions(+), 6 deletions(-) diff --git a/pkg/api/devfile-data.go b/pkg/api/devfile-data.go index 172f5df0164..e730dd682ee 100644 --- a/pkg/api/devfile-data.go +++ b/pkg/api/devfile-data.go @@ -5,6 +5,7 @@ import "github.com/devfile/library/v2/pkg/devfile/parser/data" // DevfileData describes a devfile content type DevfileData struct { Devfile data.DevfileData `json:"devfile"` + Commands []DevfileCommand `json:"commands,omitempty"` SupportedOdoFeatures *SupportedOdoFeatures `json:"supportedOdoFeatures,omitempty"` } @@ -14,3 +15,41 @@ type SupportedOdoFeatures struct { Deploy bool `json:"deploy"` Debug bool `json:"debug"` } + +type DevfileCommand struct { + Name string `json:"name,omitempty"` + Type DevfileCommandType `json:"type,omitempty"` + Group DevfileCommandGroup `json:"group,omitempty"` + IsDefault *bool `json:"isDefault,omitempty"` + CommandLine string `json:"commandLine,omitempty"` + Component string `json:"component,omitempty"` + ComponentType DevfileComponentType `json:"componentType,omitempty"` + ImageName string `json:"imageName,omitempty"` +} + +type DevfileCommandType string + +const ( + ExecCommandType DevfileCommandType = "exec" + ApplyCommandType DevfileCommandType = "apply" + CompositeCommandType DevfileCommandType = "composite" +) + +type DevfileCommandGroup string + +const ( + BuildCommandGroup DevfileCommandGroup = "build" + RunCommandGroup DevfileCommandGroup = "run" + TestCommandGroup DevfileCommandGroup = "test" + DebugCommandGroup DevfileCommandGroup = "debug" + DeployCommandGroup DevfileCommandGroup = "deploy" +) + +type DevfileComponentType string + +const ( + ImageComponentType DevfileComponentType = "image" + ContainerComponentType DevfileComponentType = "container" + KubernetesComponentType DevfileComponentType = "kubernetes" + OpenshiftComponentType DevfileComponentType = "openshift" +) diff --git a/pkg/api/utils.go b/pkg/api/utils.go index 4716b28d235..c151df5505e 100644 --- a/pkg/api/utils.go +++ b/pkg/api/utils.go @@ -1,16 +1,24 @@ package api import ( + 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/data" + "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common" + "github.com/redhat-developer/odo/pkg/libdevfile" ) -func GetDevfileData(devfileObj parser.DevfileObj) *DevfileData { +func GetDevfileData(devfileObj parser.DevfileObj) (*DevfileData, error) { + commands, err := getDevfileCommands(devfileObj.Data) + if err != nil { + return nil, err + } return &DevfileData{ Devfile: devfileObj.Data, + Commands: commands, SupportedOdoFeatures: getSupportedOdoFeatures(devfileObj.Data), - } + }, nil } func getSupportedOdoFeatures(devfileData data.DevfileData) *SupportedOdoFeatures { @@ -20,3 +28,92 @@ func getSupportedOdoFeatures(devfileData data.DevfileData) *SupportedOdoFeatures Debug: libdevfile.HasDebugCommand(devfileData), } } + +func getDevfileCommands(devfileData data.DevfileData) ([]DevfileCommand, error) { + commands, err := devfileData.GetCommands(common.DevfileOptions{}) + if err != nil { + return nil, err + } + + toGroupFn := func(g *v1alpha2.CommandGroup) (group DevfileCommandGroup, isDefault *bool) { + if g == nil { + return "", nil + } + switch g.Kind { + case v1alpha2.BuildCommandGroupKind: + group = BuildCommandGroup + case v1alpha2.RunCommandGroupKind: + group = RunCommandGroup + case v1alpha2.DebugCommandGroupKind: + group = DebugCommandGroup + case v1alpha2.TestCommandGroupKind: + group = TestCommandGroup + case v1alpha2.DeployCommandGroupKind: + group = DeployCommandGroup + } + + return group, g.IsDefault + } + + var result []DevfileCommand + for _, cmd := range commands { + var ( + cmdType DevfileCommandType + cmdComponent string + cmdCompType DevfileComponentType + cmdLine string + ) + var cmdGroup *v1alpha2.CommandGroup + switch { + case cmd.Apply != nil: + cmdType = ApplyCommandType + cmdComponent = cmd.Apply.Component + cmdGroup = cmd.Apply.Group + case cmd.Exec != nil: + cmdType = ExecCommandType + cmdComponent = cmd.Exec.Component + cmdGroup = cmd.Exec.Group + cmdLine = cmd.Exec.CommandLine + case cmd.Composite != nil: + cmdType = CompositeCommandType + cmdGroup = cmd.Composite.Group + } + + var imageName string + var comp v1alpha2.Component + if cmdComponent != "" { + var ok bool + comp, ok, err = libdevfile.FindComponentByName(devfileData, cmdComponent) + if err != nil { + return nil, err + } + if ok { + switch { + case comp.Kubernetes != nil: + cmdCompType = KubernetesComponentType + case comp.Openshift != nil: + cmdCompType = OpenshiftComponentType + case comp.Container != nil: + cmdCompType = ContainerComponentType + case comp.Image != nil: + cmdCompType = ImageComponentType + imageName = comp.Image.ImageName + } + } + } + g, isDefault := toGroupFn(cmdGroup) + c := DevfileCommand{ + Name: cmd.Id, + Type: cmdType, + Group: g, + IsDefault: isDefault, + CommandLine: cmdLine, + Component: cmdComponent, + ComponentType: cmdCompType, + ImageName: imageName, + } + result = append(result, c) + } + + return result, nil +} diff --git a/pkg/component/describe/describe.go b/pkg/component/describe/describe.go index c5a3e4e6fbf..b4bd87be3ac 100644 --- a/pkg/component/describe/describe.go +++ b/pkg/component/describe/describe.go @@ -9,6 +9,8 @@ import ( "github.com/devfile/library/v2/pkg/devfile/generator" "github.com/devfile/library/v2/pkg/devfile/parser" "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common" + "k8s.io/klog" + "github.com/redhat-developer/odo/pkg/api" "github.com/redhat-developer/odo/pkg/component" "github.com/redhat-developer/odo/pkg/kclient" @@ -20,7 +22,6 @@ import ( odocontext "github.com/redhat-developer/odo/pkg/odo/context" "github.com/redhat-developer/odo/pkg/podman" "github.com/redhat-developer/odo/pkg/state" - "k8s.io/klog" ) // DescribeDevfileComponent describes the component defined by the devfile in the current directory @@ -36,6 +37,11 @@ func DescribeDevfileComponent( componentName = odocontext.GetComponentName(ctx) ) + devfileData, err := api.GetDevfileData(*devfileObj) + if err != nil { + return api.Component{}, nil, err + } + isPlatformFeatureEnabled := feature.IsEnabled(ctx, feature.GenericPlatformFlag) platform := fcontext.GetPlatform(ctx, "") switch platform { @@ -115,7 +121,7 @@ func DescribeDevfileComponent( cmp := api.Component{ DevfilePath: devfilePath, - DevfileData: api.GetDevfileData(*devfileObj), + DevfileData: devfileData, DevForwardedPorts: forwardedPorts, RunningIn: api.MergeRunningModes(runningOn), RunningOn: runningOn, diff --git a/pkg/libdevfile/libdevfile.go b/pkg/libdevfile/libdevfile.go index 48489498e6d..ac7268f1e3c 100644 --- a/pkg/libdevfile/libdevfile.go +++ b/pkg/libdevfile/libdevfile.go @@ -451,6 +451,20 @@ func GetContainerComponentsForCommand(devfileObj parser.DevfileObj, cmd v1alpha2 } } +// FindComponentByName returns the Devfile component that matches the specified name. +func FindComponentByName(d data.DevfileData, n string) (v1alpha2.Component, bool, error) { + comps, err := d.GetComponents(common.DevfileOptions{}) + if err != nil { + return v1alpha2.Component{}, false, err + } + for _, c := range comps { + if c.Name == n { + return c, true, nil + } + } + return v1alpha2.Component{}, false, nil +} + // GetK8sManifestsWithVariablesSubstituted returns the full content of either a Kubernetes or an Openshift // Devfile component, either Inlined or referenced via a URI. // No matter how the component is defined, it returns the content with all variables substituted diff --git a/pkg/odo/cli/init/init.go b/pkg/odo/cli/init/init.go index d22f7608df3..a3eef32f2bf 100644 --- a/pkg/odo/cli/init/init.go +++ b/pkg/odo/cli/init/init.go @@ -161,9 +161,13 @@ func (o *InitOptions) RunForJsonOutput(ctx context.Context) (out interface{}, er if err != nil { return nil, err } + devfileData, err := api.GetDevfileData(devfileObj) + if err != nil { + return nil, err + } return api.Component{ DevfilePath: devfilePath, - DevfileData: api.GetDevfileData(devfileObj), + DevfileData: devfileData, DevForwardedPorts: []api.ForwardedPort{}, RunningIn: api.NewRunningModes(), ManagedBy: "odo", diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 24a0dfcb2e7..4194a41a883 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -445,5 +445,10 @@ func (o RegistryClient) retrieveDevfileDataFromRegistry(ctx context.Context, reg // Convert DevfileObj to DevfileData // use api.GetDevfileData to get supported features - return *api.GetDevfileData(devfileObj), nil + devfileData, err := api.GetDevfileData(devfileObj) + if err != nil { + return api.DevfileData{}, err + } + + return *devfileData, nil } From 49aceb89c2f4a30ed59e7ab7aca81aeda3d603f1 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Fri, 30 Jun 2023 17:50:39 +0200 Subject: [PATCH 3/4] Display commands in the human-readable output of 'odo describe' --- pkg/odo/cli/describe/component.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/pkg/odo/cli/describe/component.go b/pkg/odo/cli/describe/component.go index 01ff33bce76..f13e7d16781 100644 --- a/pkg/odo/cli/describe/component.go +++ b/pkg/odo/cli/describe/component.go @@ -11,6 +11,7 @@ import ( "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common" "github.com/spf13/cobra" ktemplates "k8s.io/kubectl/pkg/util/templates" + "k8s.io/utils/pointer" "github.com/redhat-developer/odo/pkg/api" "github.com/redhat-developer/odo/pkg/component/describe" @@ -192,6 +193,36 @@ func printHumanReadableOutput(ctx context.Context, cmp api.Component, devfileObj } fmt.Println() + if cmp.DevfileData != nil && len(cmp.DevfileData.Commands) != 0 { + log.Info("Commands:") + for _, cmd := range cmp.DevfileData.Commands { + item := cmd.Name + if pointer.BoolDeref(cmd.IsDefault, false) { + item = log.Sbold(cmd.Name) + } + if cmd.Type != "" { + item += fmt.Sprintf("\n Type: %s", cmd.Type) + } + if cmd.Group != "" { + item += fmt.Sprintf("\n Group: %s", cmd.Group) + } + if cmd.CommandLine != "" { + item += fmt.Sprintf("\n Command Line: %q", cmd.CommandLine) + } + if cmd.Component != "" { + item += fmt.Sprintf("\n Component: %s", cmd.Component) + } + if cmd.ComponentType != "" { + item += fmt.Sprintf("\n Component Type: %s", cmd.ComponentType) + } + if cmd.ImageName != "" { + item += fmt.Sprintf("\n Image Name: %s", cmd.ImageName) + } + log.Printf(item) + } + } + fmt.Println() + err := listComponentsNames("Container components:", devfileObj, v1alpha2.ContainerComponentType) if err != nil { return err From be0a7061e40a5eaf3c19d8bc92b7cfa33c143a87 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Fri, 30 Jun 2023 18:07:44 +0200 Subject: [PATCH 4/4] Add documentation and sample outputs --- .../command-reference/describe-component.md | 27 +++++++++++++ .../docs/command-reference/json-output.md | 40 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/docs/website/docs/command-reference/describe-component.md b/docs/website/docs/command-reference/describe-component.md index 0954c91e005..5959fd8faf5 100644 --- a/docs/website/docs/command-reference/describe-component.md +++ b/docs/website/docs/command-reference/describe-component.md @@ -33,6 +33,32 @@ Supported odo features: • Deploy: true • Debug: true +Commands: + • my-install + Type: exec + Group: build + Command Line: "npm install" + Component: runtime + Component Type: container + • my-run + Type: exec + Group: run + Command Line: "npm start" + Component: runtime + Component Type: container + • build-image + Type: apply + Component: prod-image + Component Type: image + Image Name: devfile-nodejs-deploy:latest + • deploy-deployment + Type: apply + Component: outerloop-deploy + Component Type: kubernetes + • deploy + Type: composite + Group: deploy + Container components: • runtime @@ -55,6 +81,7 @@ Kubernetes Routes: This command returns information extracted from the Devfile: - metadata (name, display name, project type, language, version, description and tags) - supported odo features, indicating if the Devfile defines necessary information to run `odo dev`, `odo dev --debug` and `odo deploy` +- the list of commands, if any, along with some useful information about each command - the list of container components, - the list of Kubernetes components. - the list of forwarded ports if the component is running in Dev mode. diff --git a/docs/website/docs/command-reference/json-output.md b/docs/website/docs/command-reference/json-output.md index c389f7658dc..29b4fcbe0ae 100644 --- a/docs/website/docs/command-reference/json-output.md +++ b/docs/website/docs/command-reference/json-output.md @@ -139,6 +139,7 @@ When the `describe component` command is executed without parameter from a direc - the path of the Devfile, - the content of the Devfile, - supported `odo` features, indicating if the Devfile defines necessary information to run `odo dev`, `odo dev --debug` and `odo deploy` + - the list of commands, if any, along with some useful information about each command - ingress or routes created in Deploy mode - the status of the component - the forwarded ports if odo is currently running in Dev mode, @@ -155,6 +156,45 @@ odo describe component -o json "schemaVersion": "2.0.0", [ devfile.yaml file content ] }, + "commands": [ + { + "name": "my-install", + "type": "exec", + "group": "build", + "isDefault": true, + "commandLine": "npm install", + "component": "runtime", + "componentType": "container" + }, + { + "name": "my-run", + "type": "exec", + "group": "run", + "isDefault": true, + "commandLine": "npm start", + "component": "runtime", + "componentType": "container" + }, + { + "name": "build-image", + "type": "apply", + "component": "prod-image", + "componentType": "image", + "imageName": "devfile-nodejs-deploy" + }, + { + "name": "deploy-deployment", + "type": "apply", + "component": "outerloop-deploy", + "componentType": "kubernetes" + }, + { + "name": "deploy", + "type": "composite", + "group": "deploy", + "isDefault": true + } + ], "supportedOdoFeatures": { "dev": true, "deploy": false,