Move UI out of experimental mode (#7012)
* Make UI not experimental * Display API and UI URLs * Remove link to old sources * Fix integration tests * Add UI to Usage Data * Add a "Using the GUI to edit the Devfile" page to doc * Add link to odo.dev specific page * Apply suggestions from code review Co-authored-by: Armel Soro <armel@rm3l.org> * Change favicon with odo logo * Display web console URL as part of the Dev status * Update UI static files * Document that Comments not supported * Add UI screenshots --------- Co-authored-by: Armel Soro <armel@rm3l.org>
@@ -30,6 +30,20 @@ The following tables describe the additional information collected by `odo` comm
|
||||
| odo deploy | Component Type, Devfile Name, Language, Project Type, Platform (kubernetes, openshift), Platform version |
|
||||
| odo <create/set/delete> namespace | Cluster Type (Possible values: OpenShift 3, OpenShift 4, Kubernetes) |
|
||||
|
||||
**odo v3 GUI**
|
||||
|
||||
The odo v3 GUI is accessible (by default at http://localhost:20000) when the command `odo dev` is running.
|
||||
|
||||
| Page | Data
|
||||
|----------------------|-------------------------
|
||||
| YAML (main page) | Page accessed, UI started, Devfile saved to disk, Devfile cleared, Devfile applied |
|
||||
| Metadata | Page accessed, Metadata applied |
|
||||
| Commands | Page accessed, Start create command, Create command |
|
||||
| Events | Page accessed, Add event |
|
||||
| Containers | Page accessed, Create container |
|
||||
| Images | Page accessed, Create Image |
|
||||
| Resources | Page accessed, Create Resource |
|
||||
|
||||
**odo v2**
|
||||
|
||||
| Command | Data |
|
||||
|
||||
74
docs/website/docs/user-guides/advanced/using-gui.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: Using the Web UI to edit the Devfile
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
When the command `odo dev` is running, a Graphical User Interface (GUI) is accessible (generally at http://localhost:20000).
|
||||
|
||||
The interface can be used to edit the Devfile used by the `odo dev` session.
|
||||
|
||||
The interface proposes three representations of the Devfile: a textual representation in YAML format, a Chart, and a graphical representation.
|
||||
|
||||
You can edit any representation independently, the other representations will be modified accordingly. The chart is read-only, the two other representations can be freely edited.
|
||||
|
||||
The YAML representation reflects exactly the content of the `devfile.yaml` file found into the directory where the `odo dev` session is running.
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={require('/static/img/ui-textual-representation.png').default}
|
||||
alt="Textual Representation of a Devfile in Devfile Builder"
|
||||
/>
|
||||
<figcaption>A Textual Representation of a Devfile</figcaption>
|
||||
</figure>
|
||||
|
||||
|
||||
The page *Chart* contains a chart describing the different steps of the `odo dev` session.
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={require('/static/img/ui-chart-representation.png').default}
|
||||
alt="Chart Representation of a Devfile in Devfile Builder"
|
||||
/>
|
||||
<figcaption>A Chart Representation of a Devfile</figcaption>
|
||||
</figure>
|
||||
|
||||
The following pages of the UI contain a graphical representation of the Devfile. From these pages, you can edit the Devfile by adding and deleting objects (commands, events, containers, images, resources and volumes). From the *Commands* page, it is possible to change the *Kind* (Build, Run, Test, Debug or Deploy) of each command.
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={require('/static/img/ui-graphical-representation.png').default}
|
||||
alt="Graphical Representation of a Devfile in Devfile Builder"
|
||||
/>
|
||||
<figcaption>A Graphical Representation of a Devfile</figcaption>
|
||||
</figure>
|
||||
|
||||
When you *Save* the Devfile, the content of the YAML representation is saved to the disk, replacing the previous version of the Devfile. The `odo dev` session will react accordingly, depending on the changes done into the Devfile.
|
||||
|
||||
When the file `devfile.yaml` is modified, its content is sent to the GUI, which will alert you and give you the opportunity to accept the changes done into the file. If you accept, the changes you may have done in the interface will be lost.
|
||||
|
||||
## Limitations
|
||||
|
||||
### Limited Devfile Schema Versions
|
||||
|
||||
The only supported Devfile Schema version is 2.2.0.
|
||||
|
||||
### Limited support of parameters during object creation
|
||||
|
||||
When you create an object (either a command, a container or an image) from the graphical representation, you can fill in a limited number of parameters for the object, as only the more common parameters are presented in the creation form.
|
||||
|
||||
You can add parameters to the object after it has been created by editing it from the YAML representation.
|
||||
|
||||
### Limited support for parent devfile
|
||||
|
||||
When the current Devfile is referencing a parent Devfile (using the `.parent` field into the YAML), this parent is not represented into the GUI.
|
||||
|
||||
It is still possible to add a parent information to the YAML representation. It will be taken into account by the `odo dev` session once saved.
|
||||
|
||||
### Experimental Chart representation
|
||||
|
||||
The chart representation is experimental. It is possible that, for some complex Devfile, the chart is not accurate or is not displayed.
|
||||
|
||||
### Comments in YAML are not supported
|
||||
|
||||
Comments are generally supported in YAML. In the case of a Devfile, the library used to validate the contents of a Devfile discards these comments.
|
||||
This results in that comments are removed from the YAML when you save it.
|
||||
BIN
docs/website/static/img/ui-chart-representation.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/website/static/img/ui-graphical-representation.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
docs/website/static/img/ui-textual-representation.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
@@ -12,7 +12,9 @@ import (
|
||||
|
||||
openapi "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
|
||||
"github.com/redhat-developer/odo/pkg/apiserver-impl/sse"
|
||||
"github.com/redhat-developer/odo/pkg/informer"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
"github.com/redhat-developer/odo/pkg/log"
|
||||
"github.com/redhat-developer/odo/pkg/odo/cli/feature"
|
||||
"github.com/redhat-developer/odo/pkg/podman"
|
||||
"github.com/redhat-developer/odo/pkg/preference"
|
||||
@@ -45,6 +47,7 @@ func StartServer(
|
||||
podmanClient podman.Client,
|
||||
stateClient state.Client,
|
||||
preferenceClient preference.Client,
|
||||
informerClient *informer.InformerClient,
|
||||
) (ApiServer, error) {
|
||||
pushWatcher := make(chan struct{})
|
||||
defaultApiService := NewDefaultApiService(
|
||||
@@ -129,7 +132,13 @@ func StartServer(
|
||||
cancelFunc()
|
||||
}
|
||||
|
||||
klog.V(0).Infof("API Server started at localhost:%d/api/v1", listeningPort)
|
||||
if feature.IsEnabled(ctx, feature.UIServer) {
|
||||
info := fmt.Sprintf("Web console accessible at http://localhost:%d/", listeningPort)
|
||||
log.Spinner(info).End(true)
|
||||
informerClient.AppendInfo(info + "\n")
|
||||
}
|
||||
log.Spinner(fmt.Sprintf("API Server started at http://localhost:%d/api/v1", listeningPort)).End(true)
|
||||
log.Spinner(fmt.Sprintf("API documentation accessible at http://localhost:%d/swagger-ui/", listeningPort)).End(true)
|
||||
|
||||
go func() {
|
||||
select {
|
||||
|
||||
BIN
pkg/apiserver-impl/ui/favicon.ico
generated
|
Before Width: | Height: | Size: 948 B After Width: | Height: | Size: 15 KiB |
2
pkg/apiserver-impl/ui/index.html
generated
@@ -11,6 +11,6 @@
|
||||
<body class="mat-typography">
|
||||
<div id="loading">Loading, please wait...</div>
|
||||
<app-root></app-root>
|
||||
<script src="runtime.1289ea0acffcdc5e.js" type="module"></script><script src="polyfills.8b3b37cedaf377c3.js" type="module"></script><script src="main.1f6f2714e5bbe400.js" type="module"></script>
|
||||
<script src="runtime.1289ea0acffcdc5e.js" type="module"></script><script src="polyfills.8b3b37cedaf377c3.js" type="module"></script><script src="main.6a89d63885b00552.js" type="module"></script>
|
||||
|
||||
</body></html>
|
||||
1
pkg/apiserver-impl/ui/main.1f6f2714e5bbe400.js
generated
1
pkg/apiserver-impl/ui/main.6a89d63885b00552.js
generated
Normal file
@@ -24,13 +24,6 @@ import (
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
const (
|
||||
promptMessage = `
|
||||
[Ctrl+c] - Exit and delete resources from the cluster
|
||||
[p] - Manually apply local changes to the application on the cluster
|
||||
`
|
||||
)
|
||||
|
||||
type DevClient struct {
|
||||
kubernetesClient kclient.ClientInterface
|
||||
prefClient preference.Client
|
||||
@@ -97,7 +90,6 @@ func (o *DevClient) Start(
|
||||
StartOptions: options,
|
||||
DevfileWatchHandler: o.regenerateAdapterAndPush,
|
||||
WatchCluster: true,
|
||||
PromptMessage: promptMessage,
|
||||
}
|
||||
|
||||
return o.watchClient.WatchAndPush(ctx, watchParameters, componentStatus)
|
||||
|
||||
@@ -27,13 +27,6 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
promptMessage = `
|
||||
[Ctrl+c] - Exit and delete resources from podman
|
||||
[p] - Manually apply local changes to the application on podman
|
||||
`
|
||||
)
|
||||
|
||||
type DevClient struct {
|
||||
fs filesystem.Filesystem
|
||||
|
||||
@@ -91,7 +84,6 @@ func (o *DevClient) Start(
|
||||
StartOptions: options,
|
||||
DevfileWatchHandler: o.watchHandler,
|
||||
WatchCluster: false,
|
||||
PromptMessage: promptMessage,
|
||||
}
|
||||
|
||||
return o.watchClient.WatchAndPush(ctx, watchParameters, componentStatus)
|
||||
|
||||
3
pkg/informer/doc.go
Normal file
@@ -0,0 +1,3 @@
|
||||
// package informer provides a service to register information
|
||||
// to display during Dev mode to the user in a regular basis
|
||||
package informer
|
||||
20
pkg/informer/informer.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package informer
|
||||
|
||||
type InformerClient struct {
|
||||
info string
|
||||
}
|
||||
|
||||
func NewInformerClient() *InformerClient {
|
||||
return &InformerClient{}
|
||||
}
|
||||
|
||||
func (o *InformerClient) AppendInfo(s string) {
|
||||
if o.info != "" {
|
||||
o.info += "\n"
|
||||
}
|
||||
o.info += s
|
||||
}
|
||||
|
||||
func (o *InformerClient) GetInfo() string {
|
||||
return o.info
|
||||
}
|
||||
@@ -83,6 +83,7 @@ func (o *ApiServerOptions) Run(ctx context.Context) (err error) {
|
||||
nil,
|
||||
o.clientset.StateClient,
|
||||
o.clientset.PreferenceClient,
|
||||
o.clientset.InformerClient,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -119,6 +120,7 @@ func NewCmdApiServer(ctx context.Context, name, fullName string, testClientset c
|
||||
}
|
||||
clientset.Add(apiserverCmd,
|
||||
clientset.FILESYSTEM,
|
||||
clientset.INFORMER,
|
||||
clientset.STATE,
|
||||
clientset.PREFERENCE,
|
||||
)
|
||||
|
||||
@@ -203,10 +203,10 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
componentName = odocontext.GetComponentName(ctx)
|
||||
variables = fcontext.GetVariables(ctx)
|
||||
platform = fcontext.GetPlatform(ctx, commonflags.PlatformCluster)
|
||||
dest string
|
||||
deployingTo string
|
||||
)
|
||||
|
||||
var dest string
|
||||
var deployingTo string
|
||||
switch platform {
|
||||
case commonflags.PlatformPodman:
|
||||
dest = "Platform: podman"
|
||||
@@ -286,6 +286,7 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
o.clientset.PodmanClient,
|
||||
o.clientset.StateClient,
|
||||
o.clientset.PreferenceClient,
|
||||
o.clientset.InformerClient,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -298,6 +299,10 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
}()
|
||||
}
|
||||
|
||||
o.clientset.InformerClient.AppendInfo(log.Sbold("Keyboard Commands:") + "\n" +
|
||||
"[Ctrl+c] - Exit and delete resources from " + deployingTo + "\n" +
|
||||
" [p] - Manually apply local changes to the application on " + deployingTo + "\n")
|
||||
|
||||
return o.clientset.DevClient.Start(
|
||||
o.ctx,
|
||||
dev.StartOptions{
|
||||
@@ -426,6 +431,7 @@ It forwards endpoints with any exposure values ('public', 'internal' or 'none')
|
||||
clientset.DEV,
|
||||
clientset.EXEC,
|
||||
clientset.FILESYSTEM,
|
||||
clientset.INFORMER,
|
||||
clientset.INIT,
|
||||
clientset.KUBERNETES_NULLABLE,
|
||||
clientset.LOGS,
|
||||
|
||||
@@ -19,7 +19,7 @@ var (
|
||||
}
|
||||
|
||||
UIServer = OdoFeature{
|
||||
isExperimental: true,
|
||||
isExperimental: false,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/redhat-developer/odo/pkg/dev/kubedev"
|
||||
"github.com/redhat-developer/odo/pkg/dev/podmandev"
|
||||
"github.com/redhat-developer/odo/pkg/exec"
|
||||
"github.com/redhat-developer/odo/pkg/informer"
|
||||
"github.com/redhat-developer/odo/pkg/log"
|
||||
"github.com/redhat-developer/odo/pkg/logs"
|
||||
"github.com/redhat-developer/odo/pkg/odo/commonflags"
|
||||
@@ -63,6 +64,8 @@ const (
|
||||
EXEC = "DEP_EXEC"
|
||||
// FILESYSTEM instantiates client for pkg/testingutil/filesystem
|
||||
FILESYSTEM = "DEP_FILESYSTEM"
|
||||
// INFORMER instantiates client for pkg/informer
|
||||
INFORMER = "DEP_INFORMER"
|
||||
// INIT instantiates client for pkg/init
|
||||
INIT = "DEP_INIT"
|
||||
// KUBERNETES_NULLABLE instantiates client for pkg/kclient, can be nil
|
||||
@@ -121,7 +124,7 @@ var subdeps map[string][]string = map[string][]string{
|
||||
REGISTRY: {FILESYSTEM, PREFERENCE, KUBERNETES_NULLABLE},
|
||||
STATE: {FILESYSTEM},
|
||||
SYNC: {EXEC},
|
||||
WATCH: {KUBERNETES_NULLABLE},
|
||||
WATCH: {INFORMER, KUBERNETES_NULLABLE},
|
||||
BINDING: {PROJECT, KUBERNETES_NULLABLE},
|
||||
/* Add sub-dependencies here, if any */
|
||||
}
|
||||
@@ -138,6 +141,7 @@ type Clientset struct {
|
||||
DevClient dev.Client
|
||||
ExecClient exec.Client
|
||||
FS filesystem.Filesystem
|
||||
InformerClient *informer.InformerClient
|
||||
InitClient _init.Client
|
||||
KubernetesClient kclient.ClientInterface
|
||||
LogsClient logs.Client
|
||||
@@ -197,6 +201,9 @@ func Fetch(command *cobra.Command, platform string, testClientset Clientset) (*C
|
||||
dep.FS = filesystem.DefaultFs{}
|
||||
}
|
||||
}
|
||||
if isDefined(command, INFORMER) {
|
||||
dep.InformerClient = informer.NewInformerClient()
|
||||
}
|
||||
if isDefined(command, KUBERNETES) || isDefined(command, KUBERNETES_NULLABLE) {
|
||||
if testClientset.KubernetesClient != nil {
|
||||
dep.KubernetesClient = testClientset.KubernetesClient
|
||||
@@ -293,7 +300,7 @@ func Fetch(command *cobra.Command, platform string, testClientset Clientset) (*C
|
||||
}
|
||||
}
|
||||
if isDefined(command, WATCH) {
|
||||
dep.WatchClient = watch.NewWatchClient(dep.KubernetesClient)
|
||||
dep.WatchClient = watch.NewWatchClient(dep.KubernetesClient, dep.InformerClient)
|
||||
}
|
||||
if isDefined(command, BINDING) {
|
||||
dep.BindingClient = binding.NewBindingClient(dep.ProjectClient, dep.KubernetesClient)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/dev"
|
||||
"github.com/redhat-developer/odo/pkg/dev/common"
|
||||
"github.com/redhat-developer/odo/pkg/informer"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
"github.com/redhat-developer/odo/pkg/labels"
|
||||
@@ -36,7 +37,8 @@ const (
|
||||
)
|
||||
|
||||
type WatchClient struct {
|
||||
kubeClient kclient.ClientInterface
|
||||
kubeClient kclient.ClientInterface
|
||||
informerClient *informer.InformerClient
|
||||
|
||||
sourcesWatcher *fsnotify.Watcher
|
||||
deploymentWatcher watch.Interface
|
||||
@@ -55,9 +57,13 @@ type WatchClient struct {
|
||||
|
||||
var _ Client = (*WatchClient)(nil)
|
||||
|
||||
func NewWatchClient(kubeClient kclient.ClientInterface) *WatchClient {
|
||||
func NewWatchClient(
|
||||
kubeClient kclient.ClientInterface,
|
||||
informerClient *informer.InformerClient,
|
||||
) *WatchClient {
|
||||
return &WatchClient{
|
||||
kubeClient: kubeClient,
|
||||
kubeClient: kubeClient,
|
||||
informerClient: informerClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +82,6 @@ type WatchParameters struct {
|
||||
|
||||
// WatchCluster indicates to watch Cluster-related objects (Deployment, Pod, etc)
|
||||
WatchCluster bool
|
||||
// PromptMessage
|
||||
PromptMessage string
|
||||
}
|
||||
|
||||
// evaluateChangesFunc evaluates any file changes for the events by ignoring the files in fileIgnores slice and removes
|
||||
@@ -444,14 +448,14 @@ func (o *WatchClient) processEvents(
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(out, "%s - %s\n\n", PushErrorString, err.Error())
|
||||
PrintInfoMessage(out, path, parameters.StartOptions.WatchFiles, parameters.PromptMessage)
|
||||
o.printInfoMessage(out, path, parameters.StartOptions.WatchFiles)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if oldStatus.GetState() != StateReady && componentStatus.GetState() == StateReady ||
|
||||
!reflect.DeepEqual(oldStatus.EndpointsForwarded, componentStatus.EndpointsForwarded) {
|
||||
|
||||
PrintInfoMessage(out, path, parameters.StartOptions.WatchFiles, parameters.PromptMessage)
|
||||
o.printInfoMessage(out, path, parameters.StartOptions.WatchFiles)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -497,7 +501,7 @@ func removeDuplicates(input []string) []string {
|
||||
return result
|
||||
}
|
||||
|
||||
func PrintInfoMessage(out io.Writer, path string, watchFiles bool, promptMessage string) {
|
||||
func (o *WatchClient) printInfoMessage(out io.Writer, path string, watchFiles bool) {
|
||||
log.Sectionf("Dev mode")
|
||||
if watchFiles {
|
||||
fmt.Fprintf(
|
||||
@@ -507,11 +511,9 @@ func PrintInfoMessage(out io.Writer, path string, watchFiles bool, promptMessage
|
||||
path,
|
||||
)
|
||||
}
|
||||
fmt.Fprintf(
|
||||
fmt.Fprint(
|
||||
out,
|
||||
" %s%s",
|
||||
log.Sbold("Keyboard Commands:"),
|
||||
promptMessage,
|
||||
o.informerClient.GetInfo(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ActiveState/termtest/expect"
|
||||
@@ -206,8 +205,7 @@ func StartDevMode(options DevSessionOpts) (devSession DevSession, err error) {
|
||||
result.ErrOut = string(errContents)
|
||||
result.Endpoints = getPorts(string(outContents), options.CustomAddress)
|
||||
if options.StartAPIServer {
|
||||
// errContents because the server message is still printed as a log/warning
|
||||
result.APIServerEndpoint = getAPIServerPort(string(errContents))
|
||||
result.APIServerEndpoint = getAPIServerPort(string(outContents))
|
||||
}
|
||||
return result, nil
|
||||
|
||||
@@ -395,10 +393,8 @@ func getPorts(s, address string) map[string]string {
|
||||
}
|
||||
|
||||
// getAPIServerPort returns the address at which api server is running
|
||||
//
|
||||
// `I0617 11:40:44.124391 49578 starterserver.go:36] API Server started at localhost:20000/api/v1`
|
||||
func getAPIServerPort(s string) string {
|
||||
re := regexp.MustCompile(`(API Server started at localhost:[0-9]+\/api\/v1)`)
|
||||
matches := re.FindString(s)
|
||||
return strings.Split(matches, "at ")[1]
|
||||
re := regexp.MustCompile(`API Server started at http://(localhost:[0-9]+\/api\/v1)`)
|
||||
matches := re.FindStringSubmatch(s)
|
||||
return matches[1]
|
||||
}
|
||||
|
||||
@@ -105,44 +105,6 @@ var _ = Describe("odo dev command with api server tests", func() {
|
||||
Expect(resp.StatusCode).To(BeEquivalentTo(http.StatusOK))
|
||||
})
|
||||
|
||||
It("should describe the API Server port in the experimental mode", func() {
|
||||
args := []string{"describe", "component"}
|
||||
if podman {
|
||||
args = append(args, "--platform", "podman")
|
||||
}
|
||||
stdout := helper.Cmd("odo", args...).AddEnv("ODO_EXPERIMENTAL_MODE=true").ShouldPass().Out()
|
||||
Expect(stdout).To(ContainSubstring("Dev Control Plane"))
|
||||
Expect(stdout).To(ContainSubstring("API: http://%s", devSession.APIServerEndpoint))
|
||||
if customPort {
|
||||
Expect(stdout).To(ContainSubstring("Web UI: http://localhost:%d/", localPort))
|
||||
} else {
|
||||
Expect(stdout).To(MatchRegexp("Web UI: http:\\/\\/localhost:[0-9]+\\/"))
|
||||
}
|
||||
})
|
||||
|
||||
It("should describe the API Server port in the experimental mode (JSON)", func() {
|
||||
args := []string{"describe", "component", "-o", "json"}
|
||||
if podman {
|
||||
args = append(args, "--platform", "podman")
|
||||
}
|
||||
stdout := helper.Cmd("odo", args...).AddEnv("ODO_EXPERIMENTAL_MODE=true").ShouldPass().Out()
|
||||
helper.IsJSON(stdout)
|
||||
helper.JsonPathExist(stdout, "devControlPlane")
|
||||
plt := "cluster"
|
||||
if podman {
|
||||
plt = "podman"
|
||||
}
|
||||
helper.JsonPathContentHasLen(stdout, "devControlPlane", 1)
|
||||
helper.JsonPathContentIs(stdout, "devControlPlane.0.platform", plt)
|
||||
if customPort {
|
||||
helper.JsonPathContentIs(stdout, "devControlPlane.0.localPort", strconv.Itoa(localPort))
|
||||
} else {
|
||||
helper.JsonPathContentIsValidUserPort(stdout, "devControlPlane.0.localPort")
|
||||
}
|
||||
helper.JsonPathContentIs(stdout, "devControlPlane.0.apiServerPath", "/api/v1/")
|
||||
helper.JsonPathContentIs(stdout, "devControlPlane.0.webInterfacePath", "/")
|
||||
})
|
||||
|
||||
It("should describe the API Server port", func() {
|
||||
args := []string{"describe", "component"}
|
||||
if podman {
|
||||
@@ -151,7 +113,11 @@ var _ = Describe("odo dev command with api server tests", func() {
|
||||
stdout := helper.Cmd("odo", args...).ShouldPass().Out()
|
||||
Expect(stdout).To(ContainSubstring("Dev Control Plane"))
|
||||
Expect(stdout).To(ContainSubstring("API: http://%s", devSession.APIServerEndpoint))
|
||||
Expect(stdout).ToNot(ContainSubstring("Web UI: http://localhost:%d/", localPort))
|
||||
if customPort {
|
||||
Expect(stdout).To(ContainSubstring("Web UI: http://localhost:%d/", localPort))
|
||||
} else {
|
||||
Expect(stdout).To(MatchRegexp("Web UI: http:\\/\\/localhost:[0-9]+\\/"))
|
||||
}
|
||||
})
|
||||
|
||||
It("should describe the API Server port (JSON)", func() {
|
||||
@@ -174,7 +140,7 @@ var _ = Describe("odo dev command with api server tests", func() {
|
||||
helper.JsonPathContentIsValidUserPort(stdout, "devControlPlane.0.localPort")
|
||||
}
|
||||
helper.JsonPathContentIs(stdout, "devControlPlane.0.apiServerPath", "/api/v1/")
|
||||
helper.JsonPathDoesNotExist(stdout, "devControlPlane.0.webInterfacePath")
|
||||
helper.JsonPathContentIs(stdout, "devControlPlane.0.webInterfacePath", "/")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -33,3 +33,7 @@ div.error-message {
|
||||
font-size: large;
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.toplink {
|
||||
color: white;
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
<mat-toolbar color="primary">
|
||||
<span>Devfile Builder</span>
|
||||
<span class="spacer"></span>
|
||||
<span class="topright">Work in progress</span>
|
||||
<a mat-icon-button href="https://github.com/feloy/devfile-builder" target="_blank"><mat-icon svgIcon="github"></mat-icon></a>
|
||||
<span class="topright"><a href="https://odo.dev/docs/user-guides/advanced/using-gui/" target="_blank" class="toplink">Work in progress</a></span>
|
||||
<button style="top: -8px" data-cy="yaml-send" matTooltip="Save Devfile to disk" mat-flat-button color="warn" disabled="{{!(state.modified|async)}}" (click)="onSave(input.value)">Save</button>
|
||||
</mat-toolbar>
|
||||
<main>
|
||||
|
||||
|
Before Width: | Height: | Size: 948 B After Width: | Height: | Size: 15 KiB |