Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/koyeb/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func NewAppCmd() *cobra.Command {
Short: "List apps",
RunE: WithCLIContext(h.List),
}
listAppCmd.Flags().Bool("all-projects", false, "List apps from all projects")
appCmd.AddCommand(listAppCmd)

describeAppCmd := &cobra.Command{
Expand Down
1 change: 1 addition & 0 deletions pkg/koyeb/apps_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (h *AppHandler) CreateApp(ctx *CLIContext, payload *koyeb.CreateApp) (*koye

func (h *AppHandler) Create(ctx *CLIContext, cmd *cobra.Command, args []string, createApp *koyeb.CreateApp) error {
createApp.SetName(args[0])
applyProjectID(createApp, ctx.Project)

res, err := h.CreateApp(ctx, createApp)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/koyeb/apps_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (h *AppHandler) Init(ctx *CLIContext, cmd *cobra.Command, args []string, cr

uid := uuid.Must(uuid.NewV4())
createService.SetAppId(uid.String())
applyProjectID(createService, ctx.Project)
_, resp, err := ctx.Client.ServicesApi.CreateService(ctx.Context).DryRun(true).Service(*createService).Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
Expand All @@ -32,6 +33,7 @@ func (h *AppHandler) Init(ctx *CLIContext, cmd *cobra.Command, args []string, cr
}

createApp.SetName(args[0])
applyProjectID(createApp, ctx.Project)
res, resp, err := ctx.Client.AppsApi.CreateApp(ctx.Context).App(*createApp).Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
Expand Down
9 changes: 7 additions & 2 deletions pkg/koyeb/apps_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ func (h *AppHandler) List(ctx *CLIContext, cmd *cobra.Command, args []string) er
offset := int64(0)
limit := int64(100)
for {
res, resp, err := ctx.Client.AppsApi.ListApps(ctx.Context).
Limit(strconv.FormatInt(limit, 10)).Offset(strconv.FormatInt(offset, 10)).Execute()
req := ctx.Client.AppsApi.ListApps(ctx.Context).
Limit(strconv.FormatInt(limit, 10)).
Offset(strconv.FormatInt(offset, 10))
if ctx.Project != "" {
req = req.ProjectId(ctx.Project)
}
res, resp, err := req.Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
"Error while listing the applications",
Expand Down
1 change: 1 addition & 0 deletions pkg/koyeb/archives_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (h *ArchiveHandler) CreateArchive(ctx *CLIContext, path string) (*koyeb.Cre
// because the underlying type to store the size is uint64, which is not
// representable in JSON.
c.SetSize(fmt.Sprintf("%d", stat.Size()))
applyProjectID(c, ctx.Project)

res, resp, err := ctx.Client.ArchivesApi.CreateArchive(ctx.Context).Archive(*c).Execute()
if err != nil {
Expand Down
49 changes: 47 additions & 2 deletions pkg/koyeb/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@ const (
ctx_mapper
ctx_renderer
ctx_organization
ctx_project
)

func topLevelCommand(cmd *cobra.Command) *cobra.Command {
current := cmd
for current.Parent() != nil && current.Parent().Parent() != nil {
current = current.Parent()
}
return current
}

// SetupCLIContext is called by the root command to setup the context for all subcommands.
// When `organization` is not empty, it should contain the ID of the organization to switch the context to.
func SetupCLIContext(cmd *cobra.Command, organization string) error {
func SetupCLIContext(cmd *cobra.Command, organization string, project string) error {
apiClient, err := getApiClient()
if err != nil {
return err
Expand All @@ -43,6 +52,39 @@ func SetupCLIContext(cmd *cobra.Command, organization string) error {
cmd.SetContext(ctx)
}

activeProject := ""
topLevel := topLevelCommand(cmd)
if flag := cmd.Flags().Lookup("all-projects"); flag != nil {
allProjects, err := cmd.Flags().GetBool("all-projects")
if err != nil {
return err
}
if allProjects {
project = ""
}
}
if topLevel.Name() == "organizations" || topLevel.Name() == "projects" {
project = ""
}
if project == "" {
project, err = getOrganizationDefaultProjectID(&CLIContext{
Context: ctx,
Client: apiClient,
Token: ctx.Value(koyeb.ContextAccessToken).(string),
Organization: organization,
})
if err != nil {
return err
}
}
if project != "" {
projectMapper := idmapper.NewProjectMapper(ctx, apiClient)
activeProject, err = projectMapper.ResolveID(project)
if err != nil {
return err
}
}

ctx = context.WithValue(ctx, ctx_client, apiClient)

logsApiClient, err := NewLogsAPIClient(apiClient, apiurl, ctx.Value(koyeb.ContextAccessToken).(string))
Expand All @@ -57,9 +99,10 @@ func SetupCLIContext(cmd *cobra.Command, organization string) error {
}
ctx = context.WithValue(ctx, ctx_exec_client, execApiClient)

ctx = context.WithValue(ctx, ctx_mapper, idmapper.NewMapper(ctx, apiClient))
ctx = context.WithValue(ctx, ctx_mapper, idmapper.NewMapper(ctx, apiClient, activeProject))
ctx = context.WithValue(ctx, ctx_renderer, renderer.NewRenderer(outputFormat))
ctx = context.WithValue(ctx, ctx_organization, organization)
ctx = context.WithValue(ctx, ctx_project, activeProject)
cmd.SetContext(ctx)

return nil
Expand All @@ -74,6 +117,7 @@ type CLIContext struct {
Token string
Renderer renderer.Renderer
Organization string
Project string
}

// GetCLIContext transforms the untyped context passed to cobra commands into a CLIContext.
Expand All @@ -87,6 +131,7 @@ func GetCLIContext(ctx context.Context) *CLIContext {
Token: ctx.Value(koyeb.ContextAccessToken).(string),
Renderer: ctx.Value(ctx_renderer).(renderer.Renderer),
Organization: ctx.Value(ctx_organization).(string),
Project: ctx.Value(ctx_project).(string),
}
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/koyeb/databases_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
func TryCreateKoyebApplication(name string, ctx *CLIContext) error {
createApp := koyeb.NewCreateAppWithDefaults()
createApp.SetName(name)
applyProjectID(createApp, ctx.Project)

_, resp, err := ctx.Client.AppsApi.CreateApp(ctx.Context).App(*createApp).Execute()
if err != nil {
Expand Down Expand Up @@ -56,6 +57,7 @@ func (h *DatabaseHandler) Create(ctx *CLIContext, cmd *cobra.Command, args []str
}

createService.SetAppId(appID)
applyProjectID(createService, ctx.Project)
res, resp, err := ctx.Client.ServicesApi.CreateService(ctx.Context).Service(*createService).Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
Expand Down
9 changes: 6 additions & 3 deletions pkg/koyeb/databases_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ func (h *DatabaseHandler) List(ctx *CLIContext, cmd *cobra.Command, args []strin
offset := int64(0)
limit := int64(100)
for {
res, resp, err := ctx.Client.ServicesApi.ListServices(ctx.Context).
req := ctx.Client.ServicesApi.ListServices(ctx.Context).
Limit(strconv.FormatInt(limit, 10)).
Offset(strconv.FormatInt(offset, 10)).
Types([]string{"DATABASE"}).
Execute()
Types([]string{"DATABASE"})
if ctx.Project != "" {
req = req.ProjectId(ctx.Project)
}
res, resp, err := req.Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
"Error while listing database services",
Expand Down
1 change: 1 addition & 0 deletions pkg/koyeb/domains_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func (h *DomainHandler) Create(ctx *CLIContext, cmd *cobra.Command, args []strin
createDomainReq := koyeb.NewCreateDomainWithDefaults()
createDomainReq.SetName(args[0])
createDomainReq.SetType(koyeb.DOMAINTYPE_CUSTOM)
applyProjectID(createDomainReq, ctx.Project)

attachToApp := GetStringFlags(cmd, "attach-to")
if attachToApp != "" {
Expand Down
9 changes: 6 additions & 3 deletions pkg/koyeb/domains_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ func (h *DomainHandler) List(ctx *CLIContext, cmd *cobra.Command, args []string)
offset := int64(0)
limit := int64(100)
for {
res, resp, err := ctx.Client.DomainsApi.ListDomains(ctx.Context).
req := ctx.Client.DomainsApi.ListDomains(ctx.Context).
Limit(strconv.FormatInt(limit, 10)).
Offset(strconv.FormatInt(offset, 10)).
Types([]string{string(koyeb.DOMAINTYPE_CUSTOM)}).
Execute()
Types([]string{string(koyeb.DOMAINTYPE_CUSTOM)})
if ctx.Project != "" {
req = req.ProjectId(ctx.Project)
}
res, resp, err := req.Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
"Error while listing the domains",
Expand Down
45 changes: 40 additions & 5 deletions pkg/koyeb/idmapper/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import (
type AppMapper struct {
ctx context.Context
client *koyeb.APIClient
project string
fetched bool
sidMap *IDMap
nameMap *IDMap
autoDomainMap *IDMap
}

func NewAppMapper(ctx context.Context, client *koyeb.APIClient) *AppMapper {
func NewAppMapper(ctx context.Context, client *koyeb.APIClient, project string) *AppMapper {
return &AppMapper{
ctx: ctx,
client: client,
project: project,
fetched: false,
sidMap: NewIDMap(),
nameMap: NewIDMap(),
Expand Down Expand Up @@ -67,7 +69,16 @@ func (mapper *AppMapper) GetName(id string) (string, error) {

name, ok := mapper.nameMap.GetValue(id)
if !ok {
return "", fmt.Errorf("app name not found for %q", id)
res, resp, err := mapper.client.AppsApi.GetApp(mapper.ctx, id).Execute()
if err != nil {
return "", errors.NewCLIErrorFromAPIError(
fmt.Sprintf("Error retrieving the application %q", id),
err,
resp,
)
}
app := res.GetApp()
return app.GetName(), nil
}

return name, nil
Expand All @@ -83,6 +94,27 @@ func (mapper *AppMapper) GetAutoDomain(id string) (string, error) {

name, ok := mapper.autoDomainMap.GetValue(id)
if !ok {
res, resp, err := mapper.client.AppsApi.GetApp(mapper.ctx, id).Execute()
if err != nil {
return "", errors.NewCLIErrorFromAPIError(
fmt.Sprintf("Error retrieving the application %q", id),
err,
resp,
)
}
app := res.GetApp()
for _, domain := range app.GetDomains() {
if domain.GetType() != koyeb.DOMAINTYPE_AUTOASSIGNED {
continue
}

if !domain.HasCloudflare() {
continue
}

return domain.GetId(), nil
}

return "", fmt.Errorf("app automatic domain not found for %q", id)
}

Expand All @@ -97,10 +129,13 @@ func (mapper *AppMapper) fetch() error {
limit := int64(100)
for {

res, resp, err := mapper.client.AppsApi.ListApps(mapper.ctx).
req := mapper.client.AppsApi.ListApps(mapper.ctx).
Limit(strconv.FormatInt(limit, 10)).
Offset(strconv.FormatInt(offset, 10)).
Execute()
Offset(strconv.FormatInt(offset, 10))
if mapper.project != "" {
req = req.ProjectId(mapper.project)
}
res, resp, err := req.Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
"Error listing applications to resolve the provided identifier to an object ID",
Expand Down
13 changes: 9 additions & 4 deletions pkg/koyeb/idmapper/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ import (
type DomainMapper struct {
ctx context.Context
client *koyeb.APIClient
project string
fetched bool
sidMap *IDMap
nameMap *IDMap
}

func NewDomainMapper(ctx context.Context, client *koyeb.APIClient) *DomainMapper {
func NewDomainMapper(ctx context.Context, client *koyeb.APIClient, project string) *DomainMapper {
return &DomainMapper{
ctx: ctx,
client: client,
project: project,
fetched: false,
sidMap: NewIDMap(),
nameMap: NewIDMap(),
Expand Down Expand Up @@ -80,10 +82,13 @@ func (mapper *DomainMapper) fetch() error {
limit := int64(100)
for {

res, resp, err := mapper.client.DomainsApi.ListDomains(mapper.ctx).
req := mapper.client.DomainsApi.ListDomains(mapper.ctx).
Limit(strconv.FormatInt(limit, 10)).
Offset(strconv.FormatInt(offset, 10)).
Execute()
Offset(strconv.FormatInt(offset, 10))
if mapper.project != "" {
req = req.ProjectId(mapper.project)
}
res, resp, err := req.Execute()
if err != nil {
return errors.NewCLIErrorFromAPIError(
"Error listing domains to resolve the provided identifier to an object ID",
Expand Down
19 changes: 13 additions & 6 deletions pkg/koyeb/idmapper/idmapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,26 @@ type Mapper struct {
deployment *DeploymentMapper
regional *RegionalDeploymentMapper
instance *InstanceMapper
project *ProjectMapper
secret *SecretMapper
organization *OrganizationMapper
database *DatabaseMapper
volume *VolumeMapper
snapshot *SnapshotMapper
}

func NewMapper(ctx context.Context, client *koyeb.APIClient) *Mapper {
appMapper := NewAppMapper(ctx, client)
domainMapper := NewDomainMapper(ctx, client)
serviceMapper := NewServiceMapper(ctx, client, appMapper)
func NewMapper(ctx context.Context, client *koyeb.APIClient, project string) *Mapper {
projectMapper := NewProjectMapper(ctx, client)
appMapper := NewAppMapper(ctx, client, project)
domainMapper := NewDomainMapper(ctx, client, project)
serviceMapper := NewServiceMapper(ctx, client, appMapper, project)
deploymentMapper := NewDeploymentMapper(ctx, client)
regionalMapper := NewRegionalDeploymentMapper(ctx, client)
instanceMapper := NewInstanceMapper(ctx, client)
secretMapper := NewSecretMapper(ctx, client)
secretMapper := NewSecretMapper(ctx, client, project)
organizationMapper := NewOrganizationMapper(ctx, client)
databaseMapper := NewDatabaseMapper(ctx, client, appMapper)
volumeMapper := NewVolumeMapper(ctx, client)
volumeMapper := NewVolumeMapper(ctx, client, project)
snapshotMapper := NewSnapshotMapper(ctx, client)

return &Mapper{
Expand All @@ -40,6 +42,7 @@ func NewMapper(ctx context.Context, client *koyeb.APIClient) *Mapper {
deployment: deploymentMapper,
regional: regionalMapper,
instance: instanceMapper,
project: projectMapper,
secret: secretMapper,
organization: organizationMapper,
database: databaseMapper,
Expand Down Expand Up @@ -72,6 +75,10 @@ func (mapper *Mapper) Instance() *InstanceMapper {
return mapper.instance
}

func (mapper *Mapper) Project() *ProjectMapper {
return mapper.project
}

func (mapper *Mapper) Secret() *SecretMapper {
return mapper.secret
}
Expand Down
Loading
Loading