Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"ntqry",
"oneof",
"parameterscopeid",
"pqtype",
"promptui",
"protobuf",
"provisionerd",
Expand All @@ -61,6 +62,7 @@
"stretchr",
"tcpip",
"tfexec",
"tfjson",
"tfstate",
"unconvert",
"webrtc",
Expand Down
16 changes: 14 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
INSTALL_DIR=$(shell go env GOPATH)/bin
GOOS=$(shell go env GOOS)
GOARCH=$(shell go env GOARCH)

bin/coder:
mkdir -p bin
go build -o bin/coder cmd/coder/main.go
CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o bin/coder-$(GOOS)-$(GOARCH) cmd/coder/main.go
.PHONY: bin/coder

bin/coderd:
mkdir -p bin
go build -o bin/coderd cmd/coderd/main.go
.PHONY: bin/coderd

build: site/out bin/coder bin/coderd
bin/terraform-provider-coder:
mkdir -p bin
go build -o bin/terraform-provider-coder cmd/terraform-provider-coder/main.go
.PHONY: bin/terraform-provider-coder

build: site/out bin/coder bin/coderd bin/terraform-provider-coder
.PHONY: build

# Runs migrations to output a dump of the database.
Expand Down Expand Up @@ -59,6 +66,11 @@ install:
@echo "-- CLI available at $(shell ls $(INSTALL_DIR)/coder*)"
.PHONY: install

install/terraform-provider-coder: bin/terraform-provider-coder
$(eval OS_ARCH := $(shell go env GOOS)_$(shell go env GOARCH))
mkdir -p ~/.terraform.d/plugins/coder.com/internal/coder/0.2/$(OS_ARCH)
cp bin/terraform-provider-coder ~/.terraform.d/plugins/coder.com/internal/coder/0.2/$(OS_ARCH)

peerbroker/proto: peerbroker/proto/peerbroker.proto
protoc \
--go_out=. \
Expand Down
9 changes: 9 additions & 0 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"golang.org/x/xerrors"
)

// DialSSH creates an SSH DataChannel on the connection provided.
func DialSSH(conn *peer.Conn) (net.Conn, error) {
channel, err := conn.Dial(context.Background(), "ssh", &peer.ChannelOptions{
Protocol: "ssh",
Expand All @@ -35,6 +36,7 @@ func DialSSH(conn *peer.Conn) (net.Conn, error) {
return channel.NetConn(), nil
}

// DialSSHClient wraps the DialSSH function with a Go SSH client.
func DialSSHClient(conn *peer.Conn) (*gossh.Client, error) {
netConn, err := DialSSH(conn)
if err != nil {
Expand All @@ -59,6 +61,13 @@ type Options struct {
Logger slog.Logger
}

// Dialer to return the peerbroker.Listener, but that hinges on
// a proper authentication token. If it fails to dial for that
// reason, we should check the API error and renegotiate a new
// authentication method.
//
// This also needs to update it's own metadata and such.

type Dialer func(ctx context.Context) (*peerbroker.Listener, error)

func New(dialer Dialer, options *Options) io.Closer {
Expand Down
15 changes: 15 additions & 0 deletions cli/agent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cli

import (
"github.com/spf13/cobra"
)

func agent() *cobra.Command {
return &cobra.Command{
Use: "agent",
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}
}
19 changes: 8 additions & 11 deletions cli/projectcreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"golang.org/x/xerrors"

"github.com/coder/coder/coderd"
"github.com/coder/coder/coderd/parameter"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/database"
"github.com/coder/coder/provisionerd"
Expand Down Expand Up @@ -72,13 +71,6 @@ func projectCreate() *cobra.Command {
if err != nil {
return err
}
project, err := client.CreateProject(cmd.Context(), organization.Name, coderd.CreateProjectRequest{
Name: name,
VersionImportJobID: job.ID,
})
if err != nil {
return err
}

_, err = prompt(cmd, &promptui.Prompt{
Label: "Create project?",
Expand All @@ -92,6 +84,14 @@ func projectCreate() *cobra.Command {
return err
}

project, err := client.CreateProject(cmd.Context(), organization.Name, coderd.CreateProjectRequest{
Name: name,
VersionImportJobID: job.ID,
})
if err != nil {
return err
}

_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s The %s project has been created!\n", caret, color.HiCyanString(project.Name))
_, err = prompt(cmd, &promptui.Prompt{
Label: "Create a new workspace?",
Expand Down Expand Up @@ -187,9 +187,6 @@ func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, o
if ok {
continue
}
if parameterSchema.Name == parameter.CoderWorkspaceTransition {
continue
}
value, err := prompt(cmd, &promptui.Prompt{
Label: fmt.Sprintf("Enter value for %s:", color.HiCyanString(parameterSchema.Name)),
})
Expand Down
2 changes: 1 addition & 1 deletion cli/projectcreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestProjectCreate(t *testing.T) {
matches := []string{
"organization?", "y",
"name?", "test-project",
"somevar:", "value",
"somevar", "value",
"project?", "y",
"created!", "n",
}
Expand Down
5 changes: 4 additions & 1 deletion cli/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func projects() *cobra.Command {
return cmd
}

func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.ParameterSchema, parameterValues []coderd.ComputedParameterValue, resources []coderd.ProjectImportJobResource) error {
func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.ParameterSchema, parameterValues []coderd.ComputedParameterValue, resources []coderd.ProvisionerJobResource) error {
schemaByID := map[string]coderd.ParameterSchema{}
for _, schema := range parameterSchemas {
schemaByID[schema.ID.String()] = schema
Expand Down Expand Up @@ -78,6 +78,9 @@ func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.Para
if resource.Transition == database.WorkspaceTransitionStop {
transition = color.HiRedString("stop")
}
if resource.AgentID != nil {
transition += " with agent"
}
_, _ = fmt.Fprintf(cmd.OutOrStdout(), " %s %s on %s\n\n", color.HiCyanString(resource.Type), color.HiCyanString(resource.Name), transition)
}
return nil
Expand Down
1 change: 1 addition & 0 deletions cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func Root() *cobra.Command {
`Additional help topics:`, header.Sprint("Additional help:"),
).Replace(cmd.UsageTemplate()))

cmd.AddCommand(agent())
cmd.AddCommand(login())
cmd.AddCommand(projects())
cmd.AddCommand(workspaces())
Expand Down
13 changes: 13 additions & 0 deletions cmd/terraform-provider-coder/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"

"github.com/coder/coder/provisioner/terraform/provider"
)

func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: provider.New,
})
}
21 changes: 14 additions & 7 deletions coderd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,20 @@ func Root() *cobra.Command {
Use: "coderd",
RunE: func(cmd *cobra.Command, args []string) error {
logger := slog.Make(sloghuman.Sink(os.Stderr))
accessURL := &url.URL{
Scheme: "http",
Host: address,
}
realAccessURL, err := url.Parse("https://v2--kyle.master.cdr.dev/")
if err != nil {
return xerrors.Errorf("parse real access url: %s", err)
}

handler, closeCoderd := coderd.New(&coderd.Options{
Logger: logger,
Database: databasefake.New(),
Pubsub: database.NewPubsubInMemory(),
AccessURL: realAccessURL,
Logger: logger,
Database: databasefake.New(),
Pubsub: database.NewPubsubInMemory(),
})

listener, err := net.Listen("tcp", address)
Expand All @@ -45,10 +55,7 @@ func Root() *cobra.Command {
}
defer listener.Close()

client := codersdk.New(&url.URL{
Scheme: "http",
Host: address,
})
client := codersdk.New(accessURL)
daemonClose, err := newProvisionerDaemon(cmd.Context(), client, logger)
if err != nil {
return xerrors.Errorf("create provisioner daemon: %w", err)
Expand Down
78 changes: 40 additions & 38 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package coderd

import (
"net/http"
"net/url"
"sync"

"github.com/go-chi/chi/v5"
Expand All @@ -16,9 +17,10 @@ import (

// Options are requires parameters for Coder to start.
type Options struct {
Logger slog.Logger
Database database.Store
Pubsub database.Pubsub
AccessURL *url.URL
Logger slog.Logger
Database database.Store
Pubsub database.Pubsub

GoogleTokenValidator *idtoken.Validator
}
Expand Down Expand Up @@ -58,6 +60,22 @@ func New(options *Options) (http.Handler, func()) {
r.Post("/keys", api.postKeyForUser)
})
})

r.Route("/project/import/{organization}", func(r chi.Router) {
r.Use(
httpmw.ExtractAPIKey(options.Database, nil),
httpmw.ExtractOrganizationParam(options.Database),
)
r.Post("/", api.postProjectImportByOrganization)
r.Route("/{provisionerjob}", func(r chi.Router) {
r.Use(httpmw.ExtractProvisionerJobParam(options.Database))
r.Get("/", api.provisionerJobByID)
r.Get("/schemas", api.projectImportJobSchemasByID)
r.Get("/parameters", api.projectImportJobParametersByID)
r.Get("/resources", api.projectImportJobResourcesByID)
r.Get("/logs", api.provisionerJobLogsByID)
})
})
r.Route("/projects", func(r chi.Router) {
r.Use(
httpmw.ExtractAPIKey(options.Database, nil),
Expand Down Expand Up @@ -87,8 +105,17 @@ func New(options *Options) (http.Handler, func()) {
})
})

// Listing operations specific to resources should go under
// their respective routes. eg. /orgs/<name>/workspaces
r.Route("/workspace/provision/{organization}", func(r chi.Router) {
r.Use(
httpmw.ExtractAPIKey(options.Database, nil),
httpmw.ExtractOrganizationParam(options.Database),
)
r.Route("/{provisionerjob}", func(r chi.Router) {
r.Use(httpmw.ExtractProvisionerJobParam(options.Database))
r.Get("/", api.provisionerJobByID)
r.Get("/logs", api.provisionerJobLogsByID)
})
})
r.Route("/workspaces", func(r chi.Router) {
r.Use(httpmw.ExtractAPIKey(options.Database, nil))
r.Get("/", api.workspaces)
Expand All @@ -98,7 +125,7 @@ func New(options *Options) (http.Handler, func()) {
r.Route("/{workspace}", func(r chi.Router) {
r.Use(httpmw.ExtractWorkspaceParam(options.Database))
r.Get("/", api.workspaceByUser)
r.Route("/version", func(r chi.Router) {
r.Route("/history", func(r chi.Router) {
r.Post("/", api.postWorkspaceHistoryByUser)
r.Get("/", api.workspaceHistoryByUser)
r.Route("/{workspacehistory}", func(r chi.Router) {
Expand All @@ -110,43 +137,18 @@ func New(options *Options) (http.Handler, func()) {
})
})

r.Route("/workspaceagent", func(r chi.Router) {
r.Route("/authenticate", func(r chi.Router) {
r.Post("/google-instance-identity", api.postAuthenticateWorkspaceAgentUsingGoogleInstanceIdentity)
r.Route("/agent", func(r chi.Router) {
r.Route("/auth", func(r chi.Router) {
r.Post("/google-instance-identity", api.postAuthWorkspaceAgentUsingGoogleInstanceIdentity)
})
})
r.Route("/{agent}", func(r chi.Router) {

r.Route("/files", func(r chi.Router) {
r.Use(httpmw.ExtractAPIKey(options.Database, nil))
r.Post("/", api.postFiles)
})

r.Route("/projectimport/{organization}", func(r chi.Router) {
r.Use(
httpmw.ExtractAPIKey(options.Database, nil),
httpmw.ExtractOrganizationParam(options.Database),
)
r.Post("/", api.postProjectImportByOrganization)
r.Route("/{provisionerjob}", func(r chi.Router) {
r.Use(httpmw.ExtractProvisionerJobParam(options.Database))
r.Get("/", api.provisionerJobByID)
r.Get("/schemas", api.projectImportJobSchemasByID)
r.Get("/parameters", api.projectImportJobParametersByID)
r.Get("/resources", api.projectImportJobResourcesByID)
r.Get("/logs", api.provisionerJobLogsByID)
})
})

r.Route("/workspaceprovision/{organization}", func(r chi.Router) {
r.Use(
httpmw.ExtractAPIKey(options.Database, nil),
httpmw.ExtractOrganizationParam(options.Database),
)
r.Route("/{provisionerjob}", func(r chi.Router) {
r.Use(httpmw.ExtractProvisionerJobParam(options.Database))
r.Get("/", api.provisionerJobByID)
r.Get("/logs", api.provisionerJobLogsByID)
})
r.Route("/upload", func(r chi.Router) {
r.Use(httpmw.ExtractAPIKey(options.Database, nil))
r.Post("/", api.postUpload)
})

r.Route("/provisioners/daemons", func(r chi.Router) {
Expand Down
19 changes: 11 additions & 8 deletions coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,7 @@ func New(t *testing.T, options *Options) *codersdk.Client {
})
}

handler, closeWait := coderd.New(&coderd.Options{
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
Database: db,
Pubsub: pubsub,

GoogleTokenValidator: options.GoogleTokenValidator,
})
srv := httptest.NewUnstartedServer(handler)
srv := httptest.NewUnstartedServer(nil)
srv.Config.BaseContext = func(_ net.Listener) context.Context {
ctx, cancelFunc := context.WithCancel(context.Background())
t.Cleanup(cancelFunc)
Expand All @@ -96,6 +89,16 @@ func New(t *testing.T, options *Options) *codersdk.Client {
srv.Start()
serverURL, err := url.Parse(srv.URL)
require.NoError(t, err)
var closeWait func()
// We set the handler after server creation for the access URL.
srv.Config.Handler, closeWait = coderd.New(&coderd.Options{
AccessURL: serverURL,
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
Database: db,
Pubsub: pubsub,

GoogleTokenValidator: options.GoogleTokenValidator,
})
t.Cleanup(func() {
srv.Close()
closeWait()
Expand Down
2 changes: 1 addition & 1 deletion coderd/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type UploadFileResponse struct {
Hash string `json:"hash"`
}

func (api *api) postFiles(rw http.ResponseWriter, r *http.Request) {
func (api *api) postUpload(rw http.ResponseWriter, r *http.Request) {
apiKey := httpmw.APIKey(r)
contentType := r.Header.Get("Content-Type")

Expand Down
Loading