feat: add support for optional external auth providers (#12021)

This commit is contained in:
Kayla Washburn-Love
2024-02-21 11:18:38 -07:00
committed by GitHub
parent 78c9f82719
commit 475c3650ca
39 changed files with 1495 additions and 727 deletions
+16 -6
View File
@@ -125,7 +125,7 @@ type resourceMetadataItem struct {
type State struct {
Resources []*proto.Resource
Parameters []*proto.RichParameter
ExternalAuthProviders []string
ExternalAuthProviders []*proto.ExternalAuthProviderResource
}
// ConvertState consumes Terraform state and a GraphViz representation
@@ -699,23 +699,33 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string) (*State, error
}
// A map is used to ensure we don't have duplicates!
externalAuthProvidersMap := map[string]struct{}{}
externalAuthProvidersMap := map[string]*proto.ExternalAuthProviderResource{}
for _, tfResources := range tfResourcesByLabel {
for _, resource := range tfResources {
// Checking for `coder_git_auth` is legacy!
if resource.Type != "coder_external_auth" && resource.Type != "coder_git_auth" {
continue
}
id, ok := resource.AttributeValues["id"].(string)
if !ok {
return nil, xerrors.Errorf("external auth id is not a string")
}
externalAuthProvidersMap[id] = struct{}{}
optional := false
optionalAttribute, ok := resource.AttributeValues["optional"].(bool)
if ok {
optional = optionalAttribute
}
externalAuthProvidersMap[id] = &proto.ExternalAuthProviderResource{
Id: id,
Optional: optional,
}
}
}
externalAuthProviders := make([]string, 0, len(externalAuthProvidersMap))
for id := range externalAuthProvidersMap {
externalAuthProviders = append(externalAuthProviders, id)
externalAuthProviders := make([]*proto.ExternalAuthProviderResource, 0, len(externalAuthProvidersMap))
for _, it := range externalAuthProvidersMap {
externalAuthProviders = append(externalAuthProviders, it)
}
return &State{
+30 -8
View File
@@ -7,6 +7,7 @@ import (
"path/filepath"
"runtime"
"sort"
"strings"
"testing"
tfjson "github.com/hashicorp/terraform-json"
@@ -23,9 +24,9 @@ func TestConvertResources(t *testing.T) {
// nolint:dogsled
_, filename, _, _ := runtime.Caller(0)
type testCase struct {
resources []*proto.Resource
parameters []*proto.RichParameter
gitAuthProviders []string
resources []*proto.Resource
parameters []*proto.RichParameter
externalAuthProviders []*proto.ExternalAuthProviderResource
}
// If a user doesn't specify 'display_apps' then they default
@@ -486,7 +487,22 @@ func TestConvertResources(t *testing.T) {
DisplayApps: &displayApps,
}},
}},
gitAuthProviders: []string{"github", "gitlab"},
externalAuthProviders: []*proto.ExternalAuthProviderResource{{Id: "github"}, {Id: "gitlab"}},
},
"external-auth-providers": {
resources: []*proto.Resource{{
Name: "dev",
Type: "null_resource",
Agents: []*proto.Agent{{
Name: "main",
OperatingSystem: "linux",
Architecture: "amd64",
Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
DisplayApps: &displayApps,
}},
}},
externalAuthProviders: []*proto.ExternalAuthProviderResource{{Id: "github"}, {Id: "gitlab", Optional: true}},
},
"display-apps": {
resources: []*proto.Resource{{
@@ -547,7 +563,7 @@ func TestConvertResources(t *testing.T) {
state, err := terraform.ConvertState(modules, string(tfPlanGraph))
require.NoError(t, err)
sortResources(state.Resources)
sort.Strings(state.ExternalAuthProviders)
sortExternalAuthProviders(state.ExternalAuthProviders)
expectedNoMetadata := make([]*proto.Resource, 0)
for _, resource := range expected.resources {
@@ -585,7 +601,7 @@ func TestConvertResources(t *testing.T) {
require.Equal(t, string(parametersWant), string(parametersGot))
require.Equal(t, expectedNoMetadataMap, resourcesMap)
require.ElementsMatch(t, expected.gitAuthProviders, state.ExternalAuthProviders)
require.ElementsMatch(t, expected.externalAuthProviders, state.ExternalAuthProviders)
})
t.Run("Provision", func(t *testing.T) {
@@ -601,7 +617,7 @@ func TestConvertResources(t *testing.T) {
state, err := terraform.ConvertState([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph))
require.NoError(t, err)
sortResources(state.Resources)
sort.Strings(state.ExternalAuthProviders)
sortExternalAuthProviders(state.ExternalAuthProviders)
for _, resource := range state.Resources {
for _, agent := range resource.Agents {
agent.Id = ""
@@ -628,7 +644,7 @@ func TestConvertResources(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedMap, resourcesMap)
require.ElementsMatch(t, expected.gitAuthProviders, state.ExternalAuthProviders)
require.ElementsMatch(t, expected.externalAuthProviders, state.ExternalAuthProviders)
})
})
}
@@ -901,3 +917,9 @@ func sortResources(resources []*proto.Resource) {
})
}
}
func sortExternalAuthProviders(providers []*proto.ExternalAuthProviderResource) {
sort.Slice(providers, func(i, j int) bool {
return strings.Compare(providers[i].Id, providers[j].Id) == -1
})
}
@@ -0,0 +1,28 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
version = "0.16.0"
}
}
}
data "coder_external_auth" "github" {
id = "github"
}
data "coder_external_auth" "gitlab" {
id = "gitlab"
optional = true
}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
}
resource "null_resource" "dev" {
depends_on = [
coder_agent.main
]
}
@@ -0,0 +1,24 @@
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"]
"[root] data.coder_external_auth.github (expand)" [label = "data.coder_external_auth.github", shape = "box"]
"[root] data.coder_external_auth.gitlab (expand)" [label = "data.coder_external_auth.gitlab", shape = "box"]
"[root] null_resource.dev (expand)" [label = "null_resource.dev", shape = "box"]
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
"[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"]
"[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] data.coder_external_auth.github (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] data.coder_external_auth.gitlab (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] null_resource.dev (expand)" -> "[root] coder_agent.main (expand)"
"[root] null_resource.dev (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.main (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_external_auth.github (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_external_auth.gitlab (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.dev (expand)"
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)"
}
}
@@ -0,0 +1,230 @@
{
"format_version": "1.2",
"terraform_version": "1.6.6",
"planned_values": {
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "amd64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"login_before_ready": true,
"metadata": [],
"motd_file": null,
"os": "linux",
"shutdown_script": null,
"shutdown_script_timeout": 300,
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"troubleshooting_url": null
},
"sensitive_values": {
"display_apps": [],
"metadata": []
}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"triggers": null
},
"sensitive_values": {}
}
]
}
},
"resource_changes": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"arch": "amd64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"login_before_ready": true,
"metadata": [],
"motd_file": null,
"os": "linux",
"shutdown_script": null,
"shutdown_script_timeout": 300,
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"troubleshooting_url": null
},
"after_unknown": {
"display_apps": true,
"id": true,
"init_script": true,
"metadata": [],
"token": true
},
"before_sensitive": false,
"after_sensitive": {
"display_apps": [],
"metadata": [],
"token": true
}
}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"triggers": null
},
"after_unknown": {
"id": true
},
"before_sensitive": false,
"after_sensitive": {}
}
}
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.6.6",
"values": {
"root_module": {
"resources": [
{
"address": "data.coder_external_auth.github",
"mode": "data",
"type": "coder_external_auth",
"name": "github",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "github",
"optional": null
},
"sensitive_values": {}
},
{
"address": "data.coder_external_auth.gitlab",
"mode": "data",
"type": "coder_external_auth",
"name": "gitlab",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "gitlab",
"optional": true
},
"sensitive_values": {}
}
]
}
}
},
"configuration": {
"provider_config": {
"coder": {
"name": "coder",
"full_name": "registry.terraform.io/coder/coder",
"version_constraint": "0.16.0"
},
"null": {
"name": "null",
"full_name": "registry.terraform.io/hashicorp/null"
}
},
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_config_key": "coder",
"expressions": {
"arch": {
"constant_value": "amd64"
},
"os": {
"constant_value": "linux"
}
},
"schema_version": 0
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_config_key": "null",
"schema_version": 0,
"depends_on": [
"coder_agent.main"
]
},
{
"address": "data.coder_external_auth.github",
"mode": "data",
"type": "coder_external_auth",
"name": "github",
"provider_config_key": "coder",
"expressions": {
"id": {
"constant_value": "github"
}
},
"schema_version": 0
},
{
"address": "data.coder_external_auth.gitlab",
"mode": "data",
"type": "coder_external_auth",
"name": "gitlab",
"provider_config_key": "coder",
"expressions": {
"id": {
"constant_value": "gitlab"
},
"optional": {
"constant_value": true
}
},
"schema_version": 0
}
]
}
},
"timestamp": "2024-02-12T23:11:52Z",
"errored": false
}
@@ -0,0 +1,24 @@
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"]
"[root] data.coder_external_auth.github (expand)" [label = "data.coder_external_auth.github", shape = "box"]
"[root] data.coder_external_auth.gitlab (expand)" [label = "data.coder_external_auth.gitlab", shape = "box"]
"[root] null_resource.dev (expand)" [label = "null_resource.dev", shape = "box"]
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
"[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"]
"[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] data.coder_external_auth.github (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] data.coder_external_auth.gitlab (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] null_resource.dev (expand)" -> "[root] coder_agent.main (expand)"
"[root] null_resource.dev (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.main (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_external_auth.github (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_external_auth.gitlab (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.dev (expand)"
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)"
}
}
@@ -0,0 +1,98 @@
{
"format_version": "1.0",
"terraform_version": "1.6.6",
"values": {
"root_module": {
"resources": [
{
"address": "data.coder_external_auth.github",
"mode": "data",
"type": "coder_external_auth",
"name": "github",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "github",
"optional": null
},
"sensitive_values": {}
},
{
"address": "data.coder_external_auth.gitlab",
"mode": "data",
"type": "coder_external_auth",
"name": "gitlab",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "gitlab",
"optional": true
},
"sensitive_values": {}
},
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "amd64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"display_apps": [
{
"port_forwarding_helper": true,
"ssh_helper": true,
"vscode": true,
"vscode_insiders": false,
"web_terminal": true
}
],
"env": null,
"id": "d1f23602-ef8e-4ecf-aa5a-df8aa476344e",
"init_script": "",
"login_before_ready": true,
"metadata": [],
"motd_file": null,
"os": "linux",
"shutdown_script": null,
"shutdown_script_timeout": 300,
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "90440015-11c8-442b-adba-9f2bd279b5c7",
"troubleshooting_url": null
},
"sensitive_values": {
"display_apps": [
{}
],
"metadata": [],
"token": true
}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "8183284779544326910",
"triggers": null
},
"sensitive_values": {},
"depends_on": [
"coder_agent.main"
]
}
]
}
}
}