fix!: remove AUTO_IMPORT_TEMPLATE for Kubernetes installs (#5401)

* fix!: remove AUTO_IMPORT_TEMPLATE

* chore: remove template auto importing

Co-authored-by: Dean Sheather <dean@deansheather.com>
This commit is contained in:
Ben Potter 2023-01-04 20:04:32 -08:00 committed by GitHub
parent 24592332e2
commit 04d45f3c1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 0 additions and 355 deletions

View File

@ -362,12 +362,6 @@ func newConfig() *codersdk.DeploymentConfig {
Flag: "ssh-keygen-algorithm",
Default: "ed25519",
},
AutoImportTemplates: &codersdk.DeploymentConfigField[[]string]{
Name: "Auto Import Templates",
Usage: "Templates to auto-import. Available auto-importable templates are: kubernetes",
Flag: "auto-import-template",
Hidden: true,
},
MetricsCacheRefreshInterval: &codersdk.DeploymentConfigField[time.Duration]{
Name: "Metrics Cache Refresh Interval",
Usage: "How frequently metrics are refreshed",

View File

@ -371,27 +371,6 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
return xerrors.Errorf("parse ssh keygen algorithm %s: %w", cfg.SSHKeygenAlgorithm.Value, err)
}
// Validate provided auto-import templates.
var (
validatedAutoImportTemplates = make([]coderd.AutoImportTemplate, len(cfg.AutoImportTemplates.Value))
seenValidatedAutoImportTemplates = make(map[coderd.AutoImportTemplate]struct{}, len(cfg.AutoImportTemplates.Value))
)
for i, autoImportTemplate := range cfg.AutoImportTemplates.Value {
var v coderd.AutoImportTemplate
switch autoImportTemplate {
case "kubernetes":
v = coderd.AutoImportTemplateKubernetes
default:
return xerrors.Errorf("auto import template %q is not supported", autoImportTemplate)
}
if _, ok := seenValidatedAutoImportTemplates[v]; ok {
return xerrors.Errorf("auto import template %q is specified more than once", v)
}
seenValidatedAutoImportTemplates[v] = struct{}{}
validatedAutoImportTemplates[i] = v
}
defaultRegion := &tailcfg.DERPRegion{
EmbeddedRelay: true,
RegionID: cfg.DERP.Server.RegionID.Value,
@ -449,7 +428,6 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
SSHKeygenAlgorithm: sshKeygenAlgorithm,
TracerProvider: tracerProvider,
Telemetry: telemetry.NewNoop(),
AutoImportTemplates: validatedAutoImportTemplates,
MetricsCacheRefreshInterval: cfg.MetricsCacheRefreshInterval.Value,
AgentStatsRefreshInterval: cfg.AgentStatRefreshInterval.Value,
DeploymentConfig: cfg,

View File

@ -1573,9 +1573,6 @@ const docTemplate = `{
"audit_logging": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
},
"auto_import_templates": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-array_string"
},
"autobuild_poll_interval": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-time_Duration"
},

View File

@ -1393,9 +1393,6 @@
"audit_logging": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
},
"auto_import_templates": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-array_string"
},
"autobuild_poll_interval": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-time_Duration"
},

View File

@ -97,7 +97,6 @@ type Options struct {
SSHKeygenAlgorithm gitsshkey.Algorithm
Telemetry telemetry.Reporter
TracerProvider trace.TracerProvider
AutoImportTemplates []AutoImportTemplate
GitAuthConfigs []*gitauth.Config
RealIPConfig *httpmw.RealIPConfig
TrialGenerator func(ctx context.Context, email string) error

View File

@ -93,7 +93,6 @@ type Options struct {
GoogleTokenValidator *idtoken.Validator
SSHKeygenAlgorithm gitsshkey.Algorithm
APIRateLimit int
AutoImportTemplates []coderd.AutoImportTemplate
AutobuildTicker <-chan time.Time
AutobuildStats chan<- executor.Stats
Auditor audit.Auditor
@ -294,7 +293,6 @@ func NewOptions(t *testing.T, options *Options) (func(http.Handler), context.Can
},
},
},
AutoImportTemplates: options.AutoImportTemplates,
MetricsCacheRefreshInterval: options.MetricsCacheRefreshInterval,
AgentStatsRefreshInterval: options.AgentStatsRefreshInterval,
DeploymentConfig: options.DeploymentConfig,

View File

@ -2,9 +2,7 @@ package coderd
import (
"context"
"crypto/sha256"
"database/sql"
"encoding/hex"
"errors"
"fmt"
"net/http"
@ -13,7 +11,6 @@ import (
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator"
"golang.org/x/xerrors"
"github.com/coder/coder/coderd/audit"
@ -26,14 +23,6 @@ import (
"github.com/coder/coder/examples"
)
// Auto-importable templates. These can be auto-imported after the first user
// has been created.
type AutoImportTemplate string
const (
AutoImportTemplateKubernetes AutoImportTemplate = "kubernetes"
)
// @Summary Get template metadata by ID
// @ID get-template-metadata-by-id
// @Security CoderSessionToken
@ -640,147 +629,6 @@ func (api *API) templateExamples(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusOK, ex)
}
type autoImportTemplateOpts struct {
name string
archive []byte
params map[string]string
userID uuid.UUID
orgID uuid.UUID
}
func (api *API) autoImportTemplate(ctx context.Context, opts autoImportTemplateOpts) (database.Template, error) {
var template database.Template
err := api.Database.InTx(func(tx database.Store) error {
// Insert the archive into the files table.
var (
hash = sha256.Sum256(opts.archive)
now = database.Now()
)
file, err := tx.InsertFile(ctx, database.InsertFileParams{
ID: uuid.New(),
Hash: hex.EncodeToString(hash[:]),
CreatedAt: now,
CreatedBy: opts.userID,
Mimetype: "application/x-tar",
Data: opts.archive,
})
if err != nil {
return xerrors.Errorf("insert auto-imported template archive into files table: %w", err)
}
jobID := uuid.New()
// Insert parameters
for key, value := range opts.params {
_, err = tx.InsertParameterValue(ctx, database.InsertParameterValueParams{
ID: uuid.New(),
Name: key,
CreatedAt: now,
UpdatedAt: now,
Scope: database.ParameterScopeImportJob,
ScopeID: jobID,
SourceScheme: database.ParameterSourceSchemeData,
SourceValue: value,
DestinationScheme: database.ParameterDestinationSchemeProvisionerVariable,
})
if err != nil {
return xerrors.Errorf("insert job-scoped parameter %q with value %q: %w", key, value, err)
}
}
// Create provisioner job
job, err := tx.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
ID: jobID,
CreatedAt: now,
UpdatedAt: now,
OrganizationID: opts.orgID,
InitiatorID: opts.userID,
Provisioner: database.ProvisionerTypeTerraform,
StorageMethod: database.ProvisionerStorageMethodFile,
FileID: file.ID,
Type: database.ProvisionerJobTypeTemplateVersionImport,
Input: []byte{'{', '}'},
})
if err != nil {
return xerrors.Errorf("insert provisioner job: %w", err)
}
// Create template version
templateVersion, err := tx.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{
ID: uuid.New(),
TemplateID: uuid.NullUUID{
UUID: uuid.Nil,
Valid: false,
},
OrganizationID: opts.orgID,
CreatedAt: now,
UpdatedAt: now,
Name: namesgenerator.GetRandomName(1),
Readme: "",
JobID: job.ID,
CreatedBy: opts.userID,
})
if err != nil {
return xerrors.Errorf("insert template version: %w", err)
}
// Create template
template, err = tx.InsertTemplate(ctx, database.InsertTemplateParams{
ID: uuid.New(),
CreatedAt: now,
UpdatedAt: now,
OrganizationID: opts.orgID,
Name: opts.name,
Provisioner: job.Provisioner,
ActiveVersionID: templateVersion.ID,
Description: "This template was auto-imported by Coder.",
DefaultTTL: 0,
CreatedBy: opts.userID,
UserACL: database.TemplateACL{},
GroupACL: database.TemplateACL{
opts.orgID.String(): []rbac.Action{rbac.ActionRead},
},
})
if err != nil {
return xerrors.Errorf("insert template: %w", err)
}
// Update template version with template ID
err = tx.UpdateTemplateVersionByID(ctx, database.UpdateTemplateVersionByIDParams{
ID: templateVersion.ID,
TemplateID: uuid.NullUUID{
UUID: template.ID,
Valid: true,
},
})
if err != nil {
return xerrors.Errorf("update template version to set template ID: %s", err)
}
// Insert parameters at the template scope
for key, value := range opts.params {
_, err = tx.InsertParameterValue(ctx, database.InsertParameterValueParams{
ID: uuid.New(),
Name: key,
CreatedAt: now,
UpdatedAt: now,
Scope: database.ParameterScopeTemplate,
ScopeID: template.ID,
SourceScheme: database.ParameterSourceSchemeData,
SourceValue: value,
DestinationScheme: database.ParameterDestinationSchemeProvisionerVariable,
})
if err != nil {
return xerrors.Errorf("insert template-scoped parameter %q with value %q: %w", key, value, err)
}
}
return nil
}, nil)
return template, err
}
func getCreatedByNamesByTemplateIDs(ctx context.Context, db database.Store, templates []database.Template) (map[string]string, error) {
creators := make(map[string]string, len(templates))
for _, template := range templates {

View File

@ -1,14 +1,12 @@
package coderd
import (
"bytes"
"context"
"database/sql"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"strings"
"github.com/go-chi/chi/v5"
@ -27,7 +25,6 @@ import (
"github.com/coder/coder/coderd/userpassword"
"github.com/coder/coder/coderd/util/slice"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/examples"
)
// Returns whether the initial user has been created or not.
@ -132,60 +129,6 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
return
}
// Auto-import any designated templates into the new organization.
for _, template := range api.AutoImportTemplates {
archive, err := examples.Archive(string(template))
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error importing template.",
Detail: xerrors.Errorf("load template archive for %q: %w", template, err).Error(),
})
return
}
// Determine which parameter values to use.
parameters := map[string]string{}
switch template {
case AutoImportTemplateKubernetes:
// Determine the current namespace we're in.
const namespaceFile = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
namespace, err := os.ReadFile(namespaceFile)
if err != nil {
parameters["use_kubeconfig"] = "true" // use ~/.config/kubeconfig
parameters["namespace"] = "coder-workspaces"
} else {
parameters["use_kubeconfig"] = "false" // use SA auth
parameters["namespace"] = string(bytes.TrimSpace(namespace))
}
default:
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error importing template.",
Detail: fmt.Sprintf("cannot auto-import %q template", template),
})
return
}
tpl, err := api.autoImportTemplate(ctx, autoImportTemplateOpts{
name: string(template),
archive: archive,
params: parameters,
userID: user.ID,
orgID: organizationID,
})
if err != nil {
api.Logger.Warn(ctx, "failed to auto-import template", slog.F("template", template), slog.F("parameters", parameters), slog.Error(err))
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error importing template.",
Detail: xerrors.Errorf("failed to import template %q: %w", template, err).Error(),
})
return
}
api.Logger.Info(ctx, "auto-imported template", slog.F("id", tpl.ID), slog.F("template", template), slog.F("parameters", parameters))
}
httpapi.Write(ctx, rw, http.StatusCreated, codersdk.CreateFirstUserResponse{
UserID: user.ID,
OrganizationID: organizationID,

View File

@ -14,7 +14,6 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"
"github.com/coder/coder/coderd"
"github.com/coder/coder/coderd/audit"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/database"
@ -116,77 +115,6 @@ func TestFirstUser(t *testing.T) {
}
}
})
t.Run("AutoImportsTemplates", func(t *testing.T) {
t.Parallel()
// All available auto import templates should be added to this list, and
// also added to the switch statement below.
autoImportTemplates := []coderd.AutoImportTemplate{
coderd.AutoImportTemplateKubernetes,
}
client := coderdtest.New(t, &coderdtest.Options{
AutoImportTemplates: autoImportTemplates,
})
u := coderdtest.CreateFirstUser(t, client)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
templates, err := client.TemplatesByOrganization(ctx, u.OrganizationID)
require.NoError(t, err, "list templates")
require.Len(t, templates, len(autoImportTemplates), "listed templates count does not match")
require.ElementsMatch(t, autoImportTemplates, []coderd.AutoImportTemplate{
coderd.AutoImportTemplate(templates[0].Name),
}, "template names don't match")
for _, template := range templates {
// Check template parameters.
templateParams, err := client.Parameters(ctx, codersdk.ParameterTemplate, template.ID)
require.NoErrorf(t, err, "get template parameters for %q", template.Name)
// Ensure all template parameters are present.
expectedParams := map[string]bool{}
switch template.Name {
case "kubernetes":
expectedParams["use_kubeconfig"] = false
expectedParams["namespace"] = false
default:
t.Fatalf("unexpected template name %q", template.Name)
}
for _, v := range templateParams {
if _, ok := expectedParams[v.Name]; !ok {
t.Fatalf("unexpected template parameter %q in template %q", v.Name, template.Name)
}
expectedParams[v.Name] = true
}
for k, v := range expectedParams {
if !v {
t.Fatalf("missing template parameter %q in template %q", k, template.Name)
}
}
// Ensure template version is legit
templateVersion, err := client.TemplateVersion(ctx, template.ActiveVersionID)
require.NoErrorf(t, err, "get template version for %q", template.Name)
// Compare job parameters to template parameters.
jobParams, err := client.Parameters(ctx, codersdk.ParameterImportJob, templateVersion.Job.ID)
require.NoErrorf(t, err, "get template import job parameters for %q", template.Name)
for _, v := range jobParams {
if _, ok := expectedParams[v.Name]; !ok {
t.Fatalf("unexpected job parameter %q for template %q", v.Name, template.Name)
}
// Change it back to false so we can reuse the map
expectedParams[v.Name] = false
}
for k, v := range expectedParams {
if v {
t.Fatalf("missing job parameter %q for template %q", k, template.Name)
}
}
}
})
}
func TestPostLogin(t *testing.T) {

View File

@ -33,7 +33,6 @@ type DeploymentConfig struct {
Trace *TraceConfig `json:"trace" typescript:",notnull"`
SecureAuthCookie *DeploymentConfigField[bool] `json:"secure_auth_cookie" typescript:",notnull"`
SSHKeygenAlgorithm *DeploymentConfigField[string] `json:"ssh_keygen_algorithm" typescript:",notnull"`
AutoImportTemplates *DeploymentConfigField[[]string] `json:"auto_import_templates" typescript:",notnull"`
MetricsCacheRefreshInterval *DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval" typescript:",notnull"`
AgentStatRefreshInterval *DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval" typescript:",notnull"`
AgentFallbackTroubleshootingURL *DeploymentConfigField[string] `json:"agent_fallback_troubleshooting_url" typescript:",notnull"`

View File

@ -151,17 +151,6 @@ curl -X GET http://coder-server:8080/api/v2/config/deployment \
"usage": "string",
"value": true
},
"auto_import_templates": {
"default": ["string"],
"enterprise": true,
"flag": "string",
"hidden": true,
"name": "string",
"secret": true,
"shorthand": "string",
"usage": "string",
"value": "string"
},
"autobuild_poll_interval": {
"default": 0,
"enterprise": true,

View File

@ -735,17 +735,6 @@ CreateParameterRequest is a structure used to create a new parameter value for a
"usage": "string",
"value": true
},
"auto_import_templates": {
"default": ["string"],
"enterprise": true,
"flag": "string",
"hidden": true,
"name": "string",
"secret": true,
"shorthand": "string",
"usage": "string",
"value": "string"
},
"autobuild_poll_interval": {
"default": 0,
"enterprise": true,
@ -1522,7 +1511,6 @@ CreateParameterRequest is a structure used to create a new parameter value for a
| `agent_stat_refresh_interval` | [codersdk.DeploymentConfigField-time_Duration](#codersdkdeploymentconfigfield-time_duration) | false | | |
| `api_rate_limit` | [codersdk.DeploymentConfigField-int](#codersdkdeploymentconfigfield-int) | false | | |
| `audit_logging` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
| `auto_import_templates` | [codersdk.DeploymentConfigField-array_string](#codersdkdeploymentconfigfield-array_string) | false | | |
| `autobuild_poll_interval` | [codersdk.DeploymentConfigField-time_Duration](#codersdkdeploymentconfigfield-time_duration) | false | | |
| `browser_only` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
| `cache_directory` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | |

View File

@ -101,12 +101,6 @@ to log in and manage templates.
- name: CODER_ACCESS_URL
value: "https://coder.example.com"
# This env variable controls whether or not to auto-import the
# "kubernetes" template on first startup. This will not work unless
# coder.serviceAccount.workspacePerms is true.
- name: CODER_AUTO_IMPORT_TEMPLATES
value: "kubernetes"
#tls:
# secretNames:
# - my-tls-secret-name

View File

@ -44,12 +44,6 @@ coder:
name: coder-db-url
key: url
# This env variable controls whether or not to auto-import the "kubernetes"
# template on first startup. This will not work unless
# coder.serviceAccount.workspacePerms is true.
- name: CODER_AUTO_IMPORT_TEMPLATES
value: "kubernetes"
# This env enables the Prometheus metrics endpoint.
- name: CODER_PROMETHEUS_ADDRESS
value: "0.0.0.0:2112"

View File

@ -301,7 +301,6 @@ export interface DeploymentConfig {
readonly trace: TraceConfig
readonly secure_auth_cookie: DeploymentConfigField<boolean>
readonly ssh_keygen_algorithm: DeploymentConfigField<string>
readonly auto_import_templates: DeploymentConfigField<string[]>
readonly metrics_cache_refresh_interval: DeploymentConfigField<number>
readonly agent_stat_refresh_interval: DeploymentConfigField<number>
readonly agent_fallback_troubleshooting_url: DeploymentConfigField<string>