Skip to content

Commit

Permalink
Add spinner when determining a devfile using alizer (#6793)
Browse files Browse the repository at this point in the history
* Add spinner when determining a devfile using alizer and handle panic on odo dev

Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Change HandleSignal signature, handle context cancellation in AlizerBackend Select Devfile

Co-authored-by: Philippe Martin <phmartin@redhat.com>
Co-authored-by: Armel Soro <asoro@redhat.com>
Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Fix spinner and terminate on terminal interrupt

Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Fix validation errors

Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Fix doc test error

Signed-off-by: Parthvi Vala <pvala@redhat.com>

---------

Signed-off-by: Parthvi Vala <pvala@redhat.com>
Co-authored-by: Philippe Martin <phmartin@redhat.com>
Co-authored-by: Armel Soro <asoro@redhat.com>
  • Loading branch information
3 people authored May 16, 2023
1 parent d23789a commit a6da3e0
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $ odo init
\__/

Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Language: JavaScript
Project type: Node.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $ odo init
\__/

Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Language: .NET
Project type: dotnet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $ odo init
\__/

Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Language: Go
Project type: Go
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $ odo init
\__/

Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Language: Java
Project type: springboot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $ odo init
\__/

Interactive mode enabled, please answer the following questions:
✓ Determining a Devfile for the current directory [1s]
Based on the files in the current directory odo detected
Language: JavaScript
Project type: Node.js
Expand Down
78 changes: 52 additions & 26 deletions pkg/init/backend/alizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package backend
import (
"context"
"fmt"
"github.com/redhat-developer/odo/pkg/log"
"strconv"
"strings"

Expand Down Expand Up @@ -33,37 +34,62 @@ func (o *AlizerBackend) Validate(flags map[string]string, fs filesystem.Filesyst
return nil
}

// SelectDevfile calls thz Alizer to detect the devfile and asks for confirmation to the user
func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]string, fs filesystem.Filesystem, dir string) (location *api.DetectionResult, err error) {
selected, defaultVersion, registry, err := o.alizerClient.DetectFramework(ctx, dir)
if err != nil {
return nil, err
// SelectDevfile calls the Alizer to detect the devfile and asks for confirmation to the user
func (o *AlizerBackend) SelectDevfile(ctx context.Context, flags map[string]string, fs filesystem.Filesystem, dir string) (*api.DetectionResult, error) {
type result struct {
location *api.DetectionResult
err error
}
var (
resultChan = make(chan result)
)
go func() {
location, err := func() (location *api.DetectionResult, err error) {
spinner := log.Spinnerf("Determining a Devfile for the current directory")
defer spinner.End(err == nil)
selected, defaultVersion, registry, err := o.alizerClient.DetectFramework(ctx, dir)
if err != nil {
return nil, err
}

msg := fmt.Sprintf("Based on the files in the current directory odo detected\nLanguage: %s\nProject type: %s", selected.Language, selected.ProjectType)
msg := fmt.Sprintf("Based on the files in the current directory odo detected\nLanguage: %s\nProject type: %s", selected.Language, selected.ProjectType)

appPorts, err := o.alizerClient.DetectPorts(dir)
if err != nil {
return nil, err
}
appPortsAsString := make([]string, 0, len(appPorts))
for _, p := range appPorts {
appPortsAsString = append(appPortsAsString, strconv.Itoa(p))
}
if len(appPorts) > 0 {
msg += fmt.Sprintf("\nApplication ports: %s", strings.Join(appPortsAsString, ", "))
}
appPorts, err := o.alizerClient.DetectPorts(dir)
if err != nil {
return nil, err
}
spinner.End(true)
appPortsAsString := make([]string, 0, len(appPorts))
for _, p := range appPorts {
appPortsAsString = append(appPortsAsString, strconv.Itoa(p))
}
if len(appPorts) > 0 {
msg += fmt.Sprintf("\nApplication ports: %s", strings.Join(appPortsAsString, ", "))
}

fmt.Println(msg)
fmt.Printf("The devfile \"%s:%s\" from the registry %q will be downloaded.\n", selected.Name, defaultVersion, registry.Name)
confirm, err := o.askerClient.AskCorrect()
if err != nil {
return nil, err
}
if !confirm {
return nil, nil
fmt.Println(msg)
fmt.Printf("The devfile \"%s:%s\" from the registry %q will be downloaded.\n", selected.Name, defaultVersion, registry.Name)
confirm, err := o.askerClient.AskCorrect()
if err != nil {
return nil, err
}
if !confirm {
return nil, nil
}
return alizer.NewDetectionResult(selected, registry, appPorts, defaultVersion, ""), nil
}()
resultChan <- result{
location: location,
err: err,
}
}()

select {
case res := <-resultChan:
return res.location, res.err
case <-ctx.Done():
return nil, fmt.Errorf("interrupted: %w", ctx.Err())
}
return alizer.NewDetectionResult(selected, registry, appPorts, defaultVersion, ""), nil
}

func (o *AlizerBackend) SelectStarterProject(devfile parser.DevfileObj, flags map[string]string) (starter *v1alpha2.StarterProject, err error) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/AlecAivazis/survey/v2/terminal"
"net/url"
"path/filepath"
"strings"
Expand Down Expand Up @@ -96,6 +97,9 @@ func (o *InitClient) SelectDevfile(ctx context.Context, flags map[string]string,
if backend == o.alizerBackend {
// Fallback to the Interactive Mode if Alizer could not determine the Devfile.
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, terminal.InterruptErr) {
return nil, err
}
log.Warningf("Could not determine a Devfile based on the files in the current directory: %v", err)
}
return o.interactiveBackend.SelectDevfile(ctx, flags, fs, dir)
Expand Down
4 changes: 2 additions & 2 deletions pkg/odo/cli/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
)
}

func (o *DevOptions) HandleSignal() error {
o.cancel()
func (o *DevOptions) HandleSignal(ctx context.Context, cancelFunc context.CancelFunc) error {
cancelFunc()
// At this point, `ctx.Done()` will be raised, and the cleanup will be done
// wait for the cleanup to finish and let the main thread finish instead of signal handler go routine from runnable
select {}
Expand Down
11 changes: 6 additions & 5 deletions pkg/odo/genericclioptions/runnable.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type Runnable interface {
}

type SignalHandler interface {
HandleSignal() error
HandleSignal(ctx context.Context, cancelFunc context.CancelFunc) error
}

type Cleanuper interface {
Expand Down Expand Up @@ -81,16 +81,17 @@ const (

func GenericRun(o Runnable, cmd *cobra.Command, args []string) error {
var (
err error
startTime = time.Now()
ctx = cmd.Context()
err error
startTime = time.Now()
ctx, cancelFunc = context.WithCancel(cmd.Context())
)

defer func() {
if err != nil {
cmd.SilenceErrors = true
cmd.SilenceUsage = true
}
cancelFunc()
}()

userConfig, _ := preference.NewClient(ctx)
Expand Down Expand Up @@ -174,7 +175,7 @@ func GenericRun(o Runnable, cmd *cobra.Command, args []string) error {
go commonutil.StartSignalWatcher(captureSignals, func(receivedSignal os.Signal) {
err = fmt.Errorf("user interrupted the command execution: %w", terminal.InterruptErr)
if handler, ok := o.(SignalHandler); ok {
err = handler.HandleSignal()
err = handler.HandleSignal(ctx, cancelFunc)
if err != nil {
log.Errorf("error handling interrupt signal : %v", err)
}
Expand Down

0 comments on commit a6da3e0

Please sign in to comment.