mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add new required slug property to coder_app, use in URLs (#4573)
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package provisioner
|
||||
|
||||
import "regexp"
|
||||
|
||||
var (
|
||||
// AppSlugRegex is the regex used to validate the slug of a coder_app
|
||||
// resource. It must be a valid hostname and cannot contain two consecutive
|
||||
// hyphens or start/end with a hyphen.
|
||||
//
|
||||
// This regex is duplicated in the terraform provider code, so make sure to
|
||||
// update it there as well.
|
||||
//
|
||||
// There are test cases for this regex in appslug_test.go.
|
||||
AppSlugRegex = regexp.MustCompile(`^[a-z0-9](-?[a-z0-9])*$`)
|
||||
)
|
||||
@@ -0,0 +1,64 @@
|
||||
package provisioner_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/provisioner"
|
||||
)
|
||||
|
||||
func TestValidAppSlugRegex(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
validStrings := []string{
|
||||
"a",
|
||||
"1",
|
||||
"a1",
|
||||
"1a",
|
||||
"1a1",
|
||||
"1-1",
|
||||
"a-a",
|
||||
"ab-cd",
|
||||
"ab-cd-ef",
|
||||
"abc-123",
|
||||
"a-123",
|
||||
"abc-1",
|
||||
"ab-c",
|
||||
"a-bc",
|
||||
}
|
||||
|
||||
for _, s := range validStrings {
|
||||
require.True(t, provisioner.AppSlugRegex.MatchString(s), s)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
invalidStrings := []string{
|
||||
"",
|
||||
"-",
|
||||
"-abc",
|
||||
"abc-",
|
||||
"ab--cd",
|
||||
"a--bc",
|
||||
"ab--c",
|
||||
"_",
|
||||
"ab_cd",
|
||||
"_abc",
|
||||
"abc_",
|
||||
" ",
|
||||
"abc ",
|
||||
" abc",
|
||||
"ab cd",
|
||||
}
|
||||
|
||||
for _, s := range invalidStrings {
|
||||
require.False(t, provisioner.AppSlugRegex.MatchString(s), s)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/provisioner"
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
)
|
||||
|
||||
@@ -25,7 +26,12 @@ type agentAttributes struct {
|
||||
|
||||
// A mapping of attributes on the "coder_app" resource.
|
||||
type agentAppAttributes struct {
|
||||
AgentID string `mapstructure:"agent_id"`
|
||||
AgentID string `mapstructure:"agent_id"`
|
||||
// Slug is required in terraform, but to avoid breaking existing users we
|
||||
// will default to the resource name if it is not specified.
|
||||
Slug string `mapstructure:"slug"`
|
||||
DisplayName string `mapstructure:"display_name"`
|
||||
// Name is deprecated in favor of DisplayName.
|
||||
Name string `mapstructure:"name"`
|
||||
Icon string `mapstructure:"icon"`
|
||||
URL string `mapstructure:"url"`
|
||||
@@ -214,19 +220,40 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
||||
}
|
||||
|
||||
// Associate Apps with agents.
|
||||
appSlugs := make(map[string]struct{})
|
||||
for _, resource := range tfResourceByLabel {
|
||||
if resource.Type != "coder_app" {
|
||||
continue
|
||||
}
|
||||
|
||||
var attrs agentAppAttributes
|
||||
err = mapstructure.Decode(resource.AttributeValues, &attrs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("decode app attributes: %w", err)
|
||||
}
|
||||
if attrs.Name == "" {
|
||||
// Default to the resource name if none is set!
|
||||
attrs.Name = resource.Name
|
||||
|
||||
// Default to the resource name if none is set!
|
||||
if attrs.Slug == "" {
|
||||
attrs.Slug = resource.Name
|
||||
}
|
||||
if attrs.DisplayName == "" {
|
||||
if attrs.Name != "" {
|
||||
// Name is deprecated but still accepted.
|
||||
attrs.DisplayName = attrs.Name
|
||||
} else {
|
||||
attrs.DisplayName = attrs.Slug
|
||||
}
|
||||
}
|
||||
|
||||
if !provisioner.AppSlugRegex.MatchString(attrs.Slug) {
|
||||
return nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug)
|
||||
}
|
||||
|
||||
if _, exists := appSlugs[attrs.Slug]; exists {
|
||||
return nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug)
|
||||
}
|
||||
appSlugs[attrs.Slug] = struct{}{}
|
||||
|
||||
var healthcheck *proto.Healthcheck
|
||||
if len(attrs.Healthcheck) != 0 {
|
||||
healthcheck = &proto.Healthcheck{
|
||||
@@ -253,7 +280,8 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
||||
continue
|
||||
}
|
||||
agent.Apps = append(agent.Apps, &proto.App{
|
||||
Name: attrs.Name,
|
||||
Slug: attrs.Slug,
|
||||
DisplayName: attrs.DisplayName,
|
||||
Command: attrs.Command,
|
||||
Url: attrs.URL,
|
||||
Icon: attrs.Icon,
|
||||
|
||||
@@ -110,13 +110,15 @@ func TestConvertResources(t *testing.T) {
|
||||
Architecture: "amd64",
|
||||
Apps: []*proto.App{
|
||||
{
|
||||
Name: "app1",
|
||||
Slug: "app1",
|
||||
DisplayName: "app1",
|
||||
// Subdomain defaults to false if unspecified.
|
||||
Subdomain: false,
|
||||
},
|
||||
{
|
||||
Name: "app2",
|
||||
Subdomain: true,
|
||||
Slug: "app2",
|
||||
DisplayName: "app2",
|
||||
Subdomain: true,
|
||||
Healthcheck: &proto.Healthcheck{
|
||||
Url: "http://localhost:13337/healthz",
|
||||
Interval: 5,
|
||||
@@ -124,8 +126,9 @@ func TestConvertResources(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "app3",
|
||||
Subdomain: false,
|
||||
Slug: "app3",
|
||||
DisplayName: "app3",
|
||||
Subdomain: false,
|
||||
},
|
||||
},
|
||||
Auth: &proto.Agent_Token{},
|
||||
@@ -182,12 +185,23 @@ func TestConvertResources(t *testing.T) {
|
||||
expectedNoMetadata = append(expectedNoMetadata, resourceCopy)
|
||||
}
|
||||
|
||||
resourcesWant, err := json.Marshal(expectedNoMetadata)
|
||||
// Convert expectedNoMetadata and resources into a
|
||||
// []map[string]interface{} so they can be compared easily.
|
||||
data, err := json.Marshal(expectedNoMetadata)
|
||||
require.NoError(t, err)
|
||||
resourcesGot, err := json.Marshal(resources)
|
||||
var expectedNoMetadataMap []map[string]interface{}
|
||||
err = json.Unmarshal(data, &expectedNoMetadataMap)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(resourcesWant), string(resourcesGot))
|
||||
|
||||
data, err = json.Marshal(resources)
|
||||
require.NoError(t, err)
|
||||
var resourcesMap []map[string]interface{}
|
||||
err = json.Unmarshal(data, &resourcesMap)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedNoMetadataMap, resourcesMap)
|
||||
})
|
||||
|
||||
t.Run("Provision", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tfStateRaw, err := os.ReadFile(filepath.Join(dir, folderName+".tfstate.json"))
|
||||
@@ -212,17 +226,67 @@ func TestConvertResources(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
resourcesWant, err := json.Marshal(expected)
|
||||
// Convert expectedNoMetadata and resources into a
|
||||
// []map[string]interface{} so they can be compared easily.
|
||||
data, err := json.Marshal(expected)
|
||||
require.NoError(t, err)
|
||||
resourcesGot, err := json.Marshal(resources)
|
||||
var expectedMap []map[string]interface{}
|
||||
err = json.Unmarshal(data, &expectedMap)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, string(resourcesWant), string(resourcesGot))
|
||||
data, err = json.Marshal(resources)
|
||||
require.NoError(t, err)
|
||||
var resourcesMap []map[string]interface{}
|
||||
err = json.Unmarshal(data, &resourcesMap)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedMap, resourcesMap)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppSlugValidation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// nolint:dogsled
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
|
||||
// Load the multiple-apps state file and edit it.
|
||||
dir := filepath.Join(filepath.Dir(filename), "testdata", "multiple-apps")
|
||||
tfPlanRaw, err := os.ReadFile(filepath.Join(dir, "multiple-apps.tfplan.json"))
|
||||
require.NoError(t, err)
|
||||
var tfPlan tfjson.Plan
|
||||
err = json.Unmarshal(tfPlanRaw, &tfPlan)
|
||||
require.NoError(t, err)
|
||||
tfPlanGraph, err := os.ReadFile(filepath.Join(dir, "multiple-apps.tfplan.dot"))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Change all slugs to be invalid.
|
||||
for _, resource := range tfPlan.PlannedValues.RootModule.Resources {
|
||||
if resource.Type == "coder_app" {
|
||||
resource.AttributeValues["slug"] = "$$$ invalid slug $$$"
|
||||
}
|
||||
}
|
||||
|
||||
resources, err := terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph))
|
||||
require.Nil(t, resources)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "invalid app slug")
|
||||
|
||||
// Change all slugs to be identical and valid.
|
||||
for _, resource := range tfPlan.PlannedValues.RootModule.Resources {
|
||||
if resource.Type == "coder_app" {
|
||||
resource.AttributeValues["slug"] = "valid"
|
||||
}
|
||||
}
|
||||
|
||||
resources, err = terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph))
|
||||
require.Nil(t, resources)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "duplicate app slug")
|
||||
}
|
||||
|
||||
func TestInstanceIDAssociation(t *testing.T) {
|
||||
t.Parallel()
|
||||
type tc struct {
|
||||
@@ -304,7 +368,7 @@ func sortResources(resources []*proto.Resource) {
|
||||
for _, resource := range resources {
|
||||
for _, agent := range resource.Agents {
|
||||
sort.Slice(agent.Apps, func(i, j int) bool {
|
||||
return agent.Apps[i].Name < agent.Apps[j].Name
|
||||
return agent.Apps[i].Slug < agent.Apps[j].Slug
|
||||
})
|
||||
}
|
||||
sort.Slice(resource.Agents, func(i, j int) bool {
|
||||
|
||||
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-8
@@ -66,7 +66,9 @@
|
||||
"name": "main",
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"change": {
|
||||
"actions": ["create"],
|
||||
"actions": [
|
||||
"create"
|
||||
],
|
||||
"before": null,
|
||||
"after": {
|
||||
"arch": "amd64",
|
||||
@@ -95,7 +97,9 @@
|
||||
"name": "script",
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"change": {
|
||||
"actions": ["read"],
|
||||
"actions": [
|
||||
"read"
|
||||
],
|
||||
"before": null,
|
||||
"after": {
|
||||
"inputs": {}
|
||||
@@ -125,7 +129,9 @@
|
||||
"name": "example",
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"change": {
|
||||
"actions": ["create"],
|
||||
"actions": [
|
||||
"create"
|
||||
],
|
||||
"before": null,
|
||||
"after": {
|
||||
"triggers": null
|
||||
@@ -143,7 +149,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"module.module:null": {
|
||||
"name": "null",
|
||||
@@ -175,7 +181,10 @@
|
||||
"source": "./module",
|
||||
"expressions": {
|
||||
"script": {
|
||||
"references": ["coder_agent.main.init_script", "coder_agent.main"]
|
||||
"references": [
|
||||
"coder_agent.main.init_script",
|
||||
"coder_agent.main"
|
||||
]
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
@@ -187,7 +196,9 @@
|
||||
"name": "example",
|
||||
"provider_config_key": "module.module:null",
|
||||
"schema_version": 0,
|
||||
"depends_on": ["data.null_data_source.script"]
|
||||
"depends_on": [
|
||||
"data.null_data_source.script"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": "data.null_data_source.script",
|
||||
@@ -197,7 +208,9 @@
|
||||
"provider_config_key": "module.module:null",
|
||||
"expressions": {
|
||||
"inputs": {
|
||||
"references": ["var.script"]
|
||||
"references": [
|
||||
"var.script"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schema_version": 0
|
||||
@@ -214,7 +227,9 @@
|
||||
"relevant_attributes": [
|
||||
{
|
||||
"resource": "coder_agent.main",
|
||||
"attribute": ["init_script"]
|
||||
"attribute": [
|
||||
"init_script"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+4
-4
@@ -16,11 +16,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "b92bd0ce-d854-47af-a2f6-4941cd5dbd27",
|
||||
"id": "8a08d6a8-2ae8-4af3-b385-9d7c9230c3d3",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "3f1b6b3f-7ea9-4944-bef4-8be9b78db8ae"
|
||||
"token": "e5397170-34e8-4f59-9b3d-85d11203aba1"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
}
|
||||
@@ -44,7 +44,7 @@
|
||||
"outputs": {
|
||||
"script": ""
|
||||
},
|
||||
"random": "5257014674084238393"
|
||||
"random": "4606778210381604065"
|
||||
},
|
||||
"sensitive_values": {
|
||||
"inputs": {},
|
||||
@@ -59,7 +59,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "6805057619323391144",
|
||||
"id": "8484494817832091886",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
|
||||
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -121,7 +121,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
|
||||
Generated
Vendored
+4
-4
@@ -16,11 +16,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "d8de89cb-bb6b-4f4f-80f8-e5d39e8c5f62",
|
||||
"id": "8c46ed09-5988-47fe-8f1b-2afe4ec0b35a",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "4e877d5c-95c4-4365-b9a1-856348b54f43"
|
||||
"token": "af26634c-4fa8-4b60-aff4-736d43457b35"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -32,7 +32,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "2870641260310442024",
|
||||
"id": "1333327345487383126",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
@@ -46,7 +46,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "7093709823890756895",
|
||||
"id": "1306294717300675697",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -121,7 +121,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
|
||||
Generated
Vendored
+4
-4
@@ -16,11 +16,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "5c00c97c-7291-47b7-96cf-3ac7d7588a99",
|
||||
"id": "3621f0c7-090a-4610-8fd0-bdcf835225bd",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "a1939d12-8b8a-414b-b745-3fac020e51c0"
|
||||
"token": "4cb0ef71-0161-4a1a-b8f1-b9d81f53d658"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -32,7 +32,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "8930370582092686733",
|
||||
"id": "3108014752132131382",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
@@ -46,7 +46,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "8209925920170986769",
|
||||
"id": "8356243415524842498",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
|
||||
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
|
||||
+5
-5
@@ -16,11 +16,11 @@
|
||||
"auth": "google-instance-identity",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "248ed639-3dbe-479e-909a-37d5d226529f",
|
||||
"id": "1156666a-c202-4c54-9831-6b62dbf665fe",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "8bee2595-095f-4965-ade2-deef475023d6"
|
||||
"token": "80a893a4-fcb1-4a3a-824d-74cf5317d307"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -32,8 +32,8 @@
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"agent_id": "248ed639-3dbe-479e-909a-37d5d226529f",
|
||||
"id": "edbfac7a-a88d-433a-ab7c-be3816656477",
|
||||
"agent_id": "1156666a-c202-4c54-9831-6b62dbf665fe",
|
||||
"id": "ec6451f5-fea2-4d6f-aedc-822b93723abd",
|
||||
"instance_id": "example"
|
||||
},
|
||||
"sensitive_values": {},
|
||||
@@ -47,7 +47,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "5674804341417746589",
|
||||
"id": "5076117657273396114",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
|
||||
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -180,7 +180,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
|
||||
+7
-7
@@ -16,11 +16,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "882ce97a-3c12-410f-8916-e3bc03862162",
|
||||
"id": "dc6b52bf-7bcb-4657-9c11-2859d8721ba9",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "b24ba29b-8cb3-42da-91c5-599c7be310f7"
|
||||
"token": "85317d35-1e92-4565-850e-8ee17bf86992"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -36,11 +36,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "8a26cec7-3189-4eaf-99a1-1dce00b756dc",
|
||||
"id": "a709bb80-b4df-4d4a-9cc3-4bedd009b44f",
|
||||
"init_script": "",
|
||||
"os": "darwin",
|
||||
"startup_script": null,
|
||||
"token": "6a155e3b-3279-40cb-9c16-4b827b561bc1"
|
||||
"token": "a4b37df4-dbdd-494b-9434-92abaa88c23b"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -56,11 +56,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "57486477-64a5-4fea-8223-dbf3c259d710",
|
||||
"id": "e429fb2c-1d4a-4c7c-9747-f495e5611c9e",
|
||||
"init_script": "",
|
||||
"os": "windows",
|
||||
"startup_script": null,
|
||||
"token": "0fa9933e-802a-4d6a-b273-43c05993e52a"
|
||||
"token": "27009ab7-ec2e-476c-9193-177eeea0766c"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -72,7 +72,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "8587500025119121667",
|
||||
"id": "4682926564646626748",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
|
||||
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ resource "coder_agent" "dev1" {
|
||||
# app1 is for testing subdomain default.
|
||||
resource "coder_app" "app1" {
|
||||
agent_id = coder_agent.dev1.id
|
||||
slug = "app1"
|
||||
# subdomain should default to false.
|
||||
# subdomain = false
|
||||
}
|
||||
@@ -22,6 +23,7 @@ resource "coder_app" "app1" {
|
||||
# app2 tests that subdomaincan be true, and that healthchecks work.
|
||||
resource "coder_app" "app2" {
|
||||
agent_id = coder_agent.dev1.id
|
||||
slug = "app2"
|
||||
subdomain = true
|
||||
healthcheck {
|
||||
url = "http://localhost:13337/healthz"
|
||||
@@ -33,6 +35,7 @@ resource "coder_app" "app2" {
|
||||
# app3 tests that subdomain can explicitly be false.
|
||||
resource "coder_app" "app3" {
|
||||
agent_id = coder_agent.dev1.id
|
||||
slug = "app3"
|
||||
subdomain = false
|
||||
}
|
||||
|
||||
|
||||
+28
-1
@@ -30,10 +30,13 @@
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [],
|
||||
"icon": null,
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app1",
|
||||
"subdomain": null,
|
||||
"url": null
|
||||
},
|
||||
@@ -50,6 +53,7 @@
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [
|
||||
{
|
||||
"interval": 5,
|
||||
@@ -60,6 +64,8 @@
|
||||
"icon": null,
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app2",
|
||||
"subdomain": true,
|
||||
"url": null
|
||||
},
|
||||
@@ -76,10 +82,13 @@
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [],
|
||||
"icon": null,
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app3",
|
||||
"subdomain": false,
|
||||
"url": null
|
||||
},
|
||||
@@ -142,10 +151,13 @@
|
||||
"before": null,
|
||||
"after": {
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [],
|
||||
"icon": null,
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app1",
|
||||
"subdomain": null,
|
||||
"url": null
|
||||
},
|
||||
@@ -171,6 +183,7 @@
|
||||
"before": null,
|
||||
"after": {
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [
|
||||
{
|
||||
"interval": 5,
|
||||
@@ -181,6 +194,8 @@
|
||||
"icon": null,
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app2",
|
||||
"subdomain": true,
|
||||
"url": null
|
||||
},
|
||||
@@ -206,10 +221,13 @@
|
||||
"before": null,
|
||||
"after": {
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [],
|
||||
"icon": null,
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app3",
|
||||
"subdomain": false,
|
||||
"url": null
|
||||
},
|
||||
@@ -249,7 +267,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
@@ -283,6 +301,9 @@
|
||||
"expressions": {
|
||||
"agent_id": {
|
||||
"references": ["coder_agent.dev1.id", "coder_agent.dev1"]
|
||||
},
|
||||
"slug": {
|
||||
"constant_value": "app1"
|
||||
}
|
||||
},
|
||||
"schema_version": 0
|
||||
@@ -310,6 +331,9 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"slug": {
|
||||
"constant_value": "app2"
|
||||
},
|
||||
"subdomain": {
|
||||
"constant_value": true
|
||||
}
|
||||
@@ -326,6 +350,9 @@
|
||||
"agent_id": {
|
||||
"references": ["coder_agent.dev1.id", "coder_agent.dev1"]
|
||||
},
|
||||
"slug": {
|
||||
"constant_value": "app3"
|
||||
},
|
||||
"subdomain": {
|
||||
"constant_value": false
|
||||
}
|
||||
|
||||
+18
-9
@@ -16,11 +16,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "ecf210c8-aaa7-4a14-9b44-2a5f805f0126",
|
||||
"id": "4fa379bd-8aa9-48f2-9868-2da104013c3c",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "7e748146-cea2-45cb-927d-b4a90b0021b3"
|
||||
"token": "4eb813cb-8f29-454c-91d9-b430d76d7fcd"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -32,13 +32,16 @@
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"agent_id": "ecf210c8-aaa7-4a14-9b44-2a5f805f0126",
|
||||
"agent_id": "4fa379bd-8aa9-48f2-9868-2da104013c3c",
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [],
|
||||
"icon": null,
|
||||
"id": "95667002-bd60-4d2c-9313-0666f66c44ff",
|
||||
"id": "f303f406-b9ea-4253-935e-f80f7be54a97",
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app1",
|
||||
"subdomain": null,
|
||||
"url": null
|
||||
},
|
||||
@@ -55,8 +58,9 @@
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"agent_id": "ecf210c8-aaa7-4a14-9b44-2a5f805f0126",
|
||||
"agent_id": "4fa379bd-8aa9-48f2-9868-2da104013c3c",
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [
|
||||
{
|
||||
"interval": 5,
|
||||
@@ -65,9 +69,11 @@
|
||||
}
|
||||
],
|
||||
"icon": null,
|
||||
"id": "817c6904-69e1-485f-a057-4ddac83a9c5a",
|
||||
"id": "7086ae57-501d-4b39-bfaf-d30b83f753d4",
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app2",
|
||||
"subdomain": true,
|
||||
"url": null
|
||||
},
|
||||
@@ -84,13 +90,16 @@
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"agent_id": "ecf210c8-aaa7-4a14-9b44-2a5f805f0126",
|
||||
"agent_id": "4fa379bd-8aa9-48f2-9868-2da104013c3c",
|
||||
"command": null,
|
||||
"display_name": null,
|
||||
"healthcheck": [],
|
||||
"icon": null,
|
||||
"id": "c4a502b3-cc82-4fdf-952b-4b429e711798",
|
||||
"id": "e4b1f16b-2b8d-4278-abec-1f876f8a6aba",
|
||||
"name": null,
|
||||
"relative_path": null,
|
||||
"share": "owner",
|
||||
"slug": "app3",
|
||||
"subdomain": false,
|
||||
"url": null
|
||||
},
|
||||
@@ -107,7 +116,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "1281108380136021489",
|
||||
"id": "7676198272426781226",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {},
|
||||
|
||||
@@ -2,7 +2,7 @@ terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@
|
||||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.5.0"
|
||||
"version_constraint": "0.6.0"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
|
||||
+5
-5
@@ -16,11 +16,11 @@
|
||||
"auth": "token",
|
||||
"dir": null,
|
||||
"env": null,
|
||||
"id": "0bfa269a-e373-4fbc-929a-07b8ed0f3477",
|
||||
"id": "a7e62a9d-ef94-4abc-8bd5-e0555eae4aaf",
|
||||
"init_script": "",
|
||||
"os": "linux",
|
||||
"startup_script": null,
|
||||
"token": "4bc54f84-7d97-492a-ad98-40ae7dfbb300"
|
||||
"token": "812935fe-858a-4ff5-b890-6c8eea6a3764"
|
||||
},
|
||||
"sensitive_values": {}
|
||||
},
|
||||
@@ -34,7 +34,7 @@
|
||||
"values": {
|
||||
"hide": true,
|
||||
"icon": "/icon/server.svg",
|
||||
"id": "2ee6d253-dec1-4336-95ba-bd5e93cf4c84",
|
||||
"id": "5e954683-7a6d-47f4-bc82-5831c0ea2120",
|
||||
"item": [
|
||||
{
|
||||
"is_null": false,
|
||||
@@ -61,7 +61,7 @@
|
||||
"value": "squirrel"
|
||||
}
|
||||
],
|
||||
"resource_id": "3043919679469754967"
|
||||
"resource_id": "288893601116381968"
|
||||
},
|
||||
"sensitive_values": {
|
||||
"item": [{}, {}, {}, {}]
|
||||
@@ -76,7 +76,7 @@
|
||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||
"schema_version": 0,
|
||||
"values": {
|
||||
"id": "3043919679469754967",
|
||||
"id": "288893601116381968",
|
||||
"triggers": null
|
||||
},
|
||||
"sensitive_values": {}
|
||||
|
||||
Reference in New Issue
Block a user