Skip to content

Commit

Permalink
Add prompt for image location
Browse files Browse the repository at this point in the history
  • Loading branch information
iamhopaul123 committed Oct 7, 2020
1 parent b2f4396 commit 3a60e65
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 42 deletions.
32 changes: 27 additions & 5 deletions internal/pkg/cli/job_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,15 @@ func (o *initJobOpts) Ask() error {
if err := o.askJobName(); err != nil {
return err
}
if err := o.askDockerfile(); err != nil {
useImage, err := o.askDockerfile()
if err != nil {
return err
}
if useImage {
if err := o.askImage(); err != nil {
return err
}
}
if err := o.askSchedule(); err != nil {
return err
}
Expand Down Expand Up @@ -260,10 +266,23 @@ func (o *initJobOpts) askJobName() error {
return nil
}

func (o *initJobOpts) askDockerfile() error {
if o.dockerfilePath != "" || o.image != "" {
func (o *initJobOpts) askImage() error {
if o.image != "" {
return nil
}
image, err := o.prompt.Get(wkldInitImagePrompt, wkldInitImagePromptHelp, nil,
prompt.WithFinalMessage("Image:"))
if err != nil {
return fmt.Errorf("get image location: %w", err)
}
o.image = image
return nil
}

func (o *initJobOpts) askDockerfile() (useImage bool, err error) {
if o.dockerfilePath != "" || o.image != "" {
return false, nil
}
df, err := o.sel.Dockerfile(
fmt.Sprintf(fmtWkldInitDockerfilePrompt, color.HighlightUserInput(o.name)),
fmt.Sprintf(fmtWkldInitDockerfilePathPrompt, color.HighlightUserInput(o.name)),
Expand All @@ -274,10 +293,13 @@ func (o *initJobOpts) askDockerfile() error {
},
)
if err != nil {
return fmt.Errorf("select Dockerfile: %w", err)
return false, fmt.Errorf("select Dockerfile: %w", err)
}
if df == selector.DockerfilePromptUseImage {
return true, nil
}
o.dockerfilePath = df
return nil
return false, nil
}

func (o *initJobOpts) askSchedule() error {
Expand Down
43 changes: 43 additions & 0 deletions internal/pkg/cli/job_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,49 @@ func TestJobInitOpts_Ask(t *testing.T) {
wantedErr: nil,
wantedSchedule: wantedCronSchedule,
},
"returns an error if fail to get image location": {
inJobType: wantedJobType,
inJobName: wantedJobName,
inDockerfilePath: "",

mockPrompt: func(m *mocks.Mockprompter) {
m.EXPECT().Get(wkldInitImagePrompt, wkldInitImagePromptHelp, nil, gomock.Any()).
Return("", mockError)
},
mockSel: func(m *mocks.MockinitJobSelector) {
m.EXPECT().Dockerfile(
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePrompt, wantedJobName)),
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePathPrompt, wantedJobName)),
gomock.Eq(wkldInitDockerfileHelpPrompt),
gomock.Eq(wkldInitDockerfilePathHelpPrompt),
gomock.Any(),
).Return("Use an existing image instead", nil)
},
mockFileSystem: func(mockFS afero.Fs) {},
wantedErr: fmt.Errorf("get image location: mock error"),
},
"using existing image": {
inJobType: wantedJobType,
inJobName: wantedJobName,
inJobSchedule: wantedCronSchedule,
inDockerfilePath: "",

mockPrompt: func(m *mocks.Mockprompter) {
m.EXPECT().Get(wkldInitImagePrompt, wkldInitImagePromptHelp, nil, gomock.Any()).
Return("mockImage", nil)
},
mockSel: func(m *mocks.MockinitJobSelector) {
m.EXPECT().Dockerfile(
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePrompt, wantedJobName)),
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePathPrompt, wantedJobName)),
gomock.Eq(wkldInitDockerfileHelpPrompt),
gomock.Eq(wkldInitDockerfilePathHelpPrompt),
gomock.Any(),
).Return("Use an existing image instead", nil)
},
mockFileSystem: func(mockFS afero.Fs) {},
wantedSchedule: wantedCronSchedule,
},
"prompt for existing dockerfile": {
inJobType: wantedJobType,
inJobName: wantedJobName,
Expand Down
69 changes: 48 additions & 21 deletions internal/pkg/cli/svc_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ const (
fmtAddSvcToAppStart = "Creating ECR repositories for service %s."
fmtAddSvcToAppFailed = "Failed to create ECR repositories for service %s.\n"
fmtAddSvcToAppComplete = "Created ECR repositories for service %s.\n"

wkldInitImagePrompt = `What's the location of the image to use?`
wkldInitImagePromptHelp = `The location of an existing Docker image. Docker Hub registry are available by default.
Other repositories are specified with either repository-url/image:tag or repository-url/image@digest`
)

const (
Expand Down Expand Up @@ -161,9 +165,15 @@ func (o *initSvcOpts) Ask() error {
if err := o.askSvcName(); err != nil {
return err
}
if err := o.askDockerfile(); err != nil {
useImage, err := o.askDockerfile()
if err != nil {
return err
}
if useImage {
if err := o.askImage(); err != nil {
return err
}
}
if err := o.askSvcPort(); err != nil {
return err
}
Expand Down Expand Up @@ -327,10 +337,23 @@ func (o *initSvcOpts) askSvcName() error {
return nil
}

func (o *initSvcOpts) askImage() error {
if o.image != "" {
return nil
}
image, err := o.prompt.Get(wkldInitImagePrompt, wkldInitImagePromptHelp, nil,
prompt.WithFinalMessage("Image:"))
if err != nil {
return fmt.Errorf("get image location: %w", err)
}
o.image = image
return nil
}

// askDockerfile prompts for the Dockerfile by looking at sub-directories with a Dockerfile.
func (o *initSvcOpts) askDockerfile() error {
func (o *initSvcOpts) askDockerfile() (useImage bool, err error) {
if o.dockerfilePath != "" || o.image != "" {
return nil
return false, nil
}
df, err := o.sel.Dockerfile(
fmt.Sprintf(fmtWkldInitDockerfilePrompt, color.HighlightUserInput(o.name)),
Expand All @@ -342,10 +365,13 @@ func (o *initSvcOpts) askDockerfile() error {
},
)
if err != nil {
return err
return false, fmt.Errorf("select Dockerfile: %w", err)
}
if df == selector.DockerfilePromptUseImage {
return true, nil
}
o.dockerfilePath = df
return nil
return false, nil
}

func (o *initSvcOpts) askSvcPort() error {
Expand All @@ -354,22 +380,23 @@ func (o *initSvcOpts) askSvcPort() error {
return nil
}

o.setupParser(o)
ports, err := o.df.GetExposedPorts()
// Ignore any errors in dockerfile parsing--we'll use the default instead.
if err != nil {
log.Debugln(err.Error())
}
var defaultPort string
switch len(ports) {
case 0:
// There were no ports detected, keep the default port prompt.
defaultPort = defaultSvcPortString
case 1:
o.port = ports[0]
return nil
default:
defaultPort = strconv.Itoa(int(ports[0]))
defaultPort := defaultSvcPortString
if o.dockerfilePath != "" {
o.setupParser(o)
ports, err := o.df.GetExposedPorts()
// Ignore any errors in dockerfile parsing--we'll use the default instead.
if err != nil {
log.Debugln(err.Error())
}
switch len(ports) {
case 0:
// There were no ports detected, keep the default port prompt.
case 1:
o.port = ports[0]
return nil
default:
defaultPort = strconv.Itoa(int(ports[0]))
}
}

port, err := o.prompt.Get(
Expand Down
46 changes: 45 additions & 1 deletion internal/pkg/cli/svc_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,50 @@ func TestSvcInitOpts_Ask(t *testing.T) {
mockDockerfile: func(m *mocks.MockdockerfileParser) {},
wantedErr: nil,
},
"returns an error if fail to get image location": {
inSvcType: wantedSvcType,
inSvcName: wantedSvcName,
inSvcPort: wantedSvcPort,
inDockerfilePath: "",

mockPrompt: func(m *mocks.Mockprompter) {
m.EXPECT().Get(wkldInitImagePrompt, wkldInitImagePromptHelp, nil, gomock.Any()).
Return("", mockError)
},
mockSel: func(m *mocks.MockdockerfileSelector) {
m.EXPECT().Dockerfile(
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePrompt, wantedSvcName)),
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePathPrompt, wantedSvcName)),
gomock.Eq(wkldInitDockerfileHelpPrompt),
gomock.Eq(wkldInitDockerfilePathHelpPrompt),
gomock.Any(),
).Return("Use an existing image instead", nil)
},
mockDockerfile: func(m *mocks.MockdockerfileParser) {},
wantedErr: fmt.Errorf("get image location: mock error"),
},
"using existing image": {
inSvcType: wantedSvcType,
inSvcName: wantedSvcName,
inDockerfilePath: "",

mockPrompt: func(m *mocks.Mockprompter) {
m.EXPECT().Get(wkldInitImagePrompt, wkldInitImagePromptHelp, nil, gomock.Any()).
Return("mockImage", nil)
m.EXPECT().Get(gomock.Eq(fmt.Sprintf(svcInitSvcPortPrompt, "port")), gomock.Any(), gomock.Any(), gomock.Any()).
Return(defaultSvcPortString, nil)
},
mockSel: func(m *mocks.MockdockerfileSelector) {
m.EXPECT().Dockerfile(
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePrompt, wantedSvcName)),
gomock.Eq(fmt.Sprintf(fmtWkldInitDockerfilePathPrompt, wantedSvcName)),
gomock.Eq(wkldInitDockerfileHelpPrompt),
gomock.Eq(wkldInitDockerfilePathHelpPrompt),
gomock.Any(),
).Return("Use an existing image instead", nil)
},
mockDockerfile: func(m *mocks.MockdockerfileParser) {},
},
"select Dockerfile": {
inSvcType: wantedSvcType,
inSvcName: wantedSvcName,
Expand Down Expand Up @@ -221,7 +265,7 @@ func TestSvcInitOpts_Ask(t *testing.T) {
},
mockPrompt: func(m *mocks.Mockprompter) {},
mockDockerfile: func(m *mocks.MockdockerfileParser) {},
wantedErr: fmt.Errorf("some error"),
wantedErr: fmt.Errorf("select Dockerfile: some error"),
},
"asks for port if not specified": {
inSvcType: wantedSvcType,
Expand Down
32 changes: 18 additions & 14 deletions internal/pkg/term/selector/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,10 @@ const (
yearly = "Yearly"
)

var scheduleTypes = []string{
rate,
fixedSchedule,
}

var presetSchedules = []string{
custom,
hourly,
daily,
weekly,
monthly,
yearly,
}
const (
// DockerfilePromptUseImage is the option for using existing image instead of Dockerfile.
DockerfilePromptUseImage = "Use an existing image instead"

var (
ratePrompt = "How long would you like to wait between executions?"
rateHelp = `You can specify the time as a duration string. (For example, 2m, 1h30m, 24h)`

Expand All @@ -62,6 +51,20 @@ For example: 0 17 ? * MON-FRI (5 pm on weekdays)
(Y)es will continue execution. (N)o will allow you to input a different schedule.`
)

var scheduleTypes = []string{
rate,
fixedSchedule,
}

var presetSchedules = []string{
custom,
hourly,
daily,
weekly,
monthly,
yearly,
}

// Prompter wraps the methods to ask for inputs from the terminal.
type Prompter interface {
Get(message, help string, validator prompt.ValidatorFunc, promptOpts ...prompt.Option) (string, error)
Expand Down Expand Up @@ -436,6 +439,7 @@ func (s *WorkspaceSelect) Dockerfile(selPrompt, notFoundPrompt, selHelp, notFoun
// If Dockerfiles are found in the current directory or subdirectory one level down, ask the user to select one.
var sel string
if err == nil {
dockerfiles = append(dockerfiles, DockerfilePromptUseImage)
sel, err = s.prompt.SelectOne(
selPrompt,
selHelp,
Expand Down
7 changes: 6 additions & 1 deletion internal/pkg/term/selector/selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,12 @@ func TestWorkspaceSelect_Dockerfile(t *testing.T) {
mockPrompt: func(m *mocks.MockPrompter) {
m.EXPECT().SelectOne(
gomock.Any(), gomock.Any(),
gomock.Eq(dockerfiles),
gomock.Eq([]string{
"./Dockerfile",
"backend/Dockerfile",
"frontend/Dockerfile",
"Use an existing image instead",
}),
gomock.Any(),
).Return("frontend/Dockerfile", nil)
},
Expand Down

0 comments on commit 3a60e65

Please sign in to comment.