mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add support for optional external auth providers (#12021)
This commit is contained in:
@@ -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{
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
+28
@@ -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
|
||||
]
|
||||
}
|
||||
Generated
Vendored
+24
@@ -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)"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
Vendored
+230
@@ -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
|
||||
}
|
||||
Generated
Vendored
+24
@@ -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)"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
Vendored
+98
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user