Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.
Merged
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
4 changes: 2 additions & 2 deletions coder-sdk/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ type Client interface {
APIVersion(ctx context.Context) (string, error)

// WorkspaceProviderByID fetches a workspace provider entity by its unique ID.
WorkspaceProviderByID(ctx context.Context, id string) (*WorkspaceProvider, error)
WorkspaceProviderByID(ctx context.Context, id string) (*KubernetesProvider, error)

// WorkspaceProviders fetches all workspace providers known to the Coder control plane.
WorkspaceProviders(ctx context.Context) ([]WorkspaceProvider, error)
WorkspaceProviders(ctx context.Context) (*WorkspaceProviders, error)

// CreateWorkspaceProvider creates a new WorkspaceProvider entity.
CreateWorkspaceProvider(ctx context.Context, req CreateWorkspaceProviderReq) (*CreateWorkspaceProviderRes, error)
Expand Down
50 changes: 30 additions & 20 deletions coder-sdk/workspace_providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,31 @@ import (
"net/http"
)

// WorkspaceProvider defines an entity capable of deploying and acting as an ingress for Coder environments.
type WorkspaceProvider struct {
ID string `json:"id" table:"-"`
Name string `json:"name" table:"Name"`
Status WorkspaceProviderStatus `json:"status" table:"Status"`
Local bool `json:"local" table:"-"`
ClusterAddress string `json:"cluster_address" table:"Cluster Address"`
DefaultNamespace string `json:"default_namespace" table:"Namespace"`
StorageClass string `json:"storage_class" table:"Storage Class"`
ClusterDomainSuffix string `json:"cluster_domain_suffix" table:"Cluster Domain Suffix"`
EnvproxyAccessURL string `json:"envproxy_access_url" validate:"required" table:"Access URL"`
DevurlHost string `json:"devurl_host" table:"Devurl Host"`
SSHEnabled bool `json:"ssh_enabled" table:"SSH Enabled"`
NamespaceWhitelist []string `json:"namespace_whitelist" table:"Namespace Allowlist"`
OrgWhitelist []string `json:"org_whitelist" table:"-"`
// WorkspaceProviders defines all available Coder workspace provider targets.
type WorkspaceProviders struct {
Kubernetes []KubernetesProvider `json:"kubernetes"`
}

// KubernetesProvider defines an entity capable of deploying and acting as an ingress for Coder environments.
type KubernetesProvider struct {
ID string `json:"id" table:"-"`
Name string `json:"name" table:"Name"`
Status WorkspaceProviderStatus `json:"status" table:"Status"`
Local bool `json:"local" table:"-"`
EnvproxyAccessURL string `json:"envproxy_access_url" validate:"required" table:"Access URL"`
DevurlHost string `json:"devurl_host" table:"Devurl Host"`
OrgWhitelist []string `json:"org_whitelist" table:"-"`
KubeProviderConfig `json:"config"`
}

// KubeProviderConfig defines Kubernetes-specific configuration options.
type KubeProviderConfig struct {
ClusterAddress string `json:"cluster_address" table:"Cluster Address"`
DefaultNamespace string `json:"default_namespace" table:"Namespace"`
StorageClass string `json:"storage_class" table:"Storage Class"`
ClusterDomainSuffix string `json:"cluster_domain_suffix" table:"Cluster Domain Suffix"`
SSHEnabled bool `json:"ssh_enabled" table:"SSH Enabled"`
NamespaceWhitelist []string `json:"namespace_whitelist" table:"Namespace Allowlist"`
}

// WorkspaceProviderStatus represents the configuration state of a workspace provider.
Expand All @@ -32,8 +42,8 @@ const (
)

// WorkspaceProviderByID fetches a workspace provider entity by its unique ID.
func (c *DefaultClient) WorkspaceProviderByID(ctx context.Context, id string) (*WorkspaceProvider, error) {
var wp WorkspaceProvider
func (c *DefaultClient) WorkspaceProviderByID(ctx context.Context, id string) (*KubernetesProvider, error) {
var wp KubernetesProvider
err := c.requestBody(ctx, http.MethodGet, "/api/private/resource-pools/"+id, nil, &wp)
if err != nil {
return nil, err
Expand All @@ -42,13 +52,13 @@ func (c *DefaultClient) WorkspaceProviderByID(ctx context.Context, id string) (*
}

// WorkspaceProviders fetches all workspace providers known to the Coder control plane.
func (c *DefaultClient) WorkspaceProviders(ctx context.Context) ([]WorkspaceProvider, error) {
var providers []WorkspaceProvider
func (c *DefaultClient) WorkspaceProviders(ctx context.Context) (*WorkspaceProviders, error) {
var providers WorkspaceProviders
err := c.requestBody(ctx, http.MethodGet, "/api/private/resource-pools", nil, &providers)
if err != nil {
return nil, err
}
return providers, nil
return &providers, nil
}

// CreateWorkspaceProviderReq defines the request parameters for creating a new workspace provider entity.
Expand Down
1 change: 1 addition & 0 deletions docs/coder_envs_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ub
-i, --image string name of the image to base the environment off of.
-m, --memory float32 GB of RAM an environment should be provisioned with.
-o, --org string name of the organization the environment should be created under.
--provider string name of Workspace Provider with which to create the environment
-t, --tag string tag of the image the environment will be based off of. (default "latest")
```

Expand Down
46 changes: 29 additions & 17 deletions internal/cmd/envs.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,16 @@ coder envs --user charlie@coder.com ls -o json \

func createEnvCmd() *cobra.Command {
var (
org string
cpu float32
memory float32
disk int
gpus int
img string
tag string
follow bool
useCVM bool
org string
cpu float32
memory float32
disk int
gpus int
img string
tag string
follow bool
useCVM bool
providerName string
)

cmd := &cobra.Command{
Expand Down Expand Up @@ -199,9 +200,17 @@ coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ub
return err
}

provider, err := coderutil.DefaultWorkspaceProvider(ctx, client)
if err != nil {
return xerrors.Errorf("default workspace provider: %w", err)
var provider *coder.KubernetesProvider
if providerName == "" {
provider, err = coderutil.DefaultWorkspaceProvider(ctx, client)
if err != nil {
return xerrors.Errorf("default workspace provider: %w", err)
}
} else {
provider, err = coderutil.ProviderByName(ctx, client, providerName)
if err != nil {
return xerrors.Errorf("provider by name: %w", err)
}
}

// ExactArgs(1) ensures our name value can't panic on an out of bounds.
Expand Down Expand Up @@ -258,6 +267,7 @@ coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ub
cmd.Flags().IntVarP(&disk, "disk", "d", 0, "GB of disk storage an environment should be provisioned with.")
cmd.Flags().IntVarP(&gpus, "gpus", "g", 0, "number GPUs an environment should be provisioned with.")
cmd.Flags().StringVarP(&img, "image", "i", "", "name of the image to base the environment off of.")
cmd.Flags().StringVar(&providerName, "provider", "", "name of Workspace Provider with which to create the environment")
cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild")
cmd.Flags().BoolVar(&useCVM, "container-based-vm", false, "deploy the environment as a Container-based VM")
_ = cmd.MarkFlagRequired("image")
Expand All @@ -266,11 +276,12 @@ coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ub

func createEnvFromRepoCmd() *cobra.Command {
var (
ref string
repo string
follow bool
filepath string
org string
ref string
repo string
follow bool
filepath string
org string
providerName string
)

cmd := &cobra.Command{
Expand Down Expand Up @@ -382,6 +393,7 @@ coder envs create-from-repo -f coder.yaml`,
cmd.Flags().StringVarP(&ref, "ref", "", "master", "git reference to pull template from. May be a branch, tag, or commit hash.")
cmd.Flags().StringVarP(&repo, "repo-url", "r", "", "URL of the git repository to pull the config from. Config file must live in '.coder/coder.yaml'.")
cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild")
cmd.Flags().StringVar(&providerName, "provider", "", "name of Workspace Provider with which to create the environment")
return cmd
}

Expand Down
6 changes: 3 additions & 3 deletions internal/cmd/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ coder providers ls`,
return xerrors.Errorf("list workspace providers: %w", err)
}

err = tablewriter.WriteTable(len(wps), func(i int) interface{} {
return wps[i]
err = tablewriter.WriteTable(len(wps.Kubernetes), func(i int) interface{} {
return wps.Kubernetes[i]
})
if err != nil {
return xerrors.Errorf("write table: %w", err)
Expand Down Expand Up @@ -122,7 +122,7 @@ coder providers rm my-workspace-provider`,
name := wpName
egroup.Go(func() error {
var id string
for _, wp := range wps {
for _, wp := range wps.Kubernetes {
if wp.Name == name {
id = wp.ID
}
Expand Down
10 changes: 5 additions & 5 deletions internal/coderutil/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func DialEnvWsep(ctx context.Context, client coder.Client, env *coder.Environmen
// EnvWithWorkspaceProvider composes an Environment entity with its associated WorkspaceProvider.
type EnvWithWorkspaceProvider struct {
Env coder.Environment
WorkspaceProvider coder.WorkspaceProvider
WorkspaceProvider coder.KubernetesProvider
}

// EnvsWithProvider performs the composition of each Environment with its associated WorkspaceProvider.
Expand All @@ -42,8 +42,8 @@ func EnvsWithProvider(ctx context.Context, client coder.Client, envs []coder.Env
if err != nil {
return nil, err
}
providerMap := make(map[string]coder.WorkspaceProvider, len(providers))
for _, p := range providers {
providerMap := make(map[string]coder.KubernetesProvider, len(providers.Kubernetes))
for _, p := range providers.Kubernetes {
providerMap[p.ID] = p
}
for _, e := range envs {
Expand All @@ -60,12 +60,12 @@ func EnvsWithProvider(ctx context.Context, client coder.Client, envs []coder.Env
}

// DefaultWorkspaceProvider returns the default provider with which to create environments.
func DefaultWorkspaceProvider(ctx context.Context, c coder.Client) (*coder.WorkspaceProvider, error) {
func DefaultWorkspaceProvider(ctx context.Context, c coder.Client) (*coder.KubernetesProvider, error) {
provider, err := c.WorkspaceProviders(ctx)
if err != nil {
return nil, err
}
for _, p := range provider {
for _, p := range provider.Kubernetes {
if p.Local {
return &p, nil
}
Expand Down
21 changes: 21 additions & 0 deletions internal/coderutil/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package coderutil

import (
"context"

"cdr.dev/coder-cli/coder-sdk"
)

// ProviderByName searches linearly for a workspace provider by its name.
func ProviderByName(ctx context.Context, client coder.Client, name string) (*coder.KubernetesProvider, error) {
providers, err := client.WorkspaceProviders(ctx)
if err != nil {
return nil, err
}
for _, p := range providers.Kubernetes {
if p.Name == name {
return &p, nil
}
}
return nil, coder.ErrNotFound
}