Skip to content

Commit

Permalink
Merge a2bd201 into 1c6767e
Browse files Browse the repository at this point in the history
  • Loading branch information
feloy authored Aug 4, 2023
2 parents 1c6767e + a2bd201 commit 45928ca
Show file tree
Hide file tree
Showing 21 changed files with 140 additions and 84 deletions.
14 changes: 14 additions & 0 deletions USAGE_DATA.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
44 changes: 44 additions & 0 deletions docs/website/docs/user-guides/advanced/using-gui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
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.

The page *Chart* contains a chart describing the different steps of the `odo dev` session.

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.

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.
11 changes: 10 additions & 1 deletion pkg/apiserver-impl/starterserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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 {
Expand Down
Binary file modified pkg/apiserver-impl/ui/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion pkg/apiserver-impl/ui/index.html

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

1 change: 0 additions & 1 deletion pkg/apiserver-impl/ui/main.1f6f2714e5bbe400.js

This file was deleted.

1 change: 1 addition & 0 deletions pkg/apiserver-impl/ui/main.6a89d63885b00552.js

Large diffs are not rendered by default.

8 changes: 0 additions & 8 deletions pkg/dev/kubedev/kubedev.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -97,7 +90,6 @@ func (o *DevClient) Start(
StartOptions: options,
DevfileWatchHandler: o.regenerateAdapterAndPush,
WatchCluster: true,
PromptMessage: promptMessage,
}

return o.watchClient.WatchAndPush(ctx, watchParameters, componentStatus)
Expand Down
8 changes: 0 additions & 8 deletions pkg/dev/podmandev/podmandev.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -91,7 +84,6 @@ func (o *DevClient) Start(
StartOptions: options,
DevfileWatchHandler: o.watchHandler,
WatchCluster: false,
PromptMessage: promptMessage,
}

return o.watchClient.WatchAndPush(ctx, watchParameters, componentStatus)
Expand Down
3 changes: 3 additions & 0 deletions pkg/informer/doc.go
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions pkg/informer/informer.go
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 2 additions & 0 deletions pkg/odo/cli/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
)
Expand Down
10 changes: 8 additions & 2 deletions pkg/odo/cli/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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{
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion pkg/odo/cli/feature/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var (
}

UIServer = OdoFeature{
isExperimental: true,
isExperimental: false,
}
)

Expand Down
11 changes: 9 additions & 2 deletions pkg/odo/genericclioptions/clientset/clientset.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
}
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
26 changes: 14 additions & 12 deletions pkg/watch/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -36,7 +37,8 @@ const (
)

type WatchClient struct {
kubeClient kclient.ClientInterface
kubeClient kclient.ClientInterface
informerClient *informer.InformerClient

sourcesWatcher *fsnotify.Watcher
deploymentWatcher watch.Interface
Expand All @@ -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,
}
}

Expand All @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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(
Expand All @@ -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(),
)
}

Expand Down
Loading

0 comments on commit 45928ca

Please sign in to comment.