mirror of https://github.com/coder/coder.git
feat(cli): allow specifying name of provisioner daemon (#11077)
- Adds a --name argument to provisionerd start - Plumbs through name to integrated and external provisioners - Defaults to hostname if not specified for external, hostname-N for integrated - Adds cliutil.Hostname
This commit is contained in:
parent
8aea6040c8
commit
1e349f0d50
|
@ -0,0 +1,40 @@
|
||||||
|
package cliutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
hostname string
|
||||||
|
hostnameOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hostname returns the hostname of the machine, lowercased,
|
||||||
|
// with any trailing domain suffix stripped.
|
||||||
|
// It is cached after the first call.
|
||||||
|
// If the hostname cannot be determined, for any reason,
|
||||||
|
// localhost will be returned instead.
|
||||||
|
func Hostname() string {
|
||||||
|
hostnameOnce.Do(func() { hostname = getHostname() })
|
||||||
|
return hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHostname() string {
|
||||||
|
h, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
// Something must be very wrong if this fails.
|
||||||
|
// We'll just return localhost and hope for the best.
|
||||||
|
return "localhost"
|
||||||
|
}
|
||||||
|
|
||||||
|
// On some platforms, the hostname can be an FQDN. We only want the hostname.
|
||||||
|
if idx := strings.Index(h, "."); idx != -1 {
|
||||||
|
h = h[:idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the sake of consistency, we also want to lowercase the hostname.
|
||||||
|
// Per RFC 4343, DNS lookups must be case-insensitive.
|
||||||
|
return strings.ToLower(h)
|
||||||
|
}
|
|
@ -62,6 +62,7 @@ import (
|
||||||
"github.com/coder/coder/v2/buildinfo"
|
"github.com/coder/coder/v2/buildinfo"
|
||||||
"github.com/coder/coder/v2/cli/clibase"
|
"github.com/coder/coder/v2/cli/clibase"
|
||||||
"github.com/coder/coder/v2/cli/cliui"
|
"github.com/coder/coder/v2/cli/cliui"
|
||||||
|
"github.com/coder/coder/v2/cli/cliutil"
|
||||||
"github.com/coder/coder/v2/cli/config"
|
"github.com/coder/coder/v2/cli/config"
|
||||||
"github.com/coder/coder/v2/coderd"
|
"github.com/coder/coder/v2/coderd"
|
||||||
"github.com/coder/coder/v2/coderd/autobuild"
|
"github.com/coder/coder/v2/coderd/autobuild"
|
||||||
|
@ -86,6 +87,7 @@ import (
|
||||||
"github.com/coder/coder/v2/coderd/unhanger"
|
"github.com/coder/coder/v2/coderd/unhanger"
|
||||||
"github.com/coder/coder/v2/coderd/updatecheck"
|
"github.com/coder/coder/v2/coderd/updatecheck"
|
||||||
"github.com/coder/coder/v2/coderd/util/slice"
|
"github.com/coder/coder/v2/coderd/util/slice"
|
||||||
|
stringutil "github.com/coder/coder/v2/coderd/util/strings"
|
||||||
"github.com/coder/coder/v2/coderd/workspaceapps"
|
"github.com/coder/coder/v2/coderd/workspaceapps"
|
||||||
"github.com/coder/coder/v2/codersdk"
|
"github.com/coder/coder/v2/codersdk"
|
||||||
"github.com/coder/coder/v2/cryptorand"
|
"github.com/coder/coder/v2/cryptorand"
|
||||||
|
@ -875,9 +877,14 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
|
||||||
defer provisionerdWaitGroup.Wait()
|
defer provisionerdWaitGroup.Wait()
|
||||||
provisionerdMetrics := provisionerd.NewMetrics(options.PrometheusRegistry)
|
provisionerdMetrics := provisionerd.NewMetrics(options.PrometheusRegistry)
|
||||||
for i := int64(0); i < vals.Provisioner.Daemons.Value(); i++ {
|
for i := int64(0); i < vals.Provisioner.Daemons.Value(); i++ {
|
||||||
|
suffix := fmt.Sprintf("%d", i)
|
||||||
|
// The suffix is added to the hostname, so we may need to trim to fit into
|
||||||
|
// the 64 character limit.
|
||||||
|
hostname := stringutil.Truncate(cliutil.Hostname(), 63-len(suffix))
|
||||||
|
name := fmt.Sprintf("%s-%s", hostname, suffix)
|
||||||
daemonCacheDir := filepath.Join(cacheDir, fmt.Sprintf("provisioner-%d", i))
|
daemonCacheDir := filepath.Join(cacheDir, fmt.Sprintf("provisioner-%d", i))
|
||||||
daemon, err := newProvisionerDaemon(
|
daemon, err := newProvisionerDaemon(
|
||||||
ctx, coderAPI, provisionerdMetrics, logger, vals, daemonCacheDir, errCh, &provisionerdWaitGroup,
|
ctx, coderAPI, provisionerdMetrics, logger, vals, daemonCacheDir, errCh, &provisionerdWaitGroup, name,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("create provisioner daemon: %w", err)
|
return xerrors.Errorf("create provisioner daemon: %w", err)
|
||||||
|
@ -1243,6 +1250,7 @@ func newProvisionerDaemon(
|
||||||
cacheDir string,
|
cacheDir string,
|
||||||
errCh chan error,
|
errCh chan error,
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
|
name string,
|
||||||
) (srv *provisionerd.Server, err error) {
|
) (srv *provisionerd.Server, err error) {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -1334,9 +1342,9 @@ func newProvisionerDaemon(
|
||||||
return provisionerd.New(func(ctx context.Context) (proto.DRPCProvisionerDaemonClient, error) {
|
return provisionerd.New(func(ctx context.Context) (proto.DRPCProvisionerDaemonClient, error) {
|
||||||
// This debounces calls to listen every second. Read the comment
|
// This debounces calls to listen every second. Read the comment
|
||||||
// in provisionerdserver.go to learn more!
|
// in provisionerdserver.go to learn more!
|
||||||
return coderAPI.CreateInMemoryProvisionerDaemon(ctx)
|
return coderAPI.CreateInMemoryProvisionerDaemon(ctx, name)
|
||||||
}, &provisionerd.Options{
|
}, &provisionerd.Options{
|
||||||
Logger: logger.Named("provisionerd"),
|
Logger: logger.Named(fmt.Sprintf("provisionerd-%s", name)),
|
||||||
UpdateInterval: time.Second,
|
UpdateInterval: time.Second,
|
||||||
ForceCancelInterval: cfg.Provisioner.ForceCancelInterval.Value(),
|
ForceCancelInterval: cfg.Provisioner.ForceCancelInterval.Value(),
|
||||||
Connector: connector,
|
Connector: connector,
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/klauspost/compress/zstd"
|
"github.com/klauspost/compress/zstd"
|
||||||
"github.com/moby/moby/pkg/namesgenerator"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
httpSwagger "github.com/swaggo/http-swagger/v2"
|
httpSwagger "github.com/swaggo/http-swagger/v2"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
@ -1150,7 +1149,7 @@ func compressHandler(h http.Handler) http.Handler {
|
||||||
|
|
||||||
// CreateInMemoryProvisionerDaemon is an in-memory connection to a provisionerd.
|
// CreateInMemoryProvisionerDaemon is an in-memory connection to a provisionerd.
|
||||||
// Useful when starting coderd and provisionerd in the same process.
|
// Useful when starting coderd and provisionerd in the same process.
|
||||||
func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context) (client proto.DRPCProvisionerDaemonClient, err error) {
|
func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context, name string) (client proto.DRPCProvisionerDaemonClient, err error) {
|
||||||
tracer := api.TracerProvider.Tracer(tracing.TracerName)
|
tracer := api.TracerProvider.Tracer(tracing.TracerName)
|
||||||
clientSession, serverSession := provisionersdk.MemTransportPipe()
|
clientSession, serverSession := provisionersdk.MemTransportPipe()
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -1165,9 +1164,8 @@ func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context) (client pro
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := drpcmux.New()
|
mux := drpcmux.New()
|
||||||
name := namesgenerator.GetRandomName(1)
|
api.Logger.Info(ctx, "starting in-memory provisioner daemon", slog.F("name", name))
|
||||||
logger := api.Logger.Named(fmt.Sprintf("inmem-provisionerd-%s", name))
|
logger := api.Logger.Named(fmt.Sprintf("inmem-provisionerd-%s", name))
|
||||||
logger.Info(ctx, "starting in-memory provisioner daemon")
|
|
||||||
srv, err := provisionerdserver.NewServer(
|
srv, err := provisionerdserver.NewServer(
|
||||||
api.ctx,
|
api.ctx,
|
||||||
api.AccessURL,
|
api.AccessURL,
|
||||||
|
|
|
@ -530,7 +530,7 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
daemon := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
daemon := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
||||||
return coderAPI.CreateInMemoryProvisionerDaemon(ctx)
|
return coderAPI.CreateInMemoryProvisionerDaemon(ctx, t.Name())
|
||||||
}, &provisionerd.Options{
|
}, &provisionerd.Options{
|
||||||
Logger: coderAPI.Logger.Named("provisionerd").Leveled(slog.LevelDebug),
|
Logger: coderAPI.Logger.Named("provisionerd").Leveled(slog.LevelDebug),
|
||||||
UpdateInterval: 250 * time.Millisecond,
|
UpdateInterval: 250 * time.Millisecond,
|
||||||
|
@ -567,6 +567,8 @@ func NewExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
|
||||||
|
|
||||||
daemon := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
daemon := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
||||||
return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: org,
|
Organization: org,
|
||||||
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho},
|
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho},
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
|
|
|
@ -17,3 +17,14 @@ func JoinWithConjunction(s []string) string {
|
||||||
s[last],
|
s[last],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Truncate returns the first n characters of s.
|
||||||
|
func Truncate(s string, n int) string {
|
||||||
|
if n < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(s) <= n {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return s[:n]
|
||||||
|
}
|
||||||
|
|
|
@ -14,3 +14,27 @@ func TestJoinWithConjunction(t *testing.T) {
|
||||||
require.Equal(t, "foo and bar", strings.JoinWithConjunction([]string{"foo", "bar"}))
|
require.Equal(t, "foo and bar", strings.JoinWithConjunction([]string{"foo", "bar"}))
|
||||||
require.Equal(t, "foo, bar and baz", strings.JoinWithConjunction([]string{"foo", "bar", "baz"}))
|
require.Equal(t, "foo, bar and baz", strings.JoinWithConjunction([]string{"foo", "bar", "baz"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTruncate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
for _, tt := range []struct {
|
||||||
|
s string
|
||||||
|
n int
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"foo", 4, "foo"},
|
||||||
|
{"foo", 3, "foo"},
|
||||||
|
{"foo", 2, "fo"},
|
||||||
|
{"foo", 1, "f"},
|
||||||
|
{"foo", 0, ""},
|
||||||
|
{"foo", -1, ""},
|
||||||
|
} {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.expected, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
actual := strings.Truncate(tt.s, tt.n)
|
||||||
|
require.Equal(t, tt.expected, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -177,6 +177,8 @@ func (c *Client) provisionerJobLogsAfter(ctx context.Context, path string, after
|
||||||
type ServeProvisionerDaemonRequest struct {
|
type ServeProvisionerDaemonRequest struct {
|
||||||
// ID is a unique ID for a provisioner daemon.
|
// ID is a unique ID for a provisioner daemon.
|
||||||
ID uuid.UUID `json:"id" format:"uuid"`
|
ID uuid.UUID `json:"id" format:"uuid"`
|
||||||
|
// Name is the human-readable unique identifier for the daemon.
|
||||||
|
Name string `json:"name" example:"my-cool-provisioner-daemon"`
|
||||||
// Organization is the organization for the URL. At present provisioner daemons ARE NOT scoped to organizations
|
// Organization is the organization for the URL. At present provisioner daemons ARE NOT scoped to organizations
|
||||||
// and so the organization ID is optional.
|
// and so the organization ID is optional.
|
||||||
Organization uuid.UUID `json:"organization" format:"uuid"`
|
Organization uuid.UUID `json:"organization" format:"uuid"`
|
||||||
|
@ -198,6 +200,7 @@ func (c *Client) ServeProvisionerDaemon(ctx context.Context, req ServeProvisione
|
||||||
}
|
}
|
||||||
query := serverURL.Query()
|
query := serverURL.Query()
|
||||||
query.Add("id", req.ID.String())
|
query.Add("id", req.ID.String())
|
||||||
|
query.Add("name", req.Name)
|
||||||
for _, provisioner := range req.Provisioners {
|
for _, provisioner := range req.Provisioners {
|
||||||
query.Add("provisioner", string(provisioner))
|
query.Add("provisioner", string(provisioner))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,15 @@ coder provisionerd start [flags]
|
||||||
|
|
||||||
Directory to store cached data.
|
Directory to store cached data.
|
||||||
|
|
||||||
|
### --name
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| ----------- | ------------------------------------------- |
|
||||||
|
| Type | <code>string</code> |
|
||||||
|
| Environment | <code>$CODER_PROVISIONER_DAEMON_NAME</code> |
|
||||||
|
|
||||||
|
Name of this provisioner daemon. Defaults to the current hostname without FQDN.
|
||||||
|
|
||||||
### --poll-interval
|
### --poll-interval
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -16,6 +17,7 @@ import (
|
||||||
agpl "github.com/coder/coder/v2/cli"
|
agpl "github.com/coder/coder/v2/cli"
|
||||||
"github.com/coder/coder/v2/cli/clibase"
|
"github.com/coder/coder/v2/cli/clibase"
|
||||||
"github.com/coder/coder/v2/cli/cliui"
|
"github.com/coder/coder/v2/cli/cliui"
|
||||||
|
"github.com/coder/coder/v2/cli/cliutil"
|
||||||
"github.com/coder/coder/v2/coderd/database"
|
"github.com/coder/coder/v2/coderd/database"
|
||||||
"github.com/coder/coder/v2/coderd/provisionerdserver"
|
"github.com/coder/coder/v2/coderd/provisionerdserver"
|
||||||
"github.com/coder/coder/v2/codersdk"
|
"github.com/coder/coder/v2/codersdk"
|
||||||
|
@ -41,6 +43,16 @@ func (r *RootCmd) provisionerDaemons() *clibase.Cmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateProvisionerDaemonName(name string) error {
|
||||||
|
if len(name) > 64 {
|
||||||
|
return xerrors.Errorf("name cannot be greater than 64 characters in length")
|
||||||
|
}
|
||||||
|
if ok, err := regexp.MatchString(`^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$`, name); err != nil || !ok {
|
||||||
|
return xerrors.Errorf("name %q is not a valid hostname", name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
||||||
var (
|
var (
|
||||||
cacheDir string
|
cacheDir string
|
||||||
|
@ -48,6 +60,7 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
||||||
pollInterval time.Duration
|
pollInterval time.Duration
|
||||||
pollJitter time.Duration
|
pollJitter time.Duration
|
||||||
preSharedKey string
|
preSharedKey string
|
||||||
|
name string
|
||||||
)
|
)
|
||||||
client := new(codersdk.Client)
|
client := new(codersdk.Client)
|
||||||
cmd := &clibase.Cmd{
|
cmd := &clibase.Cmd{
|
||||||
|
@ -68,6 +81,14 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
name = cliutil.Hostname()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateProvisionerDaemonName(name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
logger := slog.Make(sloghuman.Sink(inv.Stderr))
|
logger := slog.Make(sloghuman.Sink(inv.Stderr))
|
||||||
if ok, _ := inv.ParsedFlags().GetBool("verbose"); ok {
|
if ok, _ := inv.ParsedFlags().GetBool("verbose"); ok {
|
||||||
logger = logger.Leveled(slog.LevelDebug)
|
logger = logger.Leveled(slog.LevelDebug)
|
||||||
|
@ -122,7 +143,7 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logger.Info(ctx, "starting provisioner daemon", slog.F("tags", tags))
|
logger.Info(ctx, "starting provisioner daemon", slog.F("tags", tags), slog.F("name", name))
|
||||||
|
|
||||||
connector := provisionerd.LocalProvisioners{
|
connector := provisionerd.LocalProvisioners{
|
||||||
string(database.ProvisionerTypeTerraform): proto.NewDRPCProvisionerClient(terraformClient),
|
string(database.ProvisionerTypeTerraform): proto.NewDRPCProvisionerClient(terraformClient),
|
||||||
|
@ -130,7 +151,8 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
||||||
id := uuid.New()
|
id := uuid.New()
|
||||||
srv := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
srv := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
||||||
return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
Name: name,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeTerraform,
|
codersdk.ProvisionerTypeTerraform,
|
||||||
},
|
},
|
||||||
|
@ -205,6 +227,13 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd {
|
||||||
Description: "Pre-shared key to authenticate with Coder server.",
|
Description: "Pre-shared key to authenticate with Coder server.",
|
||||||
Value: clibase.StringOf(&preSharedKey),
|
Value: clibase.StringOf(&preSharedKey),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Flag: "name",
|
||||||
|
Env: "CODER_PROVISIONER_DAEMON_NAME",
|
||||||
|
Description: "Name of this provisioner daemon. Defaults to the current hostname without FQDN.",
|
||||||
|
Value: clibase.StringOf(&name),
|
||||||
|
Default: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestProvisionerDaemon_PSK(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw")
|
inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name=matt-daemon")
|
||||||
err := conf.URL().Write(client.URL.String())
|
err := conf.URL().Write(client.URL.String())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
pty := ptytest.New(t).Attach(inv)
|
pty := ptytest.New(t).Attach(inv)
|
||||||
|
@ -34,6 +34,7 @@ func TestProvisionerDaemon_PSK(t *testing.T) {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
clitest.Start(t, inv)
|
clitest.Start(t, inv)
|
||||||
pty.ExpectMatchContext(ctx, "starting provisioner daemon")
|
pty.ExpectMatchContext(ctx, "starting provisioner daemon")
|
||||||
|
pty.ExpectMatchContext(ctx, "matt-daemon")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProvisionerDaemon_SessionToken(t *testing.T) {
|
func TestProvisionerDaemon_SessionToken(t *testing.T) {
|
||||||
|
|
|
@ -9,6 +9,10 @@ OPTIONS:
|
||||||
-c, --cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir])
|
-c, --cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir])
|
||||||
Directory to store cached data.
|
Directory to store cached data.
|
||||||
|
|
||||||
|
--name string, $CODER_PROVISIONER_DAEMON_NAME
|
||||||
|
Name of this provisioner daemon. Defaults to the current hostname
|
||||||
|
without FQDN.
|
||||||
|
|
||||||
--poll-interval duration, $CODER_PROVISIONERD_POLL_INTERVAL (default: 1s)
|
--poll-interval duration, $CODER_PROVISIONERD_POLL_INTERVAL (default: 1s)
|
||||||
Deprecated and ignored.
|
Deprecated and ignored.
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,13 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := namesgenerator.GetRandomName(10)
|
||||||
|
if vals, ok := r.URL.Query()["name"]; ok && len(vals) > 0 {
|
||||||
|
name = vals[0]
|
||||||
|
} else {
|
||||||
|
api.Logger.Warn(ctx, "unnamed provisioner daemon")
|
||||||
|
}
|
||||||
|
|
||||||
tags, authorized := api.provisionerDaemonAuth.authorize(r, tags)
|
tags, authorized := api.provisionerDaemonAuth.authorize(r, tags)
|
||||||
if !authorized {
|
if !authorized {
|
||||||
api.Logger.Warn(ctx, "unauthorized provisioner daemon serve request", slog.F("tags", tags))
|
api.Logger.Warn(ctx, "unauthorized provisioner daemon serve request", slog.F("tags", tags))
|
||||||
|
@ -206,7 +213,6 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name := namesgenerator.GetRandomName(1)
|
|
||||||
log := api.Logger.With(
|
log := api.Logger.With(
|
||||||
slog.F("name", name),
|
slog.F("name", name),
|
||||||
slog.F("provisioners", provisioners),
|
slog.F("provisioners", provisioners),
|
||||||
|
|
|
@ -40,6 +40,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
srv, err := templateAdminClient.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
srv, err := templateAdminClient.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -57,6 +59,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := templateAdminClient.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
_, err := templateAdminClient.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -80,6 +84,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -105,6 +111,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -245,6 +253,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
another := codersdk.New(client.URL)
|
another := codersdk.New(client.URL)
|
||||||
pd := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
pd := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
|
||||||
return another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
return another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -321,6 +331,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -350,6 +362,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
another := codersdk.New(client.URL)
|
another := codersdk.New(client.URL)
|
||||||
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
@ -377,6 +391,8 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
another := codersdk.New(client.URL)
|
another := codersdk.New(client.URL)
|
||||||
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
_, err := another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Name: t.Name(),
|
||||||
Organization: user.OrganizationID,
|
Organization: user.OrganizationID,
|
||||||
Provisioners: []codersdk.ProvisionerType{
|
Provisioners: []codersdk.ProvisionerType{
|
||||||
codersdk.ProvisionerTypeEcho,
|
codersdk.ProvisionerTypeEcho,
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -19,6 +18,7 @@ import (
|
||||||
"cdr.dev/slog"
|
"cdr.dev/slog"
|
||||||
|
|
||||||
"github.com/coder/coder/v2/buildinfo"
|
"github.com/coder/coder/v2/buildinfo"
|
||||||
|
"github.com/coder/coder/v2/cli/cliutil"
|
||||||
"github.com/coder/coder/v2/coderd/database"
|
"github.com/coder/coder/v2/coderd/database"
|
||||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||||
"github.com/coder/coder/v2/coderd/database/dbtime"
|
"github.com/coder/coder/v2/coderd/database/dbtime"
|
||||||
|
@ -57,10 +57,7 @@ func New(ctx context.Context, logger slog.Logger, db database.Store, ps pubsub.P
|
||||||
// primary purpose is to clean up dead replicas.
|
// primary purpose is to clean up dead replicas.
|
||||||
options.CleanupInterval = 30 * time.Minute
|
options.CleanupInterval = 30 * time.Minute
|
||||||
}
|
}
|
||||||
hostname, err := os.Hostname()
|
hostname := cliutil.Hostname()
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("get hostname: %w", err)
|
|
||||||
}
|
|
||||||
databaseLatency, err := db.Ping(ctx)
|
databaseLatency, err := db.Ping(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("ping database: %w", err)
|
return nil, xerrors.Errorf("ping database: %w", err)
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -27,6 +26,7 @@ import (
|
||||||
|
|
||||||
"cdr.dev/slog"
|
"cdr.dev/slog"
|
||||||
"github.com/coder/coder/v2/buildinfo"
|
"github.com/coder/coder/v2/buildinfo"
|
||||||
|
"github.com/coder/coder/v2/cli/cliutil"
|
||||||
"github.com/coder/coder/v2/coderd"
|
"github.com/coder/coder/v2/coderd"
|
||||||
"github.com/coder/coder/v2/coderd/httpapi"
|
"github.com/coder/coder/v2/coderd/httpapi"
|
||||||
"github.com/coder/coder/v2/coderd/httpmw"
|
"github.com/coder/coder/v2/coderd/httpmw"
|
||||||
|
@ -206,10 +206,7 @@ func New(ctx context.Context, opts *Options) (*Server, error) {
|
||||||
// Register the workspace proxy with the primary coderd instance and start a
|
// Register the workspace proxy with the primary coderd instance and start a
|
||||||
// goroutine to periodically re-register.
|
// goroutine to periodically re-register.
|
||||||
replicaID := uuid.New()
|
replicaID := uuid.New()
|
||||||
osHostname, err := os.Hostname()
|
osHostname := cliutil.Hostname()
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("get OS hostname: %w", err)
|
|
||||||
}
|
|
||||||
regResp, registerDone, err := client.RegisterWorkspaceProxyLoop(ctx, wsproxysdk.RegisterWorkspaceProxyLoopOpts{
|
regResp, registerDone, err := client.RegisterWorkspaceProxyLoop(ctx, wsproxysdk.RegisterWorkspaceProxyLoopOpts{
|
||||||
Logger: opts.Logger,
|
Logger: opts.Logger,
|
||||||
Request: wsproxysdk.RegisterWorkspaceProxyRequest{
|
Request: wsproxysdk.RegisterWorkspaceProxyRequest{
|
||||||
|
|
|
@ -20,6 +20,9 @@ fi
|
||||||
if [[ ${1:-} == exp ]] && [[ ${2:-} == scaletest ]]; then
|
if [[ ${1:-} == exp ]] && [[ ${2:-} == scaletest ]]; then
|
||||||
BINARY_TYPE=coder
|
BINARY_TYPE=coder
|
||||||
fi
|
fi
|
||||||
|
if [[ ${1:-} == provisionerd ]]; then
|
||||||
|
BINARY_TYPE=coder
|
||||||
|
fi
|
||||||
RELATIVE_BINARY_PATH="build/${BINARY_TYPE}_${GOOS}_${GOARCH}"
|
RELATIVE_BINARY_PATH="build/${BINARY_TYPE}_${GOOS}_${GOARCH}"
|
||||||
|
|
||||||
# To preserve the CWD when running the binary, we need to use pushd and popd to
|
# To preserve the CWD when running the binary, we need to use pushd and popd to
|
||||||
|
|
Loading…
Reference in New Issue