Skip to content

Commit

Permalink
z0 - add projest service-add
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Saidl committed Jun 23, 2024
1 parent 2ac4336 commit b2cfaf6
Show file tree
Hide file tree
Showing 10 changed files with 422 additions and 13 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/zeropsio/zcli

go 1.21

require github.com/zeropsio/zerops-go v1.0.8
require github.com/zeropsio/zerops-go v1.0.10

require (
github.com/charmbracelet/bubbles v0.18.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ github.com/zeropsio/zerops-go v1.0.7 h1:vtiaSSu3TrC18BlOxH5/PydUk1+BNDjQhhw6S80S
github.com/zeropsio/zerops-go v1.0.7/go.mod h1:Nuqf1xWt53IRLyVoXgR4hF4ICc9jlfOfQgnN3ZhJR3E=
github.com/zeropsio/zerops-go v1.0.8 h1:YhSS7+cW1fIRUE1tD5hpGlD3+opxzvI5lfsONgwdn28=
github.com/zeropsio/zerops-go v1.0.8/go.mod h1:Nuqf1xWt53IRLyVoXgR4hF4ICc9jlfOfQgnN3ZhJR3E=
github.com/zeropsio/zerops-go v1.0.9 h1:6x0L7RrS33KOf84S75tLM7N/lO7v/ilTA7rkNi8hGz0=
github.com/zeropsio/zerops-go v1.0.9/go.mod h1:Nuqf1xWt53IRLyVoXgR4hF4ICc9jlfOfQgnN3ZhJR3E=
github.com/zeropsio/zerops-go v1.0.10 h1:42zD02HQVKFu8Fc7NC+TtOaSdIIGdzl3Wm1XpR/Brao=
github.com/zeropsio/zerops-go v1.0.10/go.mod h1:Nuqf1xWt53IRLyVoXgR4hF4ICc9jlfOfQgnN3ZhJR3E=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ func projectCmd() *cmdBuilder.Cmd {
AddChildrenCmd(projectListCmd()).
AddChildrenCmd(projectDeleteCmd()).
AddChildrenCmd(projectServiceImportCmd()).
AddChildrenCmd(projectImportCmd())
AddChildrenCmd(projectImportCmd()).
AddChildrenCmd(projectServiceAddCmd())
}
94 changes: 94 additions & 0 deletions src/cmd/projectServiceAdd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package cmd

import (
"context"

"github.com/zeropsio/zcli/src/cmd/scope"
"github.com/zeropsio/zcli/src/cmdBuilder"
"github.com/zeropsio/zcli/src/entity"
"github.com/zeropsio/zcli/src/entity/repository"
"github.com/zeropsio/zcli/src/i18n"
"github.com/zeropsio/zcli/src/uxHelpers"
"github.com/zeropsio/zerops-go/dto/input/body"
"github.com/zeropsio/zerops-go/dto/input/path"
"github.com/zeropsio/zerops-go/types"
"github.com/zeropsio/zerops-go/types/stringId"
)

const serviceAddArgName = "serviceAddName"
const serviceAddArgType = "type"

func projectServiceAddCmd() *cmdBuilder.Cmd {
return cmdBuilder.NewCmd().
Use("service-add").
Short(i18n.T(i18n.CmdDescProjectServiceAdd)).
ScopeLevel(scope.Project).
Arg(serviceAddArgName).
StringFlag(serviceAddArgType, "", i18n.T(i18n.ServiceTypeFlag)).
HelpFlag(i18n.T(i18n.CmdHelpProjectServiceAdd)).
LoggedUserRunFunc(func(ctx context.Context, cmdData *cmdBuilder.LoggedUserCmdData) error {
name := cmdData.Args[serviceAddArgName][0]

var typeNameVersion entity.ServiceStackTypeVersion
var typeNameVersionId stringId.ServiceStackTypeVersionId

if cmdData.Params.GetString(serviceAddArgType) == "" {
serviceStackType, err := uxHelpers.PrintServiceStackTypeSelector(ctx, cmdData.UxBlocks, cmdData.RestApiClient)
if err != nil {
return err
}
if len(serviceStackType.Versions) == 1 {
typeNameVersion = serviceStackType.Versions[0]
} else {
typeNameVersion, err = uxHelpers.PrintServiceStackTypeVersionSelector(ctx, cmdData.UxBlocks, cmdData.RestApiClient,
uxHelpers.PrintServiceStackTypeVersionSelectorWithServiceStackTypeIdFilter(serviceStackType),
)
if err != nil {
return err
}
}
typeNameVersionId = typeNameVersion.ID
} else {
input := cmdData.Params.GetString(serviceAddArgType)
serviceStackType, err := repository.GetServiceStackTypeById(ctx, cmdData.RestApiClient, stringId.ServiceStackTypeId(input))
if err != nil {
return err
}
typeNameVersionId = serviceStackType.Versions[0].ID
}

serviceAddResponse, err := cmdData.RestApiClient.PostServiceStack(ctx,
path.ServiceStackServiceStackTypeVersionId{
ServiceStackTypeVersionId: typeNameVersionId,
},
body.PostStandardServiceStack{
ProjectId: cmdData.Project.ID,
Name: types.NewString(name),
},
)
if err != nil {
return err
}

serviceAddOutput, err := serviceAddResponse.Output()
if err != nil {
return err
}

err = uxHelpers.ProcessCheckWithSpinner(
ctx,
cmdData.UxBlocks,
[]uxHelpers.Process{{
F: uxHelpers.CheckZeropsProcess(serviceAddOutput.Process.Id, cmdData.RestApiClient),
RunningMessage: i18n.T(i18n.ServiceAdding),
ErrorMessageMessage: i18n.T(i18n.ServiceAddFailed),
SuccessMessage: i18n.T(i18n.ServiceAdded),
}},
)
if err != nil {
return err
}

return nil
})
}
83 changes: 83 additions & 0 deletions src/entity/repository/serviceStackType.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package repository

import (
"context"
"errors"
"sort"

"github.com/zeropsio/zcli/src/entity"
"github.com/zeropsio/zcli/src/zeropsRestApiClient"
"github.com/zeropsio/zerops-go/errorCode"
"github.com/zeropsio/zerops-go/types/stringId"
)

func GetServiceStackTypes(
ctx context.Context,
restApiClient *zeropsRestApiClient.Handler,
) (result []entity.ServiceStackType, _ error) {
settings, err := restApiClient.GetSettings(ctx)
if err != nil {
return nil, err
}
settingsOutput, err := settings.Output()
if err != nil {
return nil, err
}
for _, serviceStackType := range settingsOutput.ServiceStackList {
e := entity.ServiceStackType{
ID: serviceStackType.Id,
Name: serviceStackType.Name,
}

for _, serviceStackTypeVersion := range serviceStackType.ServiceStackTypeVersionList {
if !serviceStackTypeVersion.Status.IsActive() {
continue
}
if serviceStackTypeVersion.IsBuild.Native() {
continue
}
if serviceStackTypeVersion.Name.Native() == "prepare_runtime" {
continue
}
e.Versions = append(e.Versions, entity.ServiceStackTypeVersion{
ID: serviceStackTypeVersion.Id,
Name: serviceStackTypeVersion.Name,
ExactVersionNumber: serviceStackTypeVersion.ExactVersionNumber,
})
}
if len(e.Versions) == 0 {
continue
}
result = append(result, e)
}
sort.Slice(result, func(i, j int) bool { return result[i].Name.Native() < result[j].Name.Native() })
return result, nil
}

func GetServiceStackTypeById(
ctx context.Context,
restApiClient *zeropsRestApiClient.Handler,
serviceStackTypeId stringId.ServiceStackTypeId,
) (result entity.ServiceStackType, _ error) {
serviceStackTypes, err := GetServiceStackTypes(ctx, restApiClient)
if err != nil {
return result, err
}
for _, serviceStackType := range serviceStackTypes {
if serviceStackType.ID == serviceStackTypeId {
return serviceStackType, nil
}
if serviceStackType.Name.Native() == serviceStackTypeId.Native() {
return serviceStackType, nil
}
for _, serviceStackTypeVersion := range serviceStackType.Versions {
if serviceStackTypeVersion.ID.Native() == serviceStackTypeId.Native() {
return serviceStackType, nil
}
if serviceStackTypeVersion.Name.Native() == serviceStackTypeId.Native() {
return serviceStackType, nil
}
}
}
return result, errors.New(string(errorCode.ServiceStackTypeVersionNotFound))
}
18 changes: 18 additions & 0 deletions src/entity/serviceStackType.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package entity

import (
"github.com/zeropsio/zerops-go/types"
"github.com/zeropsio/zerops-go/types/stringId"
)

type ServiceStackType struct {
ID stringId.ServiceStackTypeId
Name types.String
Versions []ServiceStackTypeVersion
}

type ServiceStackTypeVersion struct {
ID stringId.ServiceStackTypeVersionId
Name types.String
ExactVersionNumber types.EmptyString
}
35 changes: 24 additions & 11 deletions src/i18n/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ const (
CmdDescProjectServiceImport = "CmdDescProjectServiceImport"
ServiceImported = "ServiceImported"

// project service add
CmdHelpProjectServiceAdd = "CmdHelpProjectServiceAdd"
CmdDescProjectServiceAdd = "CmdDescProjectServiceAdd"
ServiceAdded = "Service added"
ServiceAdding = "Service adding"
ServiceAddFailed = "Service add failed"

// service
CmdHelpService = "CmdHelpService"
CmdDescService = "CmdDescService"
Expand Down Expand Up @@ -224,6 +231,7 @@ const (
ConfirmFlag = "ConfirmFlag"
ServiceIdFlag = "ServiceIdFlag"
ProjectIdFlag = "ProjectIdFlag"
ServiceTypeFlag = "ServiceTypeFlag"
VpnAutoDisconnectFlag = "VpnAutoDisconnectFlag"
ZeropsYamlSetup = "ZeropsYamlSetup"

Expand Down Expand Up @@ -276,17 +284,22 @@ const (
ArgsTooManyArgs = "ArgsTooManyArgs"

// ux helpers
ProjectSelectorListEmpty = "ProjectSelectorListEmpty"
ProjectSelectorPrompt = "ProjectSelectorPrompt"
ProjectSelectorOutOfRangeError = "ProjectSelectorOutOfRangeError"
ServiceSelectorListEmpty = "ServiceSelectorListEmpty"
ServiceSelectorPrompt = "ServiceSelectorPrompt"
ServiceSelectorOutOfRangeError = "ServiceSelectorOutOfRangeError"
OrgSelectorListEmpty = "OrgSelectorListEmpty"
OrgSelectorPrompt = "OrgSelectorPrompt"
OrgSelectorOutOfRangeError = "OrgSelectorOutOfRangeError"
SelectorAllowedOnlyInTerminal = "SelectorAllowedOnlyInTerminal"
PromptAllowedOnlyInTerminal = "PromptAllowedOnlyInTerminal"
ProjectSelectorListEmpty = "ProjectSelectorListEmpty"
ProjectSelectorPrompt = "ProjectSelectorPrompt"
ProjectSelectorOutOfRangeError = "ProjectSelectorOutOfRangeError"
ServiceSelectorListEmpty = "ServiceSelectorListEmpty"
ServiceStackTypesSelectorListEmpty = "ServiceStackTypeSelectorListEmpty"
ServiceSelectorPrompt = "ServiceSelectorPrompt"
ServiceStackTypeSelectorPrompt = "ServiceStackTypeSelectorPrompt"
ServiceStackTypeSelectorOutOfRangeError = "ServiceStackTypeSelectorOutOfRangeError"
ServiceStackTypeVersionSelectorPrompt = "ServiceStackTypeVersionSelectorPrompt"
ServiceStackTypeVersionSelectorOutOfRangeError = "ServiceStackTypeVersionSelectorOutOfRangeError"
ServiceSelectorOutOfRangeError = "ServiceSelectorOutOfRangeError"
OrgSelectorListEmpty = "OrgSelectorListEmpty"
OrgSelectorPrompt = "OrgSelectorPrompt"
OrgSelectorOutOfRangeError = "OrgSelectorOutOfRangeError"
SelectorAllowedOnlyInTerminal = "SelectorAllowedOnlyInTerminal"
PromptAllowedOnlyInTerminal = "PromptAllowedOnlyInTerminal"

UnauthenticatedUser = "UnauthenticatedUser"

Expand Down
32 changes: 32 additions & 0 deletions src/options/option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package options

type OptionError[T any] func(*T) error

func ApplyOptionsError[K any, T ~func(*K) error](in ...T) (K, []error) {
var emptyValue K
return ApplyOptionsErrorWithDefault[K](emptyValue, in...)
}

func ApplyOptionsErrorWithDefault[K any, T ~func(*K) error](k K, in ...T) (K, []error) {
var errors []error
for _, o := range in {
if err := o(&k); err != nil {
errors = append(errors, err)
}
}
return k, errors
}

type Option[T any] func(*T)

func ApplyOptions[K any, T ~func(*K)](in ...T) K {
var emptyValue K
return ApplyOptionsWithDefault(emptyValue, in...)
}

func ApplyOptionsWithDefault[K any, T ~func(*K)](k K, in ...T) K {
for _, o := range in {
o(&k)
}
return k
}
31 changes: 31 additions & 0 deletions src/uxHelpers/serviceStackType.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package uxHelpers

import (
"context"

"github.com/zeropsio/zcli/src/entity"
"github.com/zeropsio/zcli/src/entity/repository"
"github.com/zeropsio/zcli/src/i18n"
"github.com/zeropsio/zcli/src/uxBlock"
"github.com/zeropsio/zcli/src/zeropsRestApiClient"
)

func PrintServiceStackTypeSelector(
ctx context.Context,
uxBlocks uxBlock.UxBlocks,
restApiClient *zeropsRestApiClient.Handler,
) (result entity.ServiceStackType, _ error) {
serviceStackTypes, err := repository.GetServiceStackTypes(ctx, restApiClient)
if err != nil {
return result, err
}

return SelectOne(ctx, uxBlocks, serviceStackTypes,
SelectOneWithHeader[entity.ServiceStackType]("ID", "Name"),
SelectOneWithSelectLabel[entity.ServiceStackType](i18n.T(i18n.ServiceStackTypeSelectorPrompt)),
SelectOneWithNotFound[entity.ServiceStackType](i18n.T(i18n.ServiceStackTypeSelectorOutOfRangeError)),
SelectOneWithRow(func(in entity.ServiceStackType) []string {
return []string{string(in.ID), in.Name.String()}
}),
)
}
Loading

0 comments on commit b2cfaf6

Please sign in to comment.