fix(cli): inherit provisioner tags from last template version (#13462)

This commit is contained in:
Marcin Tojek
2024-06-04 13:59:54 +02:00
committed by GitHub
parent e527bc6242
commit cd32c42699
4 changed files with 151 additions and 3 deletions
+10
View File
@@ -100,6 +100,16 @@ func (r *RootCmd) templatePush() *serpent.Command {
return err
}
// If user hasn't provided new provisioner tags, inherit ones from the active template version.
if len(tags) == 0 && template.ActiveVersionID != uuid.Nil {
templateVersion, err := client.TemplateVersion(inv.Context(), template.ActiveVersionID)
if err != nil {
return err
}
tags = templateVersion.Job.Tags
inv.Logger.Info(inv.Context(), "reusing existing provisioner tags", "tags", tags)
}
userVariableValues, err := ParseUserVariableValues(
varsFiles,
variablesFile,
+129
View File
@@ -403,6 +403,135 @@ func TestTemplatePush(t *testing.T) {
assert.NotEqual(t, template.ActiveVersionID, templateVersions[1].ID)
})
t.Run("ProvisionerTags", func(t *testing.T) {
t.Parallel()
t.Run("ChangeTags", func(t *testing.T) {
t.Parallel()
// Start the first provisioner
client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
ProvisionerDaemonTags: map[string]string{
"docker": "true",
},
})
defer provisionerDocker.Close()
// Start the second provisioner
provisionerFoobar := coderdtest.NewTaggedProvisionerDaemon(t, api, "provisioner-foobar", map[string]string{
"foobar": "foobaz",
})
defer provisionerFoobar.Close()
owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
// Create the template with initial tagged template version.
templateVersion := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil, func(ctvr *codersdk.CreateTemplateVersionRequest) {
ctvr.ProvisionerTags = map[string]string{
"docker": "true",
}
})
templateVersion = coderdtest.AwaitTemplateVersionJobCompleted(t, client, templateVersion.ID)
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, templateVersion.ID)
// Push new template version without provisioner tags. CLI should reuse tags from the previous version.
source := clitest.CreateTemplateVersionSource(t, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: echo.ApplyComplete,
})
inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name,
"--provisioner-tag", "foobar=foobaz")
clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv)
execDone := make(chan error)
go func() {
execDone <- inv.Run()
}()
matches := []struct {
match string
write string
}{
{match: "Upload", write: "yes"},
}
for _, m := range matches {
pty.ExpectMatch(m.match)
pty.WriteLine(m.write)
}
require.NoError(t, <-execDone)
// Verify template version tags
template, err := client.Template(context.Background(), template.ID)
require.NoError(t, err)
templateVersion, err = client.TemplateVersion(context.Background(), template.ActiveVersionID)
require.NoError(t, err)
require.EqualValues(t, map[string]string{"foobar": "foobaz", "owner": "", "scope": "organization"}, templateVersion.Job.Tags)
})
t.Run("DoNotChangeTags", func(t *testing.T) {
t.Parallel()
// Start the tagged provisioner
client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
ProvisionerDaemonTags: map[string]string{
"docker": "true",
},
})
owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
// Create the template with initial tagged template version.
templateVersion := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil, func(ctvr *codersdk.CreateTemplateVersionRequest) {
ctvr.ProvisionerTags = map[string]string{
"docker": "true",
}
})
templateVersion = coderdtest.AwaitTemplateVersionJobCompleted(t, client, templateVersion.ID)
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, templateVersion.ID)
// Push new template version without provisioner tags. CLI should reuse tags from the previous version.
source := clitest.CreateTemplateVersionSource(t, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: echo.ApplyComplete,
})
inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name)
clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv)
execDone := make(chan error)
go func() {
execDone <- inv.Run()
}()
matches := []struct {
match string
write string
}{
{match: "Upload", write: "yes"},
}
for _, m := range matches {
pty.ExpectMatch(m.match)
pty.WriteLine(m.write)
}
require.NoError(t, <-execDone)
// Verify template version tags
template, err := client.Template(context.Background(), template.ID)
require.NoError(t, err)
templateVersion, err = client.TemplateVersion(context.Background(), template.ActiveVersionID)
require.NoError(t, err)
require.EqualValues(t, map[string]string{"docker": "true", "owner": "", "scope": "organization"}, templateVersion.Job.Tags)
})
})
t.Run("Variables", func(t *testing.T) {
t.Parallel()
+5 -1
View File
@@ -1373,6 +1373,10 @@ func compressHandler(h http.Handler) http.Handler {
// CreateInMemoryProvisionerDaemon is an in-memory connection to a provisionerd.
// Useful when starting coderd and provisionerd in the same process.
func (api *API) CreateInMemoryProvisionerDaemon(dialCtx context.Context, name string, provisionerTypes []codersdk.ProvisionerType) (client proto.DRPCProvisionerDaemonClient, err error) {
return api.CreateInMemoryTaggedProvisionerDaemon(dialCtx, name, provisionerTypes, nil)
}
func (api *API) CreateInMemoryTaggedProvisionerDaemon(dialCtx context.Context, name string, provisionerTypes []codersdk.ProvisionerType, provisionerTags map[string]string) (client proto.DRPCProvisionerDaemonClient, err error) {
tracer := api.TracerProvider.Tracer(tracing.TracerName)
clientSession, serverSession := drpc.MemTransportPipe()
defer func() {
@@ -1400,7 +1404,7 @@ func (api *API) CreateInMemoryProvisionerDaemon(dialCtx context.Context, name st
OrganizationID: defaultOrg.ID,
CreatedAt: dbtime.Now(),
Provisioners: dbTypes,
Tags: provisionersdk.MutateTags(uuid.Nil, nil),
Tags: provisionersdk.MutateTags(uuid.Nil, provisionerTags),
LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
Version: buildinfo.Version(),
APIVersion: proto.CurrentVersion.String(),
+7 -2
View File
@@ -125,6 +125,7 @@ type Options struct {
// IncludeProvisionerDaemon when true means to start an in-memory provisionerD
IncludeProvisionerDaemon bool
ProvisionerDaemonTags map[string]string
MetricsCacheRefreshInterval time.Duration
AgentStatsRefreshInterval time.Duration
DeploymentValues *codersdk.DeploymentValues
@@ -512,7 +513,7 @@ func NewWithAPI(t testing.TB, options *Options) (*codersdk.Client, io.Closer, *c
setHandler(coderAPI.RootHandler)
var provisionerCloser io.Closer = nopcloser{}
if options.IncludeProvisionerDaemon {
provisionerCloser = NewProvisionerDaemon(t, coderAPI)
provisionerCloser = NewTaggedProvisionerDaemon(t, coderAPI, "test", options.ProvisionerDaemonTags)
}
client := codersdk.New(serverURL)
t.Cleanup(func() {
@@ -552,6 +553,10 @@ func (c *provisionerdCloser) Close() error {
// well with coderd testing. It registers the "echo" provisioner for
// quick testing.
func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer {
return NewTaggedProvisionerDaemon(t, coderAPI, "test", nil)
}
func NewTaggedProvisionerDaemon(t testing.TB, coderAPI *coderd.API, name string, provisionerTags map[string]string) io.Closer {
t.Helper()
// t.Cleanup runs in last added, first called order. t.TempDir() will delete
@@ -578,7 +583,7 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer {
}()
daemon := provisionerd.New(func(dialCtx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
return coderAPI.CreateInMemoryProvisionerDaemon(dialCtx, "test", []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho})
return coderAPI.CreateInMemoryTaggedProvisionerDaemon(dialCtx, name, []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho}, provisionerTags)
}, &provisionerd.Options{
Logger: coderAPI.Logger.Named("provisionerd").Leveled(slog.LevelDebug),
UpdateInterval: 250 * time.Millisecond,