From 8eaac8339fef9253dd6ab0187b9603d16b7e241b Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Wed, 17 Jul 2024 18:36:37 +0000 Subject: [PATCH 1/4] chore: add multi-org flag to develop.sh --- codersdk/organizations.go | 18 +++ enterprise/cli/provisionerdaemons.go | 8 ++ enterprise/cli/provisionerdaemons_test.go | 131 +++++++++++++++++----- scripts/develop.sh | 30 ++++- 4 files changed, 158 insertions(+), 29 deletions(-) diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 0841bdba8554f..041087b26709a 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -290,6 +290,24 @@ func (c *Client) ProvisionerDaemons(ctx context.Context) ([]ProvisionerDaemon, e return daemons, json.NewDecoder(res.Body).Decode(&daemons) } +func (c *Client) OrganizationProvisionerDaemons(ctx context.Context, organizationID uuid.UUID) ([]ProvisionerDaemon, error) { + res, err := c.Request(ctx, http.MethodGet, + fmt.Sprintf("/api/v2/organizations/%s/provisionerdaemons", organizationID.String()), + nil, + ) + if err != nil { + return nil, xerrors.Errorf("execute request: %w", err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + return nil, ReadBodyAsError(res) + } + + var daemons []ProvisionerDaemon + return daemons, json.NewDecoder(res.Body).Decode(&daemons) +} + // CreateTemplateVersion processes source-code and optionally associates the version with a template. // Executing without a template is useful for validating source-code. func (c *Client) CreateTemplateVersion(ctx context.Context, organizationID uuid.UUID, req CreateTemplateVersionRequest) (TemplateVersion, error) { diff --git a/enterprise/cli/provisionerdaemons.go b/enterprise/cli/provisionerdaemons.go index 079b1891346eb..bedc20b4c699b 100644 --- a/enterprise/cli/provisionerdaemons.go +++ b/enterprise/cli/provisionerdaemons.go @@ -74,6 +74,7 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { prometheusEnable bool prometheusAddress string ) + orgContext := agpl.NewOrganizationContext() client := new(codersdk.Client) cmd := &serpent.Command{ Use: "start", @@ -93,6 +94,11 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { interruptCtx, interruptCancel := inv.SignalNotifyContext(ctx, agpl.InterruptSignals...) defer interruptCancel() + org, err := orgContext.Selected(inv, client) + if err != nil { + return xerrors.Errorf("current organization: %w", err) + } + tags, err := agpl.ParseProvisionerTags(rawTags) if err != nil { return err @@ -206,6 +212,7 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { }, Tags: tags, PreSharedKey: preSharedKey, + Organization: org.ID, }) }, &provisionerd.Options{ Logger: logger, @@ -346,6 +353,7 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { Default: "127.0.0.1:2112", }, } + orgContext.AttachOptions(cmd) return cmd } diff --git a/enterprise/cli/provisionerdaemons_test.go b/enterprise/cli/provisionerdaemons_test.go index 67054938d9068..3a19bc2325216 100644 --- a/enterprise/cli/provisionerdaemons_test.go +++ b/enterprise/cli/provisionerdaemons_test.go @@ -27,36 +27,75 @@ import ( func TestProvisionerDaemon_PSK(t *testing.T) { t.Parallel() - client, _ := coderdenttest.New(t, &coderdenttest.Options{ - ProvisionerDaemonPSK: "provisionersftw", - LicenseOptions: &coderdenttest.LicenseOptions{ - Features: license.Features{ - codersdk.FeatureExternalProvisionerDaemons: 1, + t.Run("OK", func(t *testing.T) { + t.Parallel() + + client, _ := coderdenttest.New(t, &coderdenttest.Options{ + ProvisionerDaemonPSK: "provisionersftw", + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureExternalProvisionerDaemons: 1, + }, }, - }, + }) + inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name=matt-daemon") + err := conf.URL().Write(client.URL.String()) + require.NoError(t, err) + pty := ptytest.New(t).Attach(inv) + ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) + defer cancel() + clitest.Start(t, inv) + pty.ExpectNoMatchBefore(ctx, "check entitlement", "starting provisioner daemon") + pty.ExpectMatchContext(ctx, "matt-daemon") + + var daemons []codersdk.ProvisionerDaemon + require.Eventually(t, func() bool { + daemons, err = client.ProvisionerDaemons(ctx) + if err != nil { + return false + } + return len(daemons) == 1 + }, testutil.WaitShort, testutil.IntervalSlow) + require.Equal(t, "matt-daemon", daemons[0].Name) + require.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope]) + require.Equal(t, buildinfo.Version(), daemons[0].Version) + require.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion) + }) + + t.Run("AnotherOrg", func(t *testing.T) { + t.Parallel() + client, _ := coderdenttest.New(t, &coderdenttest.Options{ + ProvisionerDaemonPSK: "provisionersftw", + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureExternalProvisionerDaemons: 1, + }, + }, + }) + anotherOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{}) + anotherClient, _ := coderdtest.CreateAnotherUser(t, client, anotherOrg.ID, rbac.RoleTemplateAdmin()) + inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name", "org-daemon", "--org", anotherOrg.ID.String()) + clitest.SetupConfig(t, anotherClient, conf) + pty := ptytest.New(t).Attach(inv) + ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) + defer cancel() + clitest.Start(t, inv) + pty.ExpectMatchContext(ctx, "starting provisioner daemon") + + var daemons []codersdk.ProvisionerDaemon + var err error + require.Eventually(t, func() bool { + daemons, err = client.OrganizationProvisionerDaemons(ctx, anotherOrg.ID) + if err != nil { + return false + } + return len(daemons) == 1 + }, testutil.WaitShort, testutil.IntervalSlow) + assert.Equal(t, "org-daemon", daemons[0].Name) + assert.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope]) + assert.Equal(t, buildinfo.Version(), daemons[0].Version) + assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion) }) - inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name=matt-daemon") - err := conf.URL().Write(client.URL.String()) - require.NoError(t, err) - pty := ptytest.New(t).Attach(inv) - ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) - defer cancel() - clitest.Start(t, inv) - pty.ExpectNoMatchBefore(ctx, "check entitlement", "starting provisioner daemon") - pty.ExpectMatchContext(ctx, "matt-daemon") - - var daemons []codersdk.ProvisionerDaemon - require.Eventually(t, func() bool { - daemons, err = client.ProvisionerDaemons(ctx) - if err != nil { - return false - } - return len(daemons) == 1 - }, testutil.WaitShort, testutil.IntervalSlow) - require.Equal(t, "matt-daemon", daemons[0].Name) - require.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope]) - require.Equal(t, buildinfo.Version(), daemons[0].Version) - require.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion) } func TestProvisionerDaemon_SessionToken(t *testing.T) { @@ -166,6 +205,42 @@ func TestProvisionerDaemon_SessionToken(t *testing.T) { assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion) }) + t.Run("ScopeUserAnotherOrg", func(t *testing.T) { + t.Parallel() + client, _ := coderdenttest.New(t, &coderdenttest.Options{ + ProvisionerDaemonPSK: "provisionersftw", + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureExternalProvisionerDaemons: 1, + }, + }, + }) + anotherOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{}) + anotherClient, anotherUser := coderdtest.CreateAnotherUser(t, client, anotherOrg.ID, rbac.RoleTemplateAdmin()) + inv, conf := newCLI(t, "provisionerd", "start", "--tag", "scope=user", "--name", "org-daemon", "--org", anotherOrg.ID.String()) + clitest.SetupConfig(t, anotherClient, conf) + pty := ptytest.New(t).Attach(inv) + ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) + defer cancel() + clitest.Start(t, inv) + pty.ExpectMatchContext(ctx, "starting provisioner daemon") + + var daemons []codersdk.ProvisionerDaemon + var err error + require.Eventually(t, func() bool { + daemons, err = client.OrganizationProvisionerDaemons(ctx, anotherOrg.ID) + if err != nil { + return false + } + return len(daemons) == 1 + }, testutil.WaitShort, testutil.IntervalSlow) + assert.Equal(t, "org-daemon", daemons[0].Name) + assert.Equal(t, provisionersdk.ScopeUser, daemons[0].Tags[provisionersdk.TagScope]) + assert.Equal(t, anotherUser.ID.String(), daemons[0].Tags[provisionersdk.TagOwner]) + assert.Equal(t, buildinfo.Version(), daemons[0].Version) + assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion) + }) + t.Run("PrometheusEnabled", func(t *testing.T) { t.Parallel() diff --git a/scripts/develop.sh b/scripts/develop.sh index 3eb9c006003de..d47b26af6bc4d 100755 --- a/scripts/develop.sh +++ b/scripts/develop.sh @@ -18,6 +18,7 @@ debug=0 DEFAULT_PASSWORD="SomeSecurePassword!" password="${CODER_DEV_ADMIN_PASSWORD:-${DEFAULT_PASSWORD}}" use_proxy=0 +multi_org=0 args="$(getopt -o "" -l access-url:,use-proxy,agpl,debug,password: -- "$@")" eval set -- "$args" @@ -39,6 +40,10 @@ while true; do use_proxy=1 shift ;; + --multi-org) + multi_org=1 + shift + ;; --debug) debug=1 shift @@ -182,7 +187,7 @@ fatal() { DOCKER_HOST="$(docker context inspect --format '{{ .Endpoints.docker.Host }}')" printf 'docker_arch: "%s"\ndocker_host: "%s"\n' "${GOARCH}" "${DOCKER_HOST}" >"${temp_template_dir}/params.yaml" ( - "${CODER_DEV_SHIM}" templates push "${template_name}" --directory "${temp_template_dir}" --variables-file "${temp_template_dir}/params.yaml" --yes + "${CODER_DEV_SHIM}" templates push "${template_name}" --directory "${temp_template_dir}" --variables-file "${temp_template_dir}/params.yaml" --yes --org first-organization rm -rfv "${temp_template_dir}" # Only delete template dir if template creation succeeds ) || echo "Failed to create a template. The template files are in ${temp_template_dir}" fi @@ -199,6 +204,29 @@ fatal() { ) || echo "Failed to create workspace proxy. No workspace proxy created." fi + if [ "${multi_org}" -gt "0" ]; then + another_org="second-organization" + if ! "${CODER_DEV_SHIM}" organizations show selected --org "${another_org}" >/dev/null 2>&1; then + log "Creating organization '${another_org}'" + ( + "${CODER_DEV_SHIM}" organizations create -y "${another_org}" + "${CODER_DEV_SHIM}" organizations members add member --org "${another_org}" + ) || echo "Failed to create organization '${another_org}'" + fi + + if ! "${CODER_DEV_SHIM}" org members list --org ${another_org} | grep "^member" >/dev/null 2>&1; then + log "Adding member user to organization '${another_org}'" + ( + "${CODER_DEV_SHIM}" organizations members add member + ) || echo "Failed to add member user to organization '${another_org}'" + fi + + log "Using external provisioner" + ( + start_cmd EXT_PROVISIONER "" "${CODER_DEV_SHIM}" provisionerd start --tag "scope=organization" --name second-org-daemon --org "${another_org}" + ) || echo "Failed to start external provisioner. No external provisioner started." + fi + # Start the frontend once we have a template up and running CODER_HOST=http://127.0.0.1:3000 start_cmd SITE date pnpm --dir ./site dev --host From 38630cf16f014743249fbc177b7ebc67bcd5d2e5 Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Thu, 18 Jul 2024 15:09:42 +0000 Subject: [PATCH 2/4] cleanup --- docs/cli/provisionerd_start.md | 9 +++ .../coder_provisionerd_start_--help.golden | 3 + scripts/develop.sh | 61 +++++++++++-------- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/docs/cli/provisionerd_start.md b/docs/cli/provisionerd_start.md index b781a4b5fe800..c3ccccbd0e1a1 100644 --- a/docs/cli/provisionerd_start.md +++ b/docs/cli/provisionerd_start.md @@ -135,3 +135,12 @@ Serve prometheus metrics on the address defined by prometheus address. | Default | 127.0.0.1:2112 | The bind address to serve prometheus metrics. + +### -O, --org + +| | | +| ----------- | -------------------------------- | +| Type | string | +| Environment | $CODER_ORGANIZATION | + +Select which organization (uuid or name) to use. diff --git a/enterprise/cli/testdata/coder_provisionerd_start_--help.golden b/enterprise/cli/testdata/coder_provisionerd_start_--help.golden index 90694af40f797..3f20d2d04eb72 100644 --- a/enterprise/cli/testdata/coder_provisionerd_start_--help.golden +++ b/enterprise/cli/testdata/coder_provisionerd_start_--help.golden @@ -6,6 +6,9 @@ USAGE: Run a provisioner daemon OPTIONS: + -O, --org string, $CODER_ORGANIZATION + Select which organization (uuid or name) to use. + -c, --cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir]) Directory to store cached data. diff --git a/scripts/develop.sh b/scripts/develop.sh index d47b26af6bc4d..51f6ded4b96f5 100755 --- a/scripts/develop.sh +++ b/scripts/develop.sh @@ -20,7 +20,7 @@ password="${CODER_DEV_ADMIN_PASSWORD:-${DEFAULT_PASSWORD}}" use_proxy=0 multi_org=0 -args="$(getopt -o "" -l access-url:,use-proxy,agpl,debug,password: -- "$@")" +args="$(getopt -o "" -l access-url:,use-proxy,agpl,debug,password:,multi-organization -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -40,7 +40,7 @@ while true; do use_proxy=1 shift ;; - --multi-org) + --multi-organization) multi_org=1 shift ;; @@ -62,6 +62,10 @@ if [ "${CODER_BUILD_AGPL:-0}" -gt "0" ] && [ "${use_proxy}" -gt "0" ]; then echo '== ERROR: cannot use both external proxies and APGL build.' && exit 1 fi +if [ "${CODER_BUILD_AGPL:-0}" -gt "0" ] && [ "${multi_org}" -gt "0" ]; then + echo '== ERROR: cannot use both multi-organizations and APGL build.' && exit 1 +fi + # Preflight checks: ensure we have our required dependencies, and make sure nothing is listening on port 3000 or 8080 dependencies curl git go make pnpm curl --fail http://127.0.0.1:3000 >/dev/null 2>&1 && echo '== ERROR: something is listening on port 3000. Kill it and re-run this script.' && exit 1 @@ -173,21 +177,51 @@ fatal() { echo 'Failed to create regular user. To troubleshoot, try running this command manually.' fi + # Create a new organization and add the member user to it. + if [ "${multi_org}" -gt "0" ]; then + another_org="second-organization" + if ! "${CODER_DEV_SHIM}" organizations show selected --org "${another_org}" >/dev/null 2>&1; then + echo "Creating organization '${another_org}'..." + ( + "${CODER_DEV_SHIM}" organizations create -y "${another_org}" + ) || echo "Failed to create organization '${another_org}'" + fi + + if ! "${CODER_DEV_SHIM}" org members list --org ${another_org} | grep "^member" >/dev/null 2>&1; then + echo "Adding member user to organization '${another_org}'..." + ( + "${CODER_DEV_SHIM}" organizations members add member --org "${another_org}" + ) || echo "Failed to add member user to organization '${another_org}'" + fi + + echo "Starting external provisioner for '${another_org}'..." + ( + start_cmd EXT_PROVISIONER "" "${CODER_DEV_SHIM}" provisionerd start --tag "scope=organization" --name second-org-daemon --org "${another_org}" + ) || echo "Failed to start external provisioner. No external provisioner started." + fi + # If we have docker available and the "docker" template doesn't already # exist, then let's try to create a template! template_name="docker" if docker info >/dev/null 2>&1 && ! "${CODER_DEV_SHIM}" templates versions list "${template_name}" >/dev/null 2>&1; then # sometimes terraform isn't installed yet when we go to create the # template + echo "Waiting for terraform to be installed..." sleep 5 + echo "Initializing docker template..." temp_template_dir="$(mktemp -d)" "${CODER_DEV_SHIM}" templates init --id "${template_name}" "${temp_template_dir}" DOCKER_HOST="$(docker context inspect --format '{{ .Endpoints.docker.Host }}')" printf 'docker_arch: "%s"\ndocker_host: "%s"\n' "${GOARCH}" "${DOCKER_HOST}" >"${temp_template_dir}/params.yaml" ( + echo "Pushing docker template to 'first-organization'..." "${CODER_DEV_SHIM}" templates push "${template_name}" --directory "${temp_template_dir}" --variables-file "${temp_template_dir}/params.yaml" --yes --org first-organization + if [ "${multi_org}" -gt "0" ]; then + echo "Pushing docker template to '${another_org}'..." + "${CODER_DEV_SHIM}" templates push "${template_name}" --directory "${temp_template_dir}" --variables-file "${temp_template_dir}/params.yaml" --yes --org "${another_org}" + fi rm -rfv "${temp_template_dir}" # Only delete template dir if template creation succeeds ) || echo "Failed to create a template. The template files are in ${temp_template_dir}" fi @@ -204,29 +238,6 @@ fatal() { ) || echo "Failed to create workspace proxy. No workspace proxy created." fi - if [ "${multi_org}" -gt "0" ]; then - another_org="second-organization" - if ! "${CODER_DEV_SHIM}" organizations show selected --org "${another_org}" >/dev/null 2>&1; then - log "Creating organization '${another_org}'" - ( - "${CODER_DEV_SHIM}" organizations create -y "${another_org}" - "${CODER_DEV_SHIM}" organizations members add member --org "${another_org}" - ) || echo "Failed to create organization '${another_org}'" - fi - - if ! "${CODER_DEV_SHIM}" org members list --org ${another_org} | grep "^member" >/dev/null 2>&1; then - log "Adding member user to organization '${another_org}'" - ( - "${CODER_DEV_SHIM}" organizations members add member - ) || echo "Failed to add member user to organization '${another_org}'" - fi - - log "Using external provisioner" - ( - start_cmd EXT_PROVISIONER "" "${CODER_DEV_SHIM}" provisionerd start --tag "scope=organization" --name second-org-daemon --org "${another_org}" - ) || echo "Failed to start external provisioner. No external provisioner started." - fi - # Start the frontend once we have a template up and running CODER_HOST=http://127.0.0.1:3000 start_cmd SITE date pnpm --dir ./site dev --host From af7428a7e176169c5c692cca466181c1e461eac9 Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Thu, 18 Jul 2024 16:33:37 +0000 Subject: [PATCH 3/4] fix org flag --- enterprise/cli/provisionerdaemons.go | 52 +++++++++++++----- enterprise/cli/provisionerdaemons_test.go | 65 +++++++++++++++++++++-- 2 files changed, 102 insertions(+), 15 deletions(-) diff --git a/enterprise/cli/provisionerdaemons.go b/enterprise/cli/provisionerdaemons.go index bedc20b4c699b..4812bfaf3c705 100644 --- a/enterprise/cli/provisionerdaemons.go +++ b/enterprise/cli/provisionerdaemons.go @@ -4,7 +4,9 @@ package cli import ( "context" + "errors" "fmt" + "net/http" "os" "regexp" "time" @@ -94,9 +96,33 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { interruptCtx, interruptCancel := inv.SignalNotifyContext(ctx, agpl.InterruptSignals...) defer interruptCancel() + // This can fail to get the current organization + // if the client is not authenticated as a user, + // like when only PSK is provided. + // This will be cleaner once PSK is replaced + // with org scoped authentication tokens. org, err := orgContext.Selected(inv, client) if err != nil { - return xerrors.Errorf("current organization: %w", err) + var cErr *codersdk.Error + if !errors.As(err, &cErr) || cErr.StatusCode() != http.StatusUnauthorized { + return xerrors.Errorf("current organization: %w", err) + } + + if preSharedKey == "" { + return xerrors.New("must provide a pre-shared key when not authenticated as a user") + } + + org = codersdk.Organization{ID: uuid.Nil} + if orgContext.FlagSelect != "" { + // If we are using PSK, we can't fetch the organization + // to validate org name so we need the user to provide + // a valid organization ID. + orgID, err := uuid.Parse(orgContext.FlagSelect) + if err != nil { + return xerrors.New("must provide an org ID when not authenticated as a user and organization is specified") + } + org = codersdk.Organization{ID: orgID} + } } tags, err := agpl.ParseProvisionerTags(rawTags) @@ -202,18 +228,20 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { connector := provisionerd.LocalProvisioners{ string(database.ProvisionerTypeTerraform): proto.NewDRPCProvisionerClient(terraformClient), } - id := uuid.New() + req := codersdk.ServeProvisionerDaemonRequest{ + ID: uuid.New(), + Name: name, + Provisioners: []codersdk.ProvisionerType{ + codersdk.ProvisionerTypeTerraform, + }, + Tags: tags, + PreSharedKey: preSharedKey, + } + if org.ID != uuid.Nil { + req.Organization = org.ID + } srv := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) { - return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{ - ID: id, - Name: name, - Provisioners: []codersdk.ProvisionerType{ - codersdk.ProvisionerTypeTerraform, - }, - Tags: tags, - PreSharedKey: preSharedKey, - Organization: org.ID, - }) + return client.ServeProvisionerDaemon(ctx, req) }, &provisionerd.Options{ Logger: logger, UpdateInterval: 500 * time.Millisecond, diff --git a/enterprise/cli/provisionerdaemons_test.go b/enterprise/cli/provisionerdaemons_test.go index 3a19bc2325216..3fdc31de062f2 100644 --- a/enterprise/cli/provisionerdaemons_test.go +++ b/enterprise/cli/provisionerdaemons_test.go @@ -73,9 +73,9 @@ func TestProvisionerDaemon_PSK(t *testing.T) { }, }) anotherOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{}) - anotherClient, _ := coderdtest.CreateAnotherUser(t, client, anotherOrg.ID, rbac.RoleTemplateAdmin()) inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name", "org-daemon", "--org", anotherOrg.ID.String()) - clitest.SetupConfig(t, anotherClient, conf) + err := conf.URL().Write(client.URL.String()) + require.NoError(t, err) pty := ptytest.New(t).Attach(inv) ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) defer cancel() @@ -83,7 +83,6 @@ func TestProvisionerDaemon_PSK(t *testing.T) { pty.ExpectMatchContext(ctx, "starting provisioner daemon") var daemons []codersdk.ProvisionerDaemon - var err error require.Eventually(t, func() bool { daemons, err = client.OrganizationProvisionerDaemons(ctx, anotherOrg.ID) if err != nil { @@ -96,6 +95,66 @@ func TestProvisionerDaemon_PSK(t *testing.T) { assert.Equal(t, buildinfo.Version(), daemons[0].Version) assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion) }) + + t.Run("AnotherOrgByNameWithUser", func(t *testing.T) { + t.Parallel() + client, _ := coderdenttest.New(t, &coderdenttest.Options{ + ProvisionerDaemonPSK: "provisionersftw", + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureExternalProvisionerDaemons: 1, + }, + }, + }) + anotherOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{}) + anotherClient, _ := coderdtest.CreateAnotherUser(t, client, anotherOrg.ID, rbac.RoleTemplateAdmin()) + inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name", "org-daemon", "--org", anotherOrg.Name) + clitest.SetupConfig(t, anotherClient, conf) + pty := ptytest.New(t).Attach(inv) + ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) + defer cancel() + clitest.Start(t, inv) + pty.ExpectMatchContext(ctx, "starting provisioner daemon") + }) + + t.Run("AnotherOrgByNameNoUser", func(t *testing.T) { + t.Parallel() + client, _ := coderdenttest.New(t, &coderdenttest.Options{ + ProvisionerDaemonPSK: "provisionersftw", + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureExternalProvisionerDaemons: 1, + }, + }, + }) + anotherOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{}) + inv, conf := newCLI(t, "provisionerd", "start", "--psk=provisionersftw", "--name", "org-daemon", "--org", anotherOrg.Name) + err := conf.URL().Write(client.URL.String()) + require.NoError(t, err) + ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) + defer cancel() + err = inv.WithContext(ctx).Run() + require.ErrorContains(t, err, "must provide an org ID when not authenticated as a user and organization is specified") + }) + + t.Run("NoUserNoPSK", func(t *testing.T) { + t.Parallel() + client, _ := coderdenttest.New(t, &coderdenttest.Options{ + ProvisionerDaemonPSK: "provisionersftw", + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureExternalProvisionerDaemons: 1, + }, + }, + }) + inv, conf := newCLI(t, "provisionerd", "start", "--name", "org-daemon") + err := conf.URL().Write(client.URL.String()) + require.NoError(t, err) + ctx, cancel := context.WithTimeout(inv.Context(), testutil.WaitLong) + defer cancel() + err = inv.WithContext(ctx).Run() + require.ErrorContains(t, err, "must provide a pre-shared key when not authenticated as a user") + }) } func TestProvisionerDaemon_SessionToken(t *testing.T) { From f88161b3bfb898810c9df77893c1b2558640fc5a Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Thu, 18 Jul 2024 18:43:44 +0000 Subject: [PATCH 4/4] pr comments --- enterprise/cli/provisionerdaemons.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/enterprise/cli/provisionerdaemons.go b/enterprise/cli/provisionerdaemons.go index 4812bfaf3c705..cf127e2fb96b8 100644 --- a/enterprise/cli/provisionerdaemons.go +++ b/enterprise/cli/provisionerdaemons.go @@ -228,20 +228,17 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command { connector := provisionerd.LocalProvisioners{ string(database.ProvisionerTypeTerraform): proto.NewDRPCProvisionerClient(terraformClient), } - req := codersdk.ServeProvisionerDaemonRequest{ - ID: uuid.New(), - Name: name, - Provisioners: []codersdk.ProvisionerType{ - codersdk.ProvisionerTypeTerraform, - }, - Tags: tags, - PreSharedKey: preSharedKey, - } - if org.ID != uuid.Nil { - req.Organization = org.ID - } srv := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) { - return client.ServeProvisionerDaemon(ctx, req) + return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{ + ID: uuid.New(), + Name: name, + Provisioners: []codersdk.ProvisionerType{ + codersdk.ProvisionerTypeTerraform, + }, + Tags: tags, + PreSharedKey: preSharedKey, + Organization: org.ID, + }) }, &provisionerd.Options{ Logger: logger, UpdateInterval: 500 * time.Millisecond, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy