From 48bcf2ccdc8885793252069514a92334712ac1a0 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Thu, 24 Feb 2022 16:37:35 +0000 Subject: [PATCH 01/10] ci: Update DataDog GitHub branch to fallback to GITHUB_REF This was detecting branches, but not our "main" branch before. Hopefully this fixes it! --- scripts/datadog-cireport/main.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/datadog-cireport/main.go b/scripts/datadog-cireport/main.go index 2c0b3a3e67844..51fb902b1689e 100644 --- a/scripts/datadog-cireport/main.go +++ b/scripts/datadog-cireport/main.go @@ -59,9 +59,16 @@ func main() { } commitParts := strings.Split(string(commitData), ",") + // On pull requests, this will be set! branch := os.Getenv("GITHUB_HEAD_REF") if branch == "" { - branch = os.Getenv("GITHUB_BASE_REF") + githubRef := os.Getenv("GITHUB_REF") + for _, prefix := range []string{"refs/heads/", "refs/tags/"} { + if !strings.HasPrefix(githubRef, prefix) { + continue + } + branch = strings.TrimPrefix(githubRef, prefix) + } } tags := map[string]string{ From eb50cda5f7446b984e328c66ed642286791adefb Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 25 Feb 2022 17:09:55 +0000 Subject: [PATCH 02/10] Add basic Terraform Provider --- Makefile | 12 +- cmd/terraform-provider-coder/main.go | 12 + coderd/downloads.go | 5 + codersdk/files.go | 7 + go.mod | 18 + go.sum | 53 ++ provisioner/terraform/provider/provider.go | 125 +++++ .../terraform/provider/provider_test.go | 69 +++ provisionersdk/agent.go | 77 +++ provisionersdk/agent_test.go | 51 ++ provisionersdk/proto/provisioner.pb.go | 510 ++++++++++++------ provisionersdk/proto/provisioner.proto | 25 +- 12 files changed, 799 insertions(+), 165 deletions(-) create mode 100644 cmd/terraform-provider-coder/main.go create mode 100644 coderd/downloads.go create mode 100644 provisioner/terraform/provider/provider.go create mode 100644 provisioner/terraform/provider/provider_test.go create mode 100644 provisionersdk/agent.go create mode 100644 provisionersdk/agent_test.go diff --git a/Makefile b/Makefile index 981c9c4846012..ba0fc488443ed 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,12 @@ bin/coderd: go build -o bin/coderd cmd/coderd/main.go .PHONY: bin/coderd -build: site/out bin/coder bin/coderd +bin/terraform-provider-coder: + mkdir -p bin + go build -o bin/terraform-provider-coder cmd/terraform-provider-coder/main.go +.PHONY: bin/terraform-provider-coder + +build: site/out bin/coder bin/coderd bin/terraform-provider-coder .PHONY: build # Runs migrations to output a dump of the database. @@ -59,6 +64,11 @@ install: @echo "-- CLI available at $(shell ls $(INSTALL_DIR)/coder*)" .PHONY: install +install/terraform-provider-coder: bin/terraform-provider-coder + $(eval OS_ARCH := $(shell go env GOOS)_$(shell go env GOARCH)) + mkdir -p ~/.terraform.d/plugins/coder.com/internal/coder/0.2/$(OS_ARCH) + cp bin/terraform-provider-coder ~/.terraform.d/plugins/coder.com/internal/coder/0.2/$(OS_ARCH) + peerbroker/proto: peerbroker/proto/peerbroker.proto protoc \ --go_out=. \ diff --git a/cmd/terraform-provider-coder/main.go b/cmd/terraform-provider-coder/main.go new file mode 100644 index 0000000000000..2cff70b9d0172 --- /dev/null +++ b/cmd/terraform-provider-coder/main.go @@ -0,0 +1,12 @@ +package main + +import ( + "github.com/coder/coder/provisioner/terraform/provider" + "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" +) + +func main() { + plugin.Serve(&plugin.ServeOpts{ + ProviderFunc: provider.New, + }) +} diff --git a/coderd/downloads.go b/coderd/downloads.go new file mode 100644 index 0000000000000..621347e8b7ff5 --- /dev/null +++ b/coderd/downloads.go @@ -0,0 +1,5 @@ +package coderd + +func downloads() { + +} diff --git a/codersdk/files.go b/codersdk/files.go index f4fe82f8cd146..efd25adae27d7 100644 --- a/codersdk/files.go +++ b/codersdk/files.go @@ -3,7 +3,9 @@ package codersdk import ( "context" "encoding/json" + "fmt" "net/http" + "net/url" "github.com/coder/coder/coderd" ) @@ -26,3 +28,8 @@ func (c *Client) UploadFile(ctx context.Context, contentType string, content []b var resp coderd.UploadFileResponse return resp, json.NewDecoder(res.Body).Decode(&resp) } + +// DownloadURL returns +func (c *Client) DownloadURL(asset string) (*url.URL, error) { + return c.URL.Parse(fmt.Sprintf("/api/v2/downloads/%s", asset)) +} diff --git a/go.mod b/go.mod index 40e1fe657e18e..35569e6f1ec01 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/hashicorp/go-version v1.4.0 github.com/hashicorp/terraform-config-inspect v0.0.0-20211115214459-90acf1ca460f github.com/hashicorp/terraform-exec v0.15.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1 github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 github.com/justinas/nosurf v1.1.1 github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f @@ -96,10 +97,22 @@ require ( github.com/google/go-cmp v0.5.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-checkpoint v0.5.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect + github.com/hashicorp/go-hclog v1.0.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-plugin v1.4.1 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/hc-install v0.3.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl/v2 v2.11.1 // indirect + github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-json v0.13.0 // indirect + github.com/hashicorp/terraform-plugin-go v0.5.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.2.0 // indirect + github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896 // indirect + github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc // indirect @@ -107,8 +120,12 @@ require ( github.com/leodido/go-urn v1.2.1 // indirect github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/oklog/run v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runc v1.1.0 // indirect @@ -129,6 +146,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect diff --git a/go.sum b/go.sum index 55f6d6c8cc674..6c5de14b22110 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,7 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.61.0/go.mod h1:XukKJg4Y7QsUu0Hxg3qQKUWR4VuWivmyMK2+rUyxAqw= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= @@ -140,9 +141,13 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= +github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= +github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -155,6 +160,7 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= @@ -674,12 +680,19 @@ github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FK github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= +github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= +github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0 h1:bkKf0BeBXcSYa7f5Fyi9gMuQ8gNsxeiNpZjR6VxNZeo= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -689,12 +702,18 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= +github.com/hashicorp/go-plugin v1.4.1 h1:6UltRQlLN9iZO513VveELp5xyaFxVD2+1OVylE+2E+w= +github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -707,8 +726,10 @@ github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= +github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= github.com/hashicorp/hcl/v2 v2.11.1 h1:yTyWcXcm9XB0TEkyU/JCRU6rYy4K+mgLtzn2wlrJbcc= github.com/hashicorp/hcl/v2 v2.11.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= @@ -718,6 +739,18 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY= github.com/hashicorp/terraform-json v0.13.0/go.mod h1:y5OdLBCT+rxbwnpxZs9kGL7R9ExU76+cpdY8zHwoazk= +github.com/hashicorp/terraform-plugin-go v0.5.0 h1:+gCDdF0hcYCm0YBTxrP4+K1NGIS5ZKZBKDORBewLJmg= +github.com/hashicorp/terraform-plugin-go v0.5.0/go.mod h1:PAVN26PNGpkkmsvva1qfriae5Arky3xl3NfzKa8XFVM= +github.com/hashicorp/terraform-plugin-log v0.2.0 h1:rjflRuBqCnSk3UHOR25MP1G5BDLKktTA6lNjjcAnBfI= +github.com/hashicorp/terraform-plugin-log v0.2.0/go.mod h1:E1kJmapEHzqu1x6M++gjvhzM2yMQNXPVWZRCB8sgYjg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1 h1:B9AocC+dxrCqcf4vVhztIkSkt3gpRjUkEka8AmZWGlQ= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1/go.mod h1:FjM9DXWfP0w/AeOtJoSKHBZ01LqmaO6uP4bXhv3fekw= +github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896 h1:1FGtlkJw87UsTMg5s8jrekrHmUPUJaMcu6ELiVhQrNw= +github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896/go.mod h1:bzBPnUIkI0RxauU8Dqo+2KrZZ28Cf48s8V6IHt3p4co= +github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= +github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -779,6 +812,8 @@ github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= +github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -923,10 +958,14 @@ github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJys github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -938,6 +977,7 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/moby v20.10.12+incompatible h1:MJVrdG0tIQqVJQBTdtooPuZQFIgski5pYTXlcW8ToE0= @@ -970,8 +1010,12 @@ github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86w github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= +github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1231,6 +1275,8 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= @@ -1381,6 +1427,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1407,6 +1454,7 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1676,6 +1724,7 @@ golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -1755,6 +1804,7 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1783,6 +1833,7 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1833,6 +1884,7 @@ google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2 google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf h1:SVYXkUz2yZS9FWb2Gm8ivSlbNQzL2Z/NpPKE3RG2jWk= google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1849,6 +1901,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= diff --git a/provisioner/terraform/provider/provider.go b/provisioner/terraform/provider/provider.go new file mode 100644 index 0000000000000..8972a4158aaca --- /dev/null +++ b/provisioner/terraform/provider/provider.go @@ -0,0 +1,125 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +// New returns a new schema provider for Terraform. +func New() *schema.Provider { + return &schema.Provider{ + Schema: map[string]*schema.Schema{ + "workspace_history_id": { + Type: schema.TypeString, + Optional: true, + }, + }, + DataSourcesMap: map[string]*schema.Resource{ + "coder_agent_script": { + Description: "TODO", + ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + osRaw := rd.Get("os") + os := osRaw.(string) + + archRaw := rd.Get("arch") + arch := archRaw.(string) + + fmt.Printf("Got OS: %s_%s\n", os, arch) + + err := rd.Set("value", "SOME SCRIPT") + if err != nil { + return diag.FromErr(err) + } + rd.SetId("something") + return nil + }, + Schema: map[string]*schema.Schema{ + "os": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"linux", "darwin", "windows"}, false), + }, + "arch": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + ResourcesMap: map[string]*schema.Resource{ + "coder_agent": { + Description: "TODO", + CreateContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + // This should be a real authentication token! + rd.SetId(uuid.NewString()) + rd.Set("token", uuid.NewString()) + return nil + }, + ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + authRaw := rd.Get("auth").([]interface{})[0] + if authRaw != nil { + auth := authRaw.(map[string]interface{}) + fmt.Printf("Auth got %+v\n", auth) + } + + env := rd.Get("env").(map[string]interface{}) + for key, value := range env { + fmt.Printf("Got: %s, %s\n", key, value) + } + return nil + }, + DeleteContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + return nil + }, + Schema: map[string]*schema.Schema{ + "auth": { + ForceNew: true, + Description: "TODO", + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Description: "TODO", + Optional: true, + Type: schema.TypeString, + }, + "instance_id": { + Description: "TODO", + Optional: true, + Type: schema.TypeString, + }, + }, + }, + }, + "env": { + ForceNew: true, + Description: "TODO", + Type: schema.TypeMap, + Optional: true, + }, + "startup_script": { + ForceNew: true, + Description: "TODO", + Type: schema.TypeString, + Optional: true, + }, + "token": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + } +} diff --git a/provisioner/terraform/provider/provider_test.go b/provisioner/terraform/provider/provider_test.go new file mode 100644 index 0000000000000..4a59b9fcb2705 --- /dev/null +++ b/provisioner/terraform/provider/provider_test.go @@ -0,0 +1,69 @@ +package provider_test + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/stretchr/testify/require" + + "github.com/coder/coder/provisioner/terraform/provider" +) + +func TestProvider(t *testing.T) { + t.Parallel() + tfProvider := provider.New() + err := tfProvider.InternalValidate() + require.NoError(t, err) +} + +func TestSomething(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: `data "coder_agent_script" "new" { + arch = "x64" + os = "linux" + }`, + Check: func(s *terraform.State) error { + fmt.Printf("check state: %+v\n", s) + return nil + }, + }}, + }) +} + +func TestAnother(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: `resource "coder_agent" "new" { + auth { + type = "gcp" + } + env = { + test = "some magic value" + } + }`, + Check: func(s *terraform.State) error { + fmt.Printf("State: %+v\n", s) + // for _, mod := range s.Modules { + // fmt.Printf("check state: %+v\n", mod.Resources) + // } + data, _ := json.MarshalIndent(s, "", "\t") + fmt.Printf("Data: %s\n", data) + + return nil + }, + }}, + }) +} diff --git a/provisionersdk/agent.go b/provisionersdk/agent.go new file mode 100644 index 0000000000000..86c26856c3d2a --- /dev/null +++ b/provisionersdk/agent.go @@ -0,0 +1,77 @@ +package provisionersdk + +import ( + "net/url" + "strings" + + "golang.org/x/xerrors" +) + +var ( + // A mapping of operating-system ($GOOS) to architecture ($GOARCH) + // to agent install and run script. ${DOWNLOAD_URL} is replaced + // with strings.ReplaceAll() when being consumed. + agentScript = map[string]map[string]string{ + "windows": { + "amd64": ` +$ProgressPreference = "SilentlyContinue" +$ErrorActionPreference = "Stop" +Invoke-WebRequest -Uri ${DOWNLOAD_URL} -OutFile $env:TEMP\coder.exe +Start-Process -FilePath $env:TEMP\coder.exe workspaces agent +`, + }, + "linux": { + "amd64": ` +#!/usr/bin/env sh +set -eu pipefail +BINARY_LOCATION=$(mktemp -d)/coder +curl -fsSL ${DOWNLOAD_URL} -o $BINARY_LOCATION +chmod +x $BINARY_LOCATION +exec $BINARY_LOCATION agent +`, + }, + "darwin": { + "amd64": ` +#!/usr/bin/env sh +set -eu pipefail +BINARY_LOCATION=$(mktemp -d)/coder +curl -fsSL ${DOWNLOAD_URL} -o $BINARY_LOCATION +chmod +x $BINARY_LOCATION +exec $BINARY_LOCATION agent +`, + }, + } +) + +// AgentBinaryName returns the binary name for an operating system and agent. +func AgentBinaryName(operatingSystem, architecture string) (string, error) { + +} + +// AgentScript returns an installation script for the specified operating system +// and architecture. +// +// baseURL is +func AgentScript(operatingSystem, architecture string, baseURL *url.URL) (string, error) { + architectures, ok := agentScript[operatingSystem] + if !ok { + list := []string{} + for key := range agentScript { + list = append(list, key) + } + return "", xerrors.Errorf("operating system %q not supported. must be in: %v", operatingSystem, list) + } + script, ok := architectures[architecture] + if !ok { + list := []string{} + for key := range architectures { + list = append(list, key) + } + return "", xerrors.Errorf("architecture %q not supported for %q. must be in: %v", architecture, operatingSystem, list) + } + if !strings.HasPrefix(baseURL.Path, "/api/v2/downloads") { + + } + + return strings.ReplaceAll(script, "${DOWNLOAD_URL}", baseURL.String()), nil +} diff --git a/provisionersdk/agent_test.go b/provisionersdk/agent_test.go new file mode 100644 index 0000000000000..9e3a0dd23fbcc --- /dev/null +++ b/provisionersdk/agent_test.go @@ -0,0 +1,51 @@ +package provisionersdk_test + +import ( + "net/http" + "net/http/httptest" + "os" + "os/exec" + "runtime" + "strings" + "testing" + + "github.com/coder/coder/provisionersdk" + "github.com/go-chi/render" + "github.com/stretchr/testify/require" +) + +func TestAgentScript(t *testing.T) { + t.Parallel() + t.Run("Run", func(t *testing.T) { + t.Parallel() + srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + content, err := os.ReadFile("/usr/bin/echo") + require.NoError(t, err) + render.Status(r, http.StatusOK) + render.Data(rw, r, content) + })) + t.Cleanup(srv.Close) + + script, err := provisionersdk.AgentScript(runtime.GOOS, runtime.GOARCH, srv.URL) + require.NoError(t, err) + + output, err := exec.Command("sh", "-c", script).CombinedOutput() + t.Log(string(output)) + require.NoError(t, err) + // Because we use the "echo" binary, we should expect the arguments provided + // as the response to executing our script. + require.Equal(t, "agent", strings.TrimSpace(string(output))) + }) + + t.Run("UnsupportedOS", func(t *testing.T) { + t.Parallel() + _, err := provisionersdk.AgentScript("unsupported", "", nil) + require.Error(t, err) + }) + + t.Run("UnsupportedArch", func(t *testing.T) { + t.Parallel() + _, err := provisionersdk.AgentScript(runtime.GOOS, "unsupported", nil) + require.Error(t, err) + }) +} diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 1912c35f9044f..5c158fab41bee 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -563,27 +563,166 @@ func (x *Log) GetOutput() string { return "" } +type GoogleInstanceIdentityAuth struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InstanceId string `protobuf:"bytes,1,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` +} + +func (x *GoogleInstanceIdentityAuth) Reset() { + *x = GoogleInstanceIdentityAuth{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GoogleInstanceIdentityAuth) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GoogleInstanceIdentityAuth) ProtoMessage() {} + +func (x *GoogleInstanceIdentityAuth) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GoogleInstanceIdentityAuth.ProtoReflect.Descriptor instead. +func (*GoogleInstanceIdentityAuth) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{5} +} + +func (x *GoogleInstanceIdentityAuth) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + +// Agent represents a running agent on the workspace. +type Agent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Env map[string]string `protobuf:"bytes,3,rep,name=env,proto3" json:"env,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + StartupScript string `protobuf:"bytes,4,opt,name=startup_script,json=startupScript,proto3" json:"startup_script,omitempty"` + // Types that are assignable to Auth: + // *Agent_Token + // *Agent_GoogleInstanceIdentity + Auth isAgent_Auth `protobuf_oneof:"auth"` +} + +func (x *Agent) Reset() { + *x = Agent{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Agent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Agent) ProtoMessage() {} + +func (x *Agent) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Agent.ProtoReflect.Descriptor instead. +func (*Agent) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6} +} + +func (x *Agent) GetEnv() map[string]string { + if x != nil { + return x.Env + } + return nil +} + +func (x *Agent) GetStartupScript() string { + if x != nil { + return x.StartupScript + } + return "" +} + +func (m *Agent) GetAuth() isAgent_Auth { + if m != nil { + return m.Auth + } + return nil +} + +func (x *Agent) GetToken() string { + if x, ok := x.GetAuth().(*Agent_Token); ok { + return x.Token + } + return "" +} + +func (x *Agent) GetGoogleInstanceIdentity() *GoogleInstanceIdentityAuth { + if x, ok := x.GetAuth().(*Agent_GoogleInstanceIdentity); ok { + return x.GoogleInstanceIdentity + } + return nil +} + +type isAgent_Auth interface { + isAgent_Auth() +} + +type Agent_Token struct { + Token string `protobuf:"bytes,5,opt,name=token,proto3,oneof"` +} + +type Agent_GoogleInstanceIdentity struct { + // https://cloud.google.com/compute/docs/instances/verifying-instance-identity + GoogleInstanceIdentity *GoogleInstanceIdentityAuth `protobuf:"bytes,6,opt,name=google_instance_identity,json=googleInstanceIdentity,proto3,oneof"` +} + +func (*Agent_Token) isAgent_Auth() {} + +func (*Agent_GoogleInstanceIdentity) isAgent_Auth() {} + // Resource represents created infrastructure. type Resource struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` - // An optional identifier used for automating Workspace Agent authentication. - // Each cloud has it's own unique instance identity signatures, which can be - // used for zero-token authentication. See: - // GCP: https://cloud.google.com/compute/docs/instances/verifying-instance-identity - // AWS: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html - // Azure: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux#get-attested-data - InstanceId string `protobuf:"bytes,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Agent *Agent `protobuf:"bytes,3,opt,name=agent,proto3" json:"agent,omitempty"` } func (x *Resource) Reset() { *x = Resource{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[5] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -596,7 +735,7 @@ func (x *Resource) String() string { func (*Resource) ProtoMessage() {} func (x *Resource) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[5] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -609,7 +748,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message { // Deprecated: Use Resource.ProtoReflect.Descriptor instead. func (*Resource) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{5} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{7} } func (x *Resource) GetName() string { @@ -626,11 +765,11 @@ func (x *Resource) GetType() string { return "" } -func (x *Resource) GetInstanceId() string { +func (x *Resource) GetAgent() *Agent { if x != nil { - return x.InstanceId + return x.Agent } - return "" + return nil } // Parse consumes source-code from a directory to produce inputs. @@ -643,7 +782,7 @@ type Parse struct { func (x *Parse) Reset() { *x = Parse{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[6] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -656,7 +795,7 @@ func (x *Parse) String() string { func (*Parse) ProtoMessage() {} func (x *Parse) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[6] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -669,7 +808,7 @@ func (x *Parse) ProtoReflect() protoreflect.Message { // Deprecated: Use Parse.ProtoReflect.Descriptor instead. func (*Parse) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{8} } // Provision consumes source-code from a directory to produce resources. @@ -682,7 +821,7 @@ type Provision struct { func (x *Provision) Reset() { *x = Provision{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[7] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -695,7 +834,7 @@ func (x *Provision) String() string { func (*Provision) ProtoMessage() {} func (x *Provision) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[7] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -708,7 +847,7 @@ func (x *Provision) ProtoReflect() protoreflect.Message { // Deprecated: Use Provision.ProtoReflect.Descriptor instead. func (*Provision) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{7} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9} } type Parse_Request struct { @@ -722,7 +861,7 @@ type Parse_Request struct { func (x *Parse_Request) Reset() { *x = Parse_Request{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[8] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -735,7 +874,7 @@ func (x *Parse_Request) String() string { func (*Parse_Request) ProtoMessage() {} func (x *Parse_Request) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[8] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -748,7 +887,7 @@ func (x *Parse_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use Parse_Request.ProtoReflect.Descriptor instead. func (*Parse_Request) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6, 0} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{8, 0} } func (x *Parse_Request) GetDirectory() string { @@ -769,7 +908,7 @@ type Parse_Complete struct { func (x *Parse_Complete) Reset() { *x = Parse_Complete{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[9] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -782,7 +921,7 @@ func (x *Parse_Complete) String() string { func (*Parse_Complete) ProtoMessage() {} func (x *Parse_Complete) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[9] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -795,7 +934,7 @@ func (x *Parse_Complete) ProtoReflect() protoreflect.Message { // Deprecated: Use Parse_Complete.ProtoReflect.Descriptor instead. func (*Parse_Complete) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6, 1} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{8, 1} } func (x *Parse_Complete) GetParameterSchemas() []*ParameterSchema { @@ -819,7 +958,7 @@ type Parse_Response struct { func (x *Parse_Response) Reset() { *x = Parse_Response{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[10] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -832,7 +971,7 @@ func (x *Parse_Response) String() string { func (*Parse_Response) ProtoMessage() {} func (x *Parse_Response) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[10] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -845,7 +984,7 @@ func (x *Parse_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use Parse_Response.ProtoReflect.Descriptor instead. func (*Parse_Response) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6, 2} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{8, 2} } func (m *Parse_Response) GetType() isParse_Response_Type { @@ -893,13 +1032,12 @@ type Provision_Request struct { Directory string `protobuf:"bytes,1,opt,name=directory,proto3" json:"directory,omitempty"` ParameterValues []*ParameterValue `protobuf:"bytes,2,rep,name=parameter_values,json=parameterValues,proto3" json:"parameter_values,omitempty"` State []byte `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` - DryRun bool `protobuf:"varint,4,opt,name=dry_run,json=dryRun,proto3" json:"dry_run,omitempty"` } func (x *Provision_Request) Reset() { *x = Provision_Request{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[11] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -912,7 +1050,7 @@ func (x *Provision_Request) String() string { func (*Provision_Request) ProtoMessage() {} func (x *Provision_Request) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[11] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -925,7 +1063,7 @@ func (x *Provision_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use Provision_Request.ProtoReflect.Descriptor instead. func (*Provision_Request) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{7, 0} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9, 0} } func (x *Provision_Request) GetDirectory() string { @@ -949,13 +1087,6 @@ func (x *Provision_Request) GetState() []byte { return nil } -func (x *Provision_Request) GetDryRun() bool { - if x != nil { - return x.DryRun - } - return false -} - type Provision_Complete struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -963,12 +1094,13 @@ type Provision_Complete struct { State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` + Agents []*Agent `protobuf:"bytes,3,rep,name=agents,proto3" json:"agents,omitempty"` } func (x *Provision_Complete) Reset() { *x = Provision_Complete{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -981,7 +1113,7 @@ func (x *Provision_Complete) String() string { func (*Provision_Complete) ProtoMessage() {} func (x *Provision_Complete) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -994,7 +1126,7 @@ func (x *Provision_Complete) ProtoReflect() protoreflect.Message { // Deprecated: Use Provision_Complete.ProtoReflect.Descriptor instead. func (*Provision_Complete) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{7, 1} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9, 1} } func (x *Provision_Complete) GetState() []byte { @@ -1011,6 +1143,13 @@ func (x *Provision_Complete) GetResources() []*Resource { return nil } +func (x *Provision_Complete) GetAgents() []*Agent { + if x != nil { + return x.Agents + } + return nil +} + type Provision_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1025,7 +1164,7 @@ type Provision_Response struct { func (x *Provision_Response) Reset() { *x = Provision_Response{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1038,7 +1177,7 @@ func (x *Provision_Response) String() string { func (*Provision_Response) ProtoMessage() {} func (x *Provision_Response) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1051,7 +1190,7 @@ func (x *Provision_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use Provision_Response.ProtoReflect.Descriptor instead. func (*Provision_Response) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{7, 2} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9, 2} } func (m *Provision_Response) GetType() isProvision_Response_Type { @@ -1169,70 +1308,94 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x53, 0x0a, 0x08, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, - 0xfc, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x79, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x49, - 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x63, - 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, - 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xfc, - 0x02, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x9e, 0x01, 0x0a, - 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x55, 0x0a, - 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, - 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x3d, 0x0a, 0x1a, 0x47, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x9a, 0x02, 0x0a, 0x05, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x65, + 0x6e, 0x76, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x75, 0x70, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x63, 0x0a, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x16, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, + 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0x5c, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x22, 0xfc, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x73, + 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, + 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, + 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x90, 0x03, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x1a, 0x85, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, + 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x81, 0x01, 0x0a, 0x08, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x77, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, + 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, + 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, + 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, + 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, - 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, - 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, - 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, - 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x32, 0xa1, - 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x42, - 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1248,26 +1411,29 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte { } var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 14) +var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ - (LogLevel)(0), // 0: provisioner.LogLevel - (ParameterSource_Scheme)(0), // 1: provisioner.ParameterSource.Scheme - (ParameterDestination_Scheme)(0), // 2: provisioner.ParameterDestination.Scheme - (ParameterSchema_TypeSystem)(0), // 3: provisioner.ParameterSchema.TypeSystem - (*ParameterSource)(nil), // 4: provisioner.ParameterSource - (*ParameterDestination)(nil), // 5: provisioner.ParameterDestination - (*ParameterValue)(nil), // 6: provisioner.ParameterValue - (*ParameterSchema)(nil), // 7: provisioner.ParameterSchema - (*Log)(nil), // 8: provisioner.Log - (*Resource)(nil), // 9: provisioner.Resource - (*Parse)(nil), // 10: provisioner.Parse - (*Provision)(nil), // 11: provisioner.Provision - (*Parse_Request)(nil), // 12: provisioner.Parse.Request - (*Parse_Complete)(nil), // 13: provisioner.Parse.Complete - (*Parse_Response)(nil), // 14: provisioner.Parse.Response - (*Provision_Request)(nil), // 15: provisioner.Provision.Request - (*Provision_Complete)(nil), // 16: provisioner.Provision.Complete - (*Provision_Response)(nil), // 17: provisioner.Provision.Response + (LogLevel)(0), // 0: provisioner.LogLevel + (ParameterSource_Scheme)(0), // 1: provisioner.ParameterSource.Scheme + (ParameterDestination_Scheme)(0), // 2: provisioner.ParameterDestination.Scheme + (ParameterSchema_TypeSystem)(0), // 3: provisioner.ParameterSchema.TypeSystem + (*ParameterSource)(nil), // 4: provisioner.ParameterSource + (*ParameterDestination)(nil), // 5: provisioner.ParameterDestination + (*ParameterValue)(nil), // 6: provisioner.ParameterValue + (*ParameterSchema)(nil), // 7: provisioner.ParameterSchema + (*Log)(nil), // 8: provisioner.Log + (*GoogleInstanceIdentityAuth)(nil), // 9: provisioner.GoogleInstanceIdentityAuth + (*Agent)(nil), // 10: provisioner.Agent + (*Resource)(nil), // 11: provisioner.Resource + (*Parse)(nil), // 12: provisioner.Parse + (*Provision)(nil), // 13: provisioner.Provision + nil, // 14: provisioner.Agent.EnvEntry + (*Parse_Request)(nil), // 15: provisioner.Parse.Request + (*Parse_Complete)(nil), // 16: provisioner.Parse.Complete + (*Parse_Response)(nil), // 17: provisioner.Parse.Response + (*Provision_Request)(nil), // 18: provisioner.Provision.Request + (*Provision_Complete)(nil), // 19: provisioner.Provision.Complete + (*Provision_Response)(nil), // 20: provisioner.Provision.Response } var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ 1, // 0: provisioner.ParameterSource.scheme:type_name -> provisioner.ParameterSource.Scheme @@ -1277,22 +1443,26 @@ var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ 5, // 4: provisioner.ParameterSchema.default_destination:type_name -> provisioner.ParameterDestination 3, // 5: provisioner.ParameterSchema.validation_type_system:type_name -> provisioner.ParameterSchema.TypeSystem 0, // 6: provisioner.Log.level:type_name -> provisioner.LogLevel - 7, // 7: provisioner.Parse.Complete.parameter_schemas:type_name -> provisioner.ParameterSchema - 8, // 8: provisioner.Parse.Response.log:type_name -> provisioner.Log - 13, // 9: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete - 6, // 10: provisioner.Provision.Request.parameter_values:type_name -> provisioner.ParameterValue - 9, // 11: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource - 8, // 12: provisioner.Provision.Response.log:type_name -> provisioner.Log - 16, // 13: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete - 12, // 14: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request - 15, // 15: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request - 14, // 16: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response - 17, // 17: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response - 16, // [16:18] is the sub-list for method output_type - 14, // [14:16] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 14, // 7: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry + 9, // 8: provisioner.Agent.google_instance_identity:type_name -> provisioner.GoogleInstanceIdentityAuth + 10, // 9: provisioner.Resource.agent:type_name -> provisioner.Agent + 7, // 10: provisioner.Parse.Complete.parameter_schemas:type_name -> provisioner.ParameterSchema + 8, // 11: provisioner.Parse.Response.log:type_name -> provisioner.Log + 16, // 12: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete + 6, // 13: provisioner.Provision.Request.parameter_values:type_name -> provisioner.ParameterValue + 11, // 14: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource + 10, // 15: provisioner.Provision.Complete.agents:type_name -> provisioner.Agent + 8, // 16: provisioner.Provision.Response.log:type_name -> provisioner.Log + 19, // 17: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete + 15, // 18: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request + 18, // 19: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request + 17, // 20: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response + 20, // 21: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response + 20, // [20:22] is the sub-list for method output_type + 18, // [18:20] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name } func init() { file_provisionersdk_proto_provisioner_proto_init() } @@ -1362,7 +1532,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Resource); i { + switch v := v.(*GoogleInstanceIdentityAuth); i { case 0: return &v.state case 1: @@ -1374,7 +1544,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Parse); i { + switch v := v.(*Agent); i { case 0: return &v.state case 1: @@ -1386,7 +1556,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision); i { + switch v := v.(*Resource); i { case 0: return &v.state case 1: @@ -1398,7 +1568,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Parse_Request); i { + switch v := v.(*Parse); i { case 0: return &v.state case 1: @@ -1410,6 +1580,30 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Provision); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_provisionersdk_proto_provisioner_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Parse_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_provisionersdk_proto_provisioner_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Parse_Complete); i { case 0: return &v.state @@ -1421,7 +1615,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_provisionersdk_proto_provisioner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Parse_Response); i { case 0: return &v.state @@ -1433,7 +1627,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_provisionersdk_proto_provisioner_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Provision_Request); i { case 0: return &v.state @@ -1445,7 +1639,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_provisionersdk_proto_provisioner_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Provision_Complete); i { case 0: return &v.state @@ -1457,7 +1651,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_provisionersdk_proto_provisioner_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Provision_Response); i { case 0: return &v.state @@ -1470,11 +1664,15 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } } - file_provisionersdk_proto_provisioner_proto_msgTypes[10].OneofWrappers = []interface{}{ + file_provisionersdk_proto_provisioner_proto_msgTypes[6].OneofWrappers = []interface{}{ + (*Agent_Token)(nil), + (*Agent_GoogleInstanceIdentity)(nil), + } + file_provisionersdk_proto_provisioner_proto_msgTypes[13].OneofWrappers = []interface{}{ (*Parse_Response_Log)(nil), (*Parse_Response_Complete)(nil), } - file_provisionersdk_proto_provisioner_proto_msgTypes[13].OneofWrappers = []interface{}{ + file_provisionersdk_proto_provisioner_proto_msgTypes[16].OneofWrappers = []interface{}{ (*Provision_Response_Log)(nil), (*Provision_Response_Complete)(nil), } @@ -1484,7 +1682,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc, NumEnums: 4, - NumMessages: 14, + NumMessages: 17, NumExtensions: 0, NumServices: 1, }, diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index bcad8d7b312b1..8517f4d08c5b6 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -64,17 +64,26 @@ message Log { string output = 2; } +message GoogleInstanceIdentityAuth { + string instance_id = 1; +} + +// Agent represents a running agent on the workspace. +message Agent { + map env = 3; + string startup_script = 4; + oneof auth { + string token = 5; + // https://cloud.google.com/compute/docs/instances/verifying-instance-identity + GoogleInstanceIdentityAuth google_instance_identity = 6; + } +} + // Resource represents created infrastructure. message Resource { string name = 1; string type = 2; - // An optional identifier used for automating Workspace Agent authentication. - // Each cloud has it's own unique instance identity signatures, which can be - // used for zero-token authentication. See: - // GCP: https://cloud.google.com/compute/docs/instances/verifying-instance-identity - // AWS: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html - // Azure: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux#get-attested-data - string instance_id = 3; + Agent agent = 3; } // Parse consumes source-code from a directory to produce inputs. @@ -99,11 +108,11 @@ message Provision { string directory = 1; repeated ParameterValue parameter_values = 2; bytes state = 3; - bool dry_run = 4; } message Complete { bytes state = 1; repeated Resource resources = 2; + repeated Agent agents = 3; } message Response { oneof type { From 773e38f02582be1fbf46a839fcb82dcae6b591fb Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 25 Feb 2022 20:41:56 +0000 Subject: [PATCH 03/10] Rename post files to upload --- coderd/coderd.go | 4 +- coderd/downloads.go | 5 -- coderd/files.go | 2 +- coderd/files_test.go | 2 +- codersdk/files.go | 2 +- provisioner/terraform/provider/provider.go | 49 ++++++++++++++++--- .../terraform/provider/provider_test.go | 20 +++++--- provisionersdk/agent.go | 20 +++----- 8 files changed, 68 insertions(+), 36 deletions(-) delete mode 100644 coderd/downloads.go diff --git a/coderd/coderd.go b/coderd/coderd.go index ab9f207fe1e15..4de6135890f11 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -116,9 +116,9 @@ func New(options *Options) (http.Handler, func()) { }) }) - r.Route("/files", func(r chi.Router) { + r.Route("/upload", func(r chi.Router) { r.Use(httpmw.ExtractAPIKey(options.Database, nil)) - r.Post("/", api.postFiles) + r.Post("/", api.postUpload) }) r.Route("/projectimport/{organization}", func(r chi.Router) { diff --git a/coderd/downloads.go b/coderd/downloads.go deleted file mode 100644 index 621347e8b7ff5..0000000000000 --- a/coderd/downloads.go +++ /dev/null @@ -1,5 +0,0 @@ -package coderd - -func downloads() { - -} diff --git a/coderd/files.go b/coderd/files.go index 069509c567ca6..e25ccd8d749b0 100644 --- a/coderd/files.go +++ b/coderd/files.go @@ -18,7 +18,7 @@ type UploadFileResponse struct { Hash string `json:"hash"` } -func (api *api) postFiles(rw http.ResponseWriter, r *http.Request) { +func (api *api) postUpload(rw http.ResponseWriter, r *http.Request) { apiKey := httpmw.APIKey(r) contentType := r.Header.Get("Content-Type") diff --git a/coderd/files_test.go b/coderd/files_test.go index 77f4085832771..ad00a6c5b656e 100644 --- a/coderd/files_test.go +++ b/coderd/files_test.go @@ -10,7 +10,7 @@ import ( "github.com/coder/coder/codersdk" ) -func TestPostFiles(t *testing.T) { +func TestPostUpload(t *testing.T) { t.Parallel() t.Run("BadContentType", func(t *testing.T) { t.Parallel() diff --git a/codersdk/files.go b/codersdk/files.go index efd25adae27d7..c7eb642f76b68 100644 --- a/codersdk/files.go +++ b/codersdk/files.go @@ -15,7 +15,7 @@ const ( ) func (c *Client) UploadFile(ctx context.Context, contentType string, content []byte) (coderd.UploadFileResponse, error) { - res, err := c.request(ctx, http.MethodPost, "/api/v2/files", content, func(r *http.Request) { + res, err := c.request(ctx, http.MethodPost, "/api/v2/upload", content, func(r *http.Request) { r.Header.Set("Content-Type", contentType) }) if err != nil { diff --git a/provisioner/terraform/provider/provider.go b/provisioner/terraform/provider/provider.go index 8972a4158aaca..22ee99374a797 100644 --- a/provisioner/terraform/provider/provider.go +++ b/provisioner/terraform/provider/provider.go @@ -3,39 +3,74 @@ package provider import ( "context" "fmt" + "net/url" + "os" + "strings" + "github.com/coder/coder/provisionersdk" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) -// New returns a new schema provider for Terraform. +type config struct { + URL *url.URL +} + +// New returns a new Terraform provider. func New() *schema.Provider { return &schema.Provider{ Schema: map[string]*schema.Schema{ - "workspace_history_id": { + "url": { Type: schema.TypeString, Optional: true, + // The "CODER_URL" environment variable is used by default + // as the Access URL when generating scripts. + DefaultFunc: func() (interface{}, error) { + return os.Getenv("CODER_URL"), nil + }, + ValidateFunc: func(i interface{}, s string) ([]string, []error) { + _, err := url.Parse(s) + if err != nil { + return nil, []error{err} + } + return nil, nil + }, }, }, + ConfigureContextFunc: func(c context.Context, rd *schema.ResourceData) (interface{}, diag.Diagnostics) { + rawURL := rd.Get("url").(string) + if rawURL == "" { + return nil, diag.Errorf("CODER_URL must not be empty; got %q", rawURL) + } + parsed, err := url.Parse(rd.Get("url").(string)) + if err != nil { + return nil, diag.FromErr(err) + } + return config{ + URL: parsed, + }, nil + }, DataSourcesMap: map[string]*schema.Resource{ "coder_agent_script": { Description: "TODO", ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + config := i.(config) osRaw := rd.Get("os") os := osRaw.(string) - archRaw := rd.Get("arch") arch := archRaw.(string) - fmt.Printf("Got OS: %s_%s\n", os, arch) - - err := rd.Set("value", "SOME SCRIPT") + script, err := provisionersdk.AgentScript(os, arch, config.URL) + if err != nil { + return diag.FromErr(err) + } + err = rd.Set("value", script) if err != nil { return diag.FromErr(err) } - rd.SetId("something") + rd.SetId(strings.Join([]string{os, arch}, "_")) return nil }, Schema: map[string]*schema.Schema{ diff --git a/provisioner/terraform/provider/provider_test.go b/provisioner/terraform/provider/provider_test.go index 4a59b9fcb2705..bdaa10f43a623 100644 --- a/provisioner/terraform/provider/provider_test.go +++ b/provisioner/terraform/provider/provider_test.go @@ -1,7 +1,6 @@ package provider_test import ( - "encoding/json" "fmt" "testing" @@ -27,8 +26,12 @@ func TestSomething(t *testing.T) { }, IsUnitTest: true, Steps: []resource.TestStep{{ - Config: `data "coder_agent_script" "new" { - arch = "x64" + Config: ` + provider "coder" { + url = "https://example.com" + } + data "coder_agent_script" "new" { + arch = "amd64" os = "linux" }`, Check: func(s *terraform.State) error { @@ -46,7 +49,12 @@ func TestAnother(t *testing.T) { }, IsUnitTest: true, Steps: []resource.TestStep{{ - Config: `resource "coder_agent" "new" { + Config: ` + provider "coder" { + url = "https://example.com" + } + + resource "coder_agent" "new" { auth { type = "gcp" } @@ -59,8 +67,8 @@ func TestAnother(t *testing.T) { // for _, mod := range s.Modules { // fmt.Printf("check state: %+v\n", mod.Resources) // } - data, _ := json.MarshalIndent(s, "", "\t") - fmt.Printf("Data: %s\n", data) + // data, _ := json.MarshalIndent(s, "", "\t") + // fmt.Printf("Data: %s\n", data) return nil }, diff --git a/provisionersdk/agent.go b/provisionersdk/agent.go index 86c26856c3d2a..e78ef67bdc594 100644 --- a/provisionersdk/agent.go +++ b/provisionersdk/agent.go @@ -43,35 +43,29 @@ exec $BINARY_LOCATION agent } ) -// AgentBinaryName returns the binary name for an operating system and agent. -func AgentBinaryName(operatingSystem, architecture string) (string, error) { - -} +// CODER_URL, operating system, and architecture can return the URL of the Coder binary. // AgentScript returns an installation script for the specified operating system // and architecture. // // baseURL is -func AgentScript(operatingSystem, architecture string, baseURL *url.URL) (string, error) { - architectures, ok := agentScript[operatingSystem] - if !ok { +func AgentScript(operatingSystem, architecture string, binaryDownloadURL *url.URL) (string, error) { + architectures, exists := agentScript[operatingSystem] + if !exists { list := []string{} for key := range agentScript { list = append(list, key) } return "", xerrors.Errorf("operating system %q not supported. must be in: %v", operatingSystem, list) } - script, ok := architectures[architecture] - if !ok { + script, exists := architectures[architecture] + if !exists { list := []string{} for key := range architectures { list = append(list, key) } return "", xerrors.Errorf("architecture %q not supported for %q. must be in: %v", architecture, operatingSystem, list) } - if !strings.HasPrefix(baseURL.Path, "/api/v2/downloads") { - - } - return strings.ReplaceAll(script, "${DOWNLOAD_URL}", baseURL.String()), nil + return strings.ReplaceAll(script, "${DOWNLOAD_URL}", binaryDownloadURL.String()), nil } From 89ca1d7723be9c20197c377c66f0418dcdd76b9c Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 26 Feb 2022 17:43:26 +0000 Subject: [PATCH 04/10] Add tests for resources --- Makefile | 4 +- coderd/provisionerdaemons.go | 8 +- coderd/workspaceagent_test.go | 5 +- provisioner/terraform/provider/provider.go | 16 +--- .../terraform/provider/provider_test.go | 48 +++++++---- provisioner/terraform/provision.go | 13 +-- provisionersdk/agent.go | 14 ++-- provisionersdk/agent_test.go | 16 +++- provisionersdk/proto/provisioner.pb.go | 83 ++++++++++--------- provisionersdk/proto/provisioner.proto | 1 + 10 files changed, 111 insertions(+), 97 deletions(-) diff --git a/Makefile b/Makefile index ba0fc488443ed..f3e1bfc8b0317 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ INSTALL_DIR=$(shell go env GOPATH)/bin +GOOS=$(shell go env GOOS) +GOARCH=$(shell go env GOARCH) bin/coder: mkdir -p bin - go build -o bin/coder cmd/coder/main.go + GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o bin/coder-$(GOOS)-$(GOARCH) cmd/coder/main.go .PHONY: bin/coder bin/coderd: diff --git a/coderd/provisionerdaemons.go b/coderd/provisionerdaemons.go index 9f45ff2d6027a..72f2761eb5ea4 100644 --- a/coderd/provisionerdaemons.go +++ b/coderd/provisionerdaemons.go @@ -520,12 +520,8 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr ID: uuid.New(), CreatedAt: database.Now(), WorkspaceHistoryID: input.WorkspaceHistoryID, - InstanceID: sql.NullString{ - Valid: protoResource.InstanceId != "", - String: protoResource.InstanceId, - }, - Type: protoResource.Type, - Name: protoResource.Name, + Type: protoResource.Type, + Name: protoResource.Name, // TODO: Generate this at the variable validation phase. // Set the value in `default_source`, and disallow overwrite. WorkspaceAgentToken: uuid.NewString(), diff --git a/coderd/workspaceagent_test.go b/coderd/workspaceagent_test.go index 86487c4c90275..abdcb8b149816 100644 --- a/coderd/workspaceagent_test.go +++ b/coderd/workspaceagent_test.go @@ -74,9 +74,8 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) { Type: &proto.Provision_Response_Complete{ Complete: &proto.Provision_Complete{ Resources: []*proto.Resource{{ - Name: "somename", - Type: "someinstance", - InstanceId: instanceID, + Name: "somename", + Type: "someinstance", }}, }, }, diff --git a/provisioner/terraform/provider/provider.go b/provisioner/terraform/provider/provider.go index 22ee99374a797..8c2b3515f646f 100644 --- a/provisioner/terraform/provider/provider.go +++ b/provisioner/terraform/provider/provider.go @@ -2,16 +2,16 @@ package provider import ( "context" - "fmt" "net/url" "os" "strings" - "github.com/coder/coder/provisionersdk" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/coder/coder/provisionersdk" ) type config struct { @@ -62,7 +62,7 @@ func New() *schema.Provider { archRaw := rd.Get("arch") arch := archRaw.(string) - script, err := provisionersdk.AgentScript(os, arch, config.URL) + script, err := provisionersdk.AgentScript(config.URL, os, arch) if err != nil { return diag.FromErr(err) } @@ -100,16 +100,6 @@ func New() *schema.Provider { return nil }, ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { - authRaw := rd.Get("auth").([]interface{})[0] - if authRaw != nil { - auth := authRaw.(map[string]interface{}) - fmt.Printf("Auth got %+v\n", auth) - } - - env := rd.Get("env").(map[string]interface{}) - for key, value := range env { - fmt.Printf("Got: %s, %s\n", key, value) - } return nil }, DeleteContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { diff --git a/provisioner/terraform/provider/provider_test.go b/provisioner/terraform/provider/provider_test.go index bdaa10f43a623..5bce83ef6b2f2 100644 --- a/provisioner/terraform/provider/provider_test.go +++ b/provisioner/terraform/provider/provider_test.go @@ -19,7 +19,8 @@ func TestProvider(t *testing.T) { require.NoError(t, err) } -func TestSomething(t *testing.T) { +func TestAgentScript(t *testing.T) { + t.Parallel() resource.Test(t, resource.TestCase{ Providers: map[string]*schema.Provider{ "coder": provider.New(), @@ -34,15 +35,22 @@ func TestSomething(t *testing.T) { arch = "amd64" os = "linux" }`, - Check: func(s *terraform.State) error { - fmt.Printf("check state: %+v\n", s) + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 1) + resource := state.Modules[0].Resources["data.coder_agent_script.new"] + require.NotNil(t, resource) + value := resource.Primary.Attributes["value"] + require.NotNil(t, value) + t.Log(value) return nil }, }}, }) } -func TestAnother(t *testing.T) { +func TestAgent(t *testing.T) { + t.Parallel() resource.Test(t, resource.TestCase{ Providers: map[string]*schema.Provider{ "coder": provider.New(), @@ -53,23 +61,33 @@ func TestAnother(t *testing.T) { provider "coder" { url = "https://example.com" } - resource "coder_agent" "new" { auth { - type = "gcp" + type = "something" + instance_id = "instance" } env = { - test = "some magic value" + hi = "test" } + startup_script = "echo test" }`, - Check: func(s *terraform.State) error { - fmt.Printf("State: %+v\n", s) - // for _, mod := range s.Modules { - // fmt.Printf("check state: %+v\n", mod.Resources) - // } - // data, _ := json.MarshalIndent(s, "", "\t") - // fmt.Printf("Data: %s\n", data) - + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 1) + resource := state.Modules[0].Resources["coder_agent.new"] + require.NotNil(t, resource) + for _, k := range []string{ + "token", + "auth.0.type", + "auth.0.instance_id", + "env.hi", + "startup_script", + } { + v := resource.Primary.Attributes[k] + t.Log(fmt.Sprintf("%q = %q", k, v)) + require.NotNil(t, v) + require.Greater(t, len(v), 0) + } return nil }, }}, diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index cf83fbf700292..3e82f568023b1 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -8,7 +8,6 @@ import ( "io" "os" "path/filepath" - "reflect" "strings" "github.com/hashicorp/terraform-exec/tfexec" @@ -246,17 +245,9 @@ func (t *terraform) runTerraformApply(ctx context.Context, terraform *tfexec.Ter resources := make([]*proto.Resource, 0) if state.Values != nil { for _, resource := range state.Values.RootModule.Resources { - var instanceID string - if gcpInstanceID, ok := resource.AttributeValues["instance_id"]; ok { - instanceID, ok = gcpInstanceID.(string) - if !ok { - return xerrors.Errorf("invalid type for instance_id property: %s", reflect.TypeOf(gcpInstanceID).String()) - } - } resources = append(resources, &proto.Resource{ - Name: resource.Name, - Type: resource.Type, - InstanceId: instanceID, + Name: resource.Name, + Type: resource.Type, }) } } diff --git a/provisionersdk/agent.go b/provisionersdk/agent.go index e78ef67bdc594..7d97dd38ce70a 100644 --- a/provisionersdk/agent.go +++ b/provisionersdk/agent.go @@ -1,6 +1,7 @@ package provisionersdk import ( + "fmt" "net/url" "strings" @@ -43,13 +44,9 @@ exec $BINARY_LOCATION agent } ) -// CODER_URL, operating system, and architecture can return the URL of the Coder binary. - // AgentScript returns an installation script for the specified operating system // and architecture. -// -// baseURL is -func AgentScript(operatingSystem, architecture string, binaryDownloadURL *url.URL) (string, error) { +func AgentScript(coderURL *url.URL, operatingSystem, architecture string) (string, error) { architectures, exists := agentScript[operatingSystem] if !exists { list := []string{} @@ -66,6 +63,9 @@ func AgentScript(operatingSystem, architecture string, binaryDownloadURL *url.UR } return "", xerrors.Errorf("architecture %q not supported for %q. must be in: %v", architecture, operatingSystem, list) } - - return strings.ReplaceAll(script, "${DOWNLOAD_URL}", binaryDownloadURL.String()), nil + parsed, err := coderURL.Parse(fmt.Sprintf("/bin/coder-%s-%s", operatingSystem, architecture)) + if err != nil { + return "", xerrors.Errorf("parse url: %w", err) + } + return strings.ReplaceAll(script, "${DOWNLOAD_URL}", parsed.String()), nil } diff --git a/provisionersdk/agent_test.go b/provisionersdk/agent_test.go index 9e3a0dd23fbcc..b1f77b79ff25f 100644 --- a/provisionersdk/agent_test.go +++ b/provisionersdk/agent_test.go @@ -1,8 +1,15 @@ +//go:build !windows +// +build !windows + +// There isn't a portable Windows binary equivalent to "echo". +// This can be tested, but it's a bit harder. + package provisionersdk_test import ( "net/http" "net/http/httptest" + "net/url" "os" "os/exec" "runtime" @@ -25,8 +32,9 @@ func TestAgentScript(t *testing.T) { render.Data(rw, r, content) })) t.Cleanup(srv.Close) - - script, err := provisionersdk.AgentScript(runtime.GOOS, runtime.GOARCH, srv.URL) + srvURL, err := url.Parse(srv.URL) + require.NoError(t, err) + script, err := provisionersdk.AgentScript(srvURL, runtime.GOOS, runtime.GOARCH) require.NoError(t, err) output, err := exec.Command("sh", "-c", script).CombinedOutput() @@ -39,13 +47,13 @@ func TestAgentScript(t *testing.T) { t.Run("UnsupportedOS", func(t *testing.T) { t.Parallel() - _, err := provisionersdk.AgentScript("unsupported", "", nil) + _, err := provisionersdk.AgentScript(nil, "unsupported", "") require.Error(t, err) }) t.Run("UnsupportedArch", func(t *testing.T) { t.Parallel() - _, err := provisionersdk.AgentScript(runtime.GOOS, "unsupported", nil) + _, err := provisionersdk.AgentScript(nil, runtime.GOOS, "unsupported") require.Error(t, err) }) } diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 5c158fab41bee..8fb2bb5de383f 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1032,6 +1032,7 @@ type Provision_Request struct { Directory string `protobuf:"bytes,1,opt,name=directory,proto3" json:"directory,omitempty"` ParameterValues []*ParameterValue `protobuf:"bytes,2,rep,name=parameter_values,json=parameterValues,proto3" json:"parameter_values,omitempty"` State []byte `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + DryRun bool `protobuf:"varint,4,opt,name=dry_run,json=dryRun,proto3" json:"dry_run,omitempty"` } func (x *Provision_Request) Reset() { @@ -1087,6 +1088,13 @@ func (x *Provision_Request) GetState() []byte { return nil } +func (x *Provision_Request) GetDryRun() bool { + if x != nil { + return x.DryRun + } + return false +} + type Provision_Complete struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1352,8 +1360,8 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x90, 0x03, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x1a, 0x85, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, + 0x79, 0x70, 0x65, 0x22, 0xa9, 0x03, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x1a, 0x9e, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, @@ -1361,41 +1369,42 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x81, 0x01, 0x0a, 0x08, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x77, 0x0a, - 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, - 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, - 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, - 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, - 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, - 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, - 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, + 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, + 0x75, 0x6e, 0x1a, 0x81, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, + 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, + 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, + 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, + 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, + 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, + 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 8517f4d08c5b6..9236c8bc1d582 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -108,6 +108,7 @@ message Provision { string directory = 1; repeated ParameterValue parameter_values = 2; bytes state = 3; + bool dry_run = 4; } message Complete { bytes state = 1; From 29b574033bed821ccec2c07d4fa12662dbc10ce7 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 26 Feb 2022 17:48:05 +0000 Subject: [PATCH 05/10] Skip instance identity test --- coderd/workspaceagent_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/coderd/workspaceagent_test.go b/coderd/workspaceagent_test.go index abdcb8b149816..857b650ecc233 100644 --- a/coderd/workspaceagent_test.go +++ b/coderd/workspaceagent_test.go @@ -29,6 +29,8 @@ import ( ) func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) { + t.Skip("Will be fixed once the Terraform Provider is implemented!") + t.Parallel() t.Run("Expired", func(t *testing.T) { t.Parallel() From 604e9958a53c2f3f89e9eca99c13cf66ac04fb37 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 26 Feb 2022 19:58:53 +0000 Subject: [PATCH 06/10] Add tests for ensuring agent get's passed through properly --- provisioner/terraform/provider/provider.go | 10 +- .../terraform/provider/provider_test.go | 102 ++++++---- provisioner/terraform/provision.go | 183 +++++++++++++++--- provisioner/terraform/provision_test.go | 171 ++++++++++++++++ provisionersdk/proto/provisioner.pb.go | 125 ++++++------ provisionersdk/proto/provisioner.proto | 10 +- 6 files changed, 466 insertions(+), 135 deletions(-) diff --git a/provisioner/terraform/provider/provider.go b/provisioner/terraform/provider/provider.go index 8c2b3515f646f..74e80559f4e47 100644 --- a/provisioner/terraform/provider/provider.go +++ b/provisioner/terraform/provider/provider.go @@ -115,11 +115,14 @@ func New() *schema.Provider { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "type": { - Description: "TODO", - Optional: true, - Type: schema.TypeString, + ForceNew: true, + Description: "TODO", + Optional: true, + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"google-instance-identity"}, false), }, "instance_id": { + ForceNew: true, Description: "TODO", Optional: true, Type: schema.TypeString, @@ -140,6 +143,7 @@ func New() *schema.Provider { Optional: true, }, "token": { + ForceNew: true, Type: schema.TypeString, Computed: true, }, diff --git a/provisioner/terraform/provider/provider_test.go b/provisioner/terraform/provider/provider_test.go index 5bce83ef6b2f2..628b066d84854 100644 --- a/provisioner/terraform/provider/provider_test.go +++ b/provisioner/terraform/provider/provider_test.go @@ -51,45 +51,71 @@ func TestAgentScript(t *testing.T) { func TestAgent(t *testing.T) { t.Parallel() - resource.Test(t, resource.TestCase{ - Providers: map[string]*schema.Provider{ - "coder": provider.New(), - }, - IsUnitTest: true, - Steps: []resource.TestStep{{ - Config: ` - provider "coder" { - url = "https://example.com" - } - resource "coder_agent" "new" { - auth { - type = "something" - instance_id = "instance" - } - env = { - hi = "test" - } - startup_script = "echo test" - }`, - Check: func(state *terraform.State) error { - require.Len(t, state.Modules, 1) - require.Len(t, state.Modules[0].Resources, 1) - resource := state.Modules[0].Resources["coder_agent.new"] - require.NotNil(t, resource) - for _, k := range []string{ - "token", - "auth.0.type", - "auth.0.instance_id", - "env.hi", - "startup_script", - } { - v := resource.Primary.Attributes[k] - t.Log(fmt.Sprintf("%q = %q", k, v)) - require.NotNil(t, v) - require.Greater(t, len(v), 0) + t.Run("Empty", func(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" { + url = "https://example.com" } - return nil + resource "coder_agent" "new" {}`, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 1) + resource := state.Modules[0].Resources["coder_agent.new"] + require.NotNil(t, resource) + require.NotNil(t, resource.Primary.Attributes["token"]) + return nil + }, + }}, + }) + }) + + t.Run("Filled", func(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), }, - }}, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" { + url = "https://example.com" + } + resource "coder_agent" "new" { + auth { + type = "google-instance-identity" + instance_id = "instance" + } + env = { + hi = "test" + } + startup_script = "echo test" + }`, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 1) + resource := state.Modules[0].Resources["coder_agent.new"] + require.NotNil(t, resource) + for _, k := range []string{ + "token", + "auth.0.type", + "auth.0.instance_id", + "env.hi", + "startup_script", + } { + v := resource.Primary.Attributes[k] + t.Log(fmt.Sprintf("%q = %q", k, v)) + require.NotNil(t, v) + require.Greater(t, len(v), 0) + } + return nil + }, + }}, + }) }) } diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index 3e82f568023b1..64cccd25d2c08 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -10,7 +10,9 @@ import ( "path/filepath" "strings" + "cdr.dev/slog" "github.com/hashicorp/terraform-exec/tfexec" + "github.com/mitchellh/mapstructure" "golang.org/x/xerrors" "github.com/coder/coder/provisionersdk/proto" @@ -71,7 +73,8 @@ func (t *terraform) Provision(request *proto.Provision_Request, stream proto.DRP func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terraform, request *proto.Provision_Request, stream proto.DRPCProvisioner_ProvisionStream) error { env := map[string]string{} - options := []tfexec.PlanOption{tfexec.JSON(true)} + planfilePath := filepath.Join(request.Directory, "terraform.tfplan") + options := []tfexec.PlanOption{tfexec.JSON(true), tfexec.Out(planfilePath)} for _, param := range request.ParameterValues { switch param.DestinationScheme { case proto.ParameterDestination_ENVIRONMENT_VARIABLE: @@ -87,7 +90,6 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr return xerrors.Errorf("apply environment variables: %w", err) } - resources := make([]*proto.Resource, 0) reader, writer := io.Pipe() defer reader.Close() defer writer.Close() @@ -116,13 +118,6 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr }, }) - if log.Change != nil && log.Change.Action == "create" { - resources = append(resources, &proto.Resource{ - Name: log.Change.Resource.ResourceName, - Type: log.Change.Resource.ResourceType, - }) - } - if log.Diagnostic == nil { continue } @@ -147,12 +142,88 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr t.logger.Debug(ctx, "running plan") _, err = terraform.Plan(ctx, options...) if err != nil { - return xerrors.Errorf("apply terraform: %w", err) + return xerrors.Errorf("plan terraform: %w", err) } - _ = reader.Close() t.logger.Debug(ctx, "ran plan") + + plan, err := terraform.ShowPlanFile(ctx, planfilePath) + if err != nil { + return xerrors.Errorf("show terraform plan file: %w", err) + } + _ = reader.Close() <-closeChan + resources := make([]*proto.Resource, 0) + agents := map[string]*proto.Agent{} + agentDepends := map[string][]string{} + + // Store all agents inside the maps! + for _, resource := range plan.Config.RootModule.Resources { + if resource.Type != "coder_agent" { + continue + } + agent := &proto.Agent{ + Auth: &proto.Agent_Token{}, + } + if env, has := resource.Expressions["env"]; has { + agent.Env = env.ConstantValue.(map[string]string) + } + if startupScript, has := resource.Expressions["startup_script"]; has { + agent.StartupScript = startupScript.ConstantValue.(string) + } + if auth, has := resource.Expressions["auth"]; has { + if len(auth.ExpressionData.NestedBlocks) > 0 { + block := auth.ExpressionData.NestedBlocks[0] + authType, has := block["type"] + if has { + switch authType.ConstantValue.(string) { + case "google-instance-identity": + agent.Auth = &proto.Agent_GoogleInstanceIdentity{ + GoogleInstanceIdentity: &proto.GoogleInstanceIdentityAuth{ + InstanceId: block["instance_id"].ConstantValue.(string), + }, + } + } + } + } + } + + resourceKey := strings.Join([]string{resource.Type, resource.Name}, ".") + agents[resourceKey] = agent + agentDepends[resourceKey] = resource.DependsOn + } + + for _, resource := range plan.Config.RootModule.Resources { + if resource.Type == "coder_agent" { + continue + } + var agent *proto.Agent + // Associate resources that depend on an agent. + for _, dep := range resource.DependsOn { + var has bool + agent, has = agents[dep] + if has { + break + } + } + // Associate resources where the agent depends on it. + for agentKey, dependsOn := range agentDepends { + for _, depend := range dependsOn { + if depend != strings.Join([]string{resource.Type, resource.Name}, ".") { + continue + } + agent = agents[agentKey] + break + } + } + + resources = append(resources, &proto.Resource{ + Name: resource.Name, + Type: resource.Type, + Agent: agent, + }) + } + return stream.Send(&proto.Provision_Response{ Type: &proto.Provision_Response_Complete{ Complete: &proto.Provision_Complete{ @@ -227,7 +298,7 @@ func (t *terraform) runTerraformApply(ctx context.Context, terraform *tfexec.Ter }() terraform.SetStdout(writer) - t.logger.Debug(ctx, "running apply") + t.logger.Debug(ctx, "running apply", slog.F("options", options)) err = terraform.Apply(ctx, options...) if err != nil { return xerrors.Errorf("apply terraform: %w", err) @@ -244,10 +315,83 @@ func (t *terraform) runTerraformApply(ctx context.Context, terraform *tfexec.Ter } resources := make([]*proto.Resource, 0) if state.Values != nil { + type agentAttributes struct { + ID string `mapstructure:"id"` + Token string `mapstructure:"token"` + Auth []struct { + Type string `mapstructure:"type"` + InstanceID string `mapstructure:"instance_id"` + } `mapstructure:"auth"` + Env map[string]string `mapstructure:"env"` + StartupScript string `mapstructure:"startup_script"` + } + agents := map[string]*proto.Agent{} + agentDepends := map[string][]string{} + + // Store all agents inside the maps! + for _, resource := range state.Values.RootModule.Resources { + if resource.Type != "coder_agent" { + continue + } + var attrs agentAttributes + err = mapstructure.Decode(resource.AttributeValues, &attrs) + if err != nil { + return xerrors.Errorf("decode agent attributes: %w", err) + } + agent := &proto.Agent{ + Id: attrs.ID, + Env: attrs.Env, + StartupScript: attrs.StartupScript, + Auth: &proto.Agent_Token{ + Token: attrs.Token, + }, + } + if len(attrs.Auth) > 0 { + auth := attrs.Auth[0] + switch auth.Type { + case "google-instance-identity": + agent.Auth = &proto.Agent_GoogleInstanceIdentity{ + GoogleInstanceIdentity: &proto.GoogleInstanceIdentityAuth{ + InstanceId: auth.InstanceID, + }, + } + default: + return xerrors.Errorf("unknown auth type: %q", auth.Type) + } + } + resourceKey := strings.Join([]string{resource.Type, resource.Name}, ".") + agents[resourceKey] = agent + agentDepends[resourceKey] = resource.DependsOn + } + for _, resource := range state.Values.RootModule.Resources { + if resource.Type == "coder_agent" { + continue + } + var agent *proto.Agent + // Associate resources that depend on an agent. + for _, dep := range resource.DependsOn { + var has bool + agent, has = agents[dep] + if has { + break + } + } + // Associate resources where the agent depends on it. + for agentKey, dependsOn := range agentDepends { + for _, depend := range dependsOn { + if depend != strings.Join([]string{resource.Type, resource.Name}, ".") { + continue + } + agent = agents[agentKey] + break + } + } + resources = append(resources, &proto.Resource{ - Name: resource.Name, - Type: resource.Type, + Name: resource.Name, + Type: resource.Type, + Agent: agent, }) } } @@ -267,17 +411,6 @@ type terraformProvisionLog struct { Message string `json:"@message"` Diagnostic *terraformProvisionLogDiagnostic `json:"diagnostic"` - Change *terraformProvisionLogChange `json:"change"` -} - -type terraformProvisionLogChange struct { - Action string `json:"action"` - Resource *terraformProvisionLogResource `json:"resource"` -} - -type terraformProvisionLogResource struct { - ResourceType string `json:"resource_type"` - ResourceName string `json:"resource_name"` } type terraformProvisionLogDiagnostic struct { diff --git a/provisioner/terraform/provision_test.go b/provisioner/terraform/provision_test.go index 90174aea84535..aa59be9727418 100644 --- a/provisioner/terraform/provision_test.go +++ b/provisioner/terraform/provision_test.go @@ -5,10 +5,15 @@ package terraform_test import ( "context" "encoding/json" + "fmt" "os" + "os/exec" "path/filepath" + "runtime" "testing" + "cdr.dev/slog" + "cdr.dev/slog/sloggers/slogtest" "github.com/stretchr/testify/require" "github.com/coder/coder/provisioner/terraform" @@ -19,6 +24,36 @@ import ( func TestProvision(t *testing.T) { t.Parallel() + // Build and output the Terraform Provider that is consumed for these tests. + homeDir, err := os.UserHomeDir() + require.NoError(t, err) + providerDest := filepath.Join(homeDir, ".terraform.d", "plugins", "coder.com", "internal", "coder", "0.0.1", fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)) + err = os.MkdirAll(providerDest, 0700) + require.NoError(t, err) + _, filename, _, _ := runtime.Caller(0) + providerSrc := filepath.Join(filepath.Dir(filename), "..", "..", "cmd", "terraform-provider-coder") + output, err := exec.Command("go", "build", "-o", providerDest, providerSrc).CombinedOutput() + if err != nil { + t.Log(string(output)) + } + require.NoError(t, err) + + provider := ` +terraform { + required_providers { + coder = { + source = "coder.com/internal/coder" + version = "0.0.1" + } + } +} + +provider "coder" { + url = "https://example.com" +} + ` + t.Log(provider) + client, server := provisionersdk.TransportPipe() ctx, cancelFunc := context.WithCancel(context.Background()) t.Cleanup(func() { @@ -31,6 +66,7 @@ func TestProvision(t *testing.T) { ServeOptions: &provisionersdk.ServeOptions{ Listener: server, }, + Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug), }) require.NoError(t, err) }() @@ -125,6 +161,127 @@ func TestProvision(t *testing.T) { }, }, }, + }, { + Name: "resource-associated-with-agent", + Files: map[string]string{ + "main.tf": provider + ` + resource "coder_agent" "A" {} + resource "null_resource" "A" { + depends_on = [ + coder_agent.A + ] + }`, + }, + Response: &proto.Provision_Response{ + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + Agent: &proto.Agent{ + Auth: &proto.Agent_Token{ + Token: "", + }, + }, + }}, + }, + }, + }, + }, { + Name: "agent-associated-with-resource", + Files: map[string]string{ + "main.tf": provider + ` + resource "coder_agent" "A" { + depends_on = [ + null_resource.A + ] + auth { + type = "google-instance-identity" + instance_id = "an-instance" + } + } + resource "null_resource" "A" {}`, + }, + Response: &proto.Provision_Response{ + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + Agent: &proto.Agent{ + Auth: &proto.Agent_GoogleInstanceIdentity{ + GoogleInstanceIdentity: &proto.GoogleInstanceIdentityAuth{ + InstanceId: "an-instance", + }, + }, + }, + }}, + }, + }, + }, + }, { + Name: "dryrun-resource-associated-with-agent", + Files: map[string]string{ + "main.tf": provider + ` + resource "coder_agent" "A" { + } + resource "null_resource" "A" { + depends_on = [ + coder_agent.A + ] + }`, + }, + Request: &proto.Provision_Request{ + DryRun: true, + }, + Response: &proto.Provision_Response{ + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + Agent: &proto.Agent{ + Auth: &proto.Agent_Token{}, + }, + }}, + }, + }, + }, + }, { + Name: "dryrun-agent-associated-with-resource", + Files: map[string]string{ + "main.tf": provider + ` + resource "coder_agent" "A" { + depends_on = [ + null_resource.A + ] + auth { + type = "google-instance-identity" + instance_id = "an-instance" + } + } + resource "null_resource" "A" {}`, + }, + Request: &proto.Provision_Request{ + DryRun: true, + }, + Response: &proto.Provision_Response{ + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + Agent: &proto.Agent{ + Auth: &proto.Agent_GoogleInstanceIdentity{ + GoogleInstanceIdentity: &proto.GoogleInstanceIdentityAuth{ + InstanceId: "an-instance", + }, + }, + }, + }}, + }, + }, + }, }} { testCase := testCase t.Run(testCase.Name, func(t *testing.T) { @@ -167,6 +324,20 @@ func TestProvision(t *testing.T) { require.Greater(t, len(msg.GetComplete().State), 0) } + // Remove randomly generated data. + for _, resource := range msg.GetComplete().Resources { + if resource.Agent == nil { + continue + } + resource.Agent.Id = "" + if resource.Agent.GetToken() == "" { + continue + } + resource.Agent.Auth = &proto.Agent_Token{ + Token: "", + } + } + resourcesGot, err := json.Marshal(msg.GetComplete().Resources) require.NoError(t, err) diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 8fb2bb5de383f..f468713d2adde 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -616,8 +616,9 @@ type Agent struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Env map[string]string `protobuf:"bytes,3,rep,name=env,proto3" json:"env,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - StartupScript string `protobuf:"bytes,4,opt,name=startup_script,json=startupScript,proto3" json:"startup_script,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Env map[string]string `protobuf:"bytes,2,rep,name=env,proto3" json:"env,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + StartupScript string `protobuf:"bytes,3,opt,name=startup_script,json=startupScript,proto3" json:"startup_script,omitempty"` // Types that are assignable to Auth: // *Agent_Token // *Agent_GoogleInstanceIdentity @@ -656,6 +657,13 @@ func (*Agent) Descriptor() ([]byte, []int) { return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6} } +func (x *Agent) GetId() string { + if x != nil { + return x.Id + } + return "" +} + func (x *Agent) GetEnv() map[string]string { if x != nil { return x.Env @@ -696,12 +704,12 @@ type isAgent_Auth interface { } type Agent_Token struct { - Token string `protobuf:"bytes,5,opt,name=token,proto3,oneof"` + Token string `protobuf:"bytes,4,opt,name=token,proto3,oneof"` } type Agent_GoogleInstanceIdentity struct { // https://cloud.google.com/compute/docs/instances/verifying-instance-identity - GoogleInstanceIdentity *GoogleInstanceIdentityAuth `protobuf:"bytes,6,opt,name=google_instance_identity,json=googleInstanceIdentity,proto3,oneof"` + GoogleInstanceIdentity *GoogleInstanceIdentityAuth `protobuf:"bytes,5,opt,name=google_instance_identity,json=googleInstanceIdentity,proto3,oneof"` } func (*Agent_Token) isAgent_Auth() {} @@ -1102,7 +1110,6 @@ type Provision_Complete struct { State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` - Agents []*Agent `protobuf:"bytes,3,rep,name=agents,proto3" json:"agents,omitempty"` } func (x *Provision_Complete) Reset() { @@ -1151,13 +1158,6 @@ func (x *Provision_Complete) GetResources() []*Resource { return nil } -func (x *Provision_Complete) GetAgents() []*Agent { - if x != nil { - return x.Agents - } - return nil -} - type Provision_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1320,16 +1320,17 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x6f, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x9a, 0x02, 0x0a, 0x05, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0xaa, 0x02, 0x0a, 0x05, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, + 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x63, 0x0a, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x16, @@ -1360,7 +1361,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0xa9, 0x03, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x79, 0x70, 0x65, 0x22, 0xfc, 0x02, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x9e, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x70, @@ -1371,40 +1372,37 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, - 0x75, 0x6e, 0x1a, 0x81, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, - 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, - 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, - 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, - 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, - 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, - 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, - 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x6e, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, + 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, + 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, + 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, + 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x04, 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1460,18 +1458,17 @@ var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ 16, // 12: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete 6, // 13: provisioner.Provision.Request.parameter_values:type_name -> provisioner.ParameterValue 11, // 14: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource - 10, // 15: provisioner.Provision.Complete.agents:type_name -> provisioner.Agent - 8, // 16: provisioner.Provision.Response.log:type_name -> provisioner.Log - 19, // 17: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete - 15, // 18: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request - 18, // 19: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request - 17, // 20: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response - 20, // 21: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response - 20, // [20:22] is the sub-list for method output_type - 18, // [18:20] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 8, // 15: provisioner.Provision.Response.log:type_name -> provisioner.Log + 19, // 16: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete + 15, // 17: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request + 18, // 18: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request + 17, // 19: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response + 20, // 20: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response + 19, // [19:21] is the sub-list for method output_type + 17, // [17:19] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_provisionersdk_proto_provisioner_proto_init() } diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 9236c8bc1d582..f77d147c0e291 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -70,12 +70,13 @@ message GoogleInstanceIdentityAuth { // Agent represents a running agent on the workspace. message Agent { - map env = 3; - string startup_script = 4; + string id = 1; + map env = 2; + string startup_script = 3; oneof auth { - string token = 5; + string token = 4; // https://cloud.google.com/compute/docs/instances/verifying-instance-identity - GoogleInstanceIdentityAuth google_instance_identity = 6; + GoogleInstanceIdentityAuth google_instance_identity = 5; } } @@ -113,7 +114,6 @@ message Provision { message Complete { bytes state = 1; repeated Resource resources = 2; - repeated Agent agents = 3; } message Response { oneof type { From f8cab499cf28a8384a5004be96738b30702d271f Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 26 Feb 2022 20:20:01 +0000 Subject: [PATCH 07/10] Fix linting errors --- cmd/terraform-provider-coder/main.go | 3 +- provisioner/terraform/provider/provider.go | 41 ++++++++++++------- .../terraform/provider/provider_test.go | 12 +++--- provisioner/terraform/provision.go | 28 ++++++++++--- provisioner/terraform/provision_test.go | 4 +- provisionersdk/agent_test.go | 3 +- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/cmd/terraform-provider-coder/main.go b/cmd/terraform-provider-coder/main.go index 2cff70b9d0172..9102d33e461ef 100644 --- a/cmd/terraform-provider-coder/main.go +++ b/cmd/terraform-provider-coder/main.go @@ -1,8 +1,9 @@ package main import ( - "github.com/coder/coder/provisioner/terraform/provider" "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" + + "github.com/coder/coder/provisioner/terraform/provider" ) func main() { diff --git a/provisioner/terraform/provider/provider.go b/provisioner/terraform/provider/provider.go index 74e80559f4e47..fa0ec83695073 100644 --- a/provisioner/terraform/provider/provider.go +++ b/provisioner/terraform/provider/provider.go @@ -4,6 +4,7 @@ import ( "context" "net/url" "os" + "reflect" "strings" "github.com/google/uuid" @@ -39,12 +40,15 @@ func New() *schema.Provider { }, }, }, - ConfigureContextFunc: func(c context.Context, rd *schema.ResourceData) (interface{}, diag.Diagnostics) { - rawURL := rd.Get("url").(string) + ConfigureContextFunc: func(c context.Context, resourceData *schema.ResourceData) (interface{}, diag.Diagnostics) { + rawURL, ok := resourceData.Get("url").(string) + if !ok { + return nil, diag.Errorf("unexpected type %q for url", reflect.TypeOf(resourceData.Get("url")).String()) + } if rawURL == "" { return nil, diag.Errorf("CODER_URL must not be empty; got %q", rawURL) } - parsed, err := url.Parse(rd.Get("url").(string)) + parsed, err := url.Parse(resourceData.Get("url").(string)) if err != nil { return nil, diag.FromErr(err) } @@ -55,22 +59,28 @@ func New() *schema.Provider { DataSourcesMap: map[string]*schema.Resource{ "coder_agent_script": { Description: "TODO", - ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { - config := i.(config) - osRaw := rd.Get("os") - os := osRaw.(string) - archRaw := rd.Get("arch") - arch := archRaw.(string) - - script, err := provisionersdk.AgentScript(config.URL, os, arch) + ReadContext: func(c context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + config, valid := i.(config) + if !valid { + return diag.Errorf("config was unexpected type %q", reflect.TypeOf(i).String()) + } + operatingSystem, valid := resourceData.Get("os").(string) + if !valid { + return diag.Errorf("os was unexpected type %q", reflect.TypeOf(resourceData.Get("os"))) + } + arch, valid := resourceData.Get("arch").(string) + if !valid { + return diag.Errorf("arch was unexpected type %q", reflect.TypeOf(resourceData.Get("arch"))) + } + script, err := provisionersdk.AgentScript(config.URL, operatingSystem, arch) if err != nil { return diag.FromErr(err) } - err = rd.Set("value", script) + err = resourceData.Set("value", script) if err != nil { return diag.FromErr(err) } - rd.SetId(strings.Join([]string{os, arch}, "_")) + resourceData.SetId(strings.Join([]string{operatingSystem, arch}, "_")) return nil }, Schema: map[string]*schema.Schema{ @@ -96,7 +106,10 @@ func New() *schema.Provider { CreateContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { // This should be a real authentication token! rd.SetId(uuid.NewString()) - rd.Set("token", uuid.NewString()) + err := rd.Set("token", uuid.NewString()) + if err != nil { + return diag.FromErr(err) + } return nil }, ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { diff --git a/provisioner/terraform/provider/provider_test.go b/provisioner/terraform/provider/provider_test.go index 628b066d84854..39348af351ca0 100644 --- a/provisioner/terraform/provider/provider_test.go +++ b/provisioner/terraform/provider/provider_test.go @@ -52,6 +52,7 @@ func TestAgentScript(t *testing.T) { func TestAgent(t *testing.T) { t.Parallel() t.Run("Empty", func(t *testing.T) { + t.Parallel() resource.Test(t, resource.TestCase{ Providers: map[string]*schema.Provider{ "coder": provider.New(), @@ -76,6 +77,7 @@ func TestAgent(t *testing.T) { }) t.Run("Filled", func(t *testing.T) { + t.Parallel() resource.Test(t, resource.TestCase{ Providers: map[string]*schema.Provider{ "coder": provider.New(), @@ -101,17 +103,17 @@ func TestAgent(t *testing.T) { require.Len(t, state.Modules[0].Resources, 1) resource := state.Modules[0].Resources["coder_agent.new"] require.NotNil(t, resource) - for _, k := range []string{ + for _, key := range []string{ "token", "auth.0.type", "auth.0.instance_id", "env.hi", "startup_script", } { - v := resource.Primary.Attributes[k] - t.Log(fmt.Sprintf("%q = %q", k, v)) - require.NotNil(t, v) - require.Greater(t, len(v), 0) + value := resource.Primary.Attributes[key] + t.Log(fmt.Sprintf("%q = %q", key, value)) + require.NotNil(t, value) + require.Greater(t, len(value), 0) } return nil }, diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index 64cccd25d2c08..a06fae5135bf6 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -8,13 +8,15 @@ import ( "io" "os" "path/filepath" + "reflect" "strings" - "cdr.dev/slog" "github.com/hashicorp/terraform-exec/tfexec" "github.com/mitchellh/mapstructure" "golang.org/x/xerrors" + "cdr.dev/slog" + "github.com/coder/coder/provisionersdk/proto" ) @@ -165,24 +167,38 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr agent := &proto.Agent{ Auth: &proto.Agent_Token{}, } - if env, has := resource.Expressions["env"]; has { - agent.Env = env.ConstantValue.(map[string]string) + if envRaw, has := resource.Expressions["env"]; has { + env, ok := envRaw.ConstantValue.(map[string]string) + if !ok { + return xerrors.Errorf("unexpected type %q for env map", reflect.TypeOf(envRaw.ConstantValue).String()) + } + agent.Env = env } - if startupScript, has := resource.Expressions["startup_script"]; has { - agent.StartupScript = startupScript.ConstantValue.(string) + if startupScriptRaw, has := resource.Expressions["startup_script"]; has { + startupScript, ok := startupScriptRaw.ConstantValue.(string) + if !ok { + return xerrors.Errorf("unexpected type %q for startup script", reflect.TypeOf(startupScriptRaw.ConstantValue).String()) + } + agent.StartupScript = startupScript } if auth, has := resource.Expressions["auth"]; has { if len(auth.ExpressionData.NestedBlocks) > 0 { block := auth.ExpressionData.NestedBlocks[0] authType, has := block["type"] if has { - switch authType.ConstantValue.(string) { + authTypeValue, valid := authType.ConstantValue.(string) + if !valid { + return xerrors.Errorf("unexpected type %q for auth type", reflect.TypeOf(authType.ConstantValue)) + } + switch authTypeValue { case "google-instance-identity": agent.Auth = &proto.Agent_GoogleInstanceIdentity{ GoogleInstanceIdentity: &proto.GoogleInstanceIdentityAuth{ InstanceId: block["instance_id"].ConstantValue.(string), }, } + default: + return xerrors.Errorf("unknown auth type: %q", authTypeValue) } } } diff --git a/provisioner/terraform/provision_test.go b/provisioner/terraform/provision_test.go index aa59be9727418..ca1cc0fb9683d 100644 --- a/provisioner/terraform/provision_test.go +++ b/provisioner/terraform/provision_test.go @@ -12,9 +12,10 @@ import ( "runtime" "testing" + "github.com/stretchr/testify/require" + "cdr.dev/slog" "cdr.dev/slog/sloggers/slogtest" - "github.com/stretchr/testify/require" "github.com/coder/coder/provisioner/terraform" "github.com/coder/coder/provisionersdk" @@ -30,6 +31,7 @@ func TestProvision(t *testing.T) { providerDest := filepath.Join(homeDir, ".terraform.d", "plugins", "coder.com", "internal", "coder", "0.0.1", fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)) err = os.MkdirAll(providerDest, 0700) require.NoError(t, err) + //nolint:dogsled _, filename, _, _ := runtime.Caller(0) providerSrc := filepath.Join(filepath.Dir(filename), "..", "..", "cmd", "terraform-provider-coder") output, err := exec.Command("go", "build", "-o", providerDest, providerSrc).CombinedOutput() diff --git a/provisionersdk/agent_test.go b/provisionersdk/agent_test.go index b1f77b79ff25f..31e93f89ef438 100644 --- a/provisionersdk/agent_test.go +++ b/provisionersdk/agent_test.go @@ -16,9 +16,10 @@ import ( "strings" "testing" - "github.com/coder/coder/provisionersdk" "github.com/go-chi/render" "github.com/stretchr/testify/require" + + "github.com/coder/coder/provisionersdk" ) func TestAgentScript(t *testing.T) { From 444109d82bd89de377bc6307b153878dcd57109d Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 26 Feb 2022 20:56:03 +0000 Subject: [PATCH 08/10] Add echo path --- provisionersdk/agent_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/provisionersdk/agent_test.go b/provisionersdk/agent_test.go index 31e93f89ef438..b5ba3924f619f 100644 --- a/provisionersdk/agent_test.go +++ b/provisionersdk/agent_test.go @@ -27,7 +27,9 @@ func TestAgentScript(t *testing.T) { t.Run("Run", func(t *testing.T) { t.Parallel() srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - content, err := os.ReadFile("/usr/bin/echo") + echoPath, err := exec.LookPath("echo") + require.NoError(t, err) + content, err := os.ReadFile(echoPath) require.NoError(t, err) render.Status(r, http.StatusOK) render.Data(rw, r, content) From 108f1b5f0c8061539f5b46eb32cbdd3c71a064e8 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 26 Feb 2022 21:51:22 +0000 Subject: [PATCH 09/10] Fix agent authentication --- coderd/provisionerdaemons.go | 8 ++++++++ coderd/workspaceagent_test.go | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/coderd/provisionerdaemons.go b/coderd/provisionerdaemons.go index 72f2761eb5ea4..95d212df7a13e 100644 --- a/coderd/provisionerdaemons.go +++ b/coderd/provisionerdaemons.go @@ -516,12 +516,20 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr } // This could be a bulk insert to improve performance. for _, protoResource := range jobType.WorkspaceProvision.Resources { + var instanceID sql.NullString + if protoResource.Agent != nil && protoResource.Agent.GetGoogleInstanceIdentity() != nil { + instanceID = sql.NullString{ + String: protoResource.Agent.GetGoogleInstanceIdentity().InstanceId, + Valid: true, + } + } _, err = db.InsertWorkspaceResource(ctx, database.InsertWorkspaceResourceParams{ ID: uuid.New(), CreatedAt: database.Now(), WorkspaceHistoryID: input.WorkspaceHistoryID, Type: protoResource.Type, Name: protoResource.Name, + InstanceID: instanceID, // TODO: Generate this at the variable validation phase. // Set the value in `default_source`, and disallow overwrite. WorkspaceAgentToken: uuid.NewString(), diff --git a/coderd/workspaceagent_test.go b/coderd/workspaceagent_test.go index 857b650ecc233..c48dfc75af1d1 100644 --- a/coderd/workspaceagent_test.go +++ b/coderd/workspaceagent_test.go @@ -29,8 +29,6 @@ import ( ) func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) { - t.Skip("Will be fixed once the Terraform Provider is implemented!") - t.Parallel() t.Run("Expired", func(t *testing.T) { t.Parallel() @@ -78,6 +76,13 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) { Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", + Agent: &proto.Agent{ + Auth: &proto.Agent_GoogleInstanceIdentity{ + GoogleInstanceIdentity: &proto.GoogleInstanceIdentityAuth{ + InstanceId: instanceID, + }, + }, + }, }}, }, }, From 75946573fbdaa10b27e872af3b078cf49bbc121a Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 28 Feb 2022 10:26:38 -0600 Subject: [PATCH 10/10] Update codersdk/files.go Co-authored-by: Bryan --- codersdk/files.go | 2 +- provisioner/terraform/provider/provider.go | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/codersdk/files.go b/codersdk/files.go index c7eb642f76b68..226391740e4b7 100644 --- a/codersdk/files.go +++ b/codersdk/files.go @@ -29,7 +29,7 @@ func (c *Client) UploadFile(ctx context.Context, contentType string, content []b return resp, json.NewDecoder(res.Body).Decode(&resp) } -// DownloadURL returns +// DownloadURL returns the download URL for the specified asset func (c *Client) DownloadURL(asset string) (*url.URL, error) { return c.URL.Parse(fmt.Sprintf("/api/v2/downloads/%s", asset)) } diff --git a/provisioner/terraform/provider/provider.go b/provisioner/terraform/provider/provider.go index fa0ec83695073..5daa91de54202 100644 --- a/provisioner/terraform/provider/provider.go +++ b/provisioner/terraform/provider/provider.go @@ -3,7 +3,6 @@ package provider import ( "context" "net/url" - "os" "reflect" "strings" @@ -28,9 +27,7 @@ func New() *schema.Provider { Optional: true, // The "CODER_URL" environment variable is used by default // as the Access URL when generating scripts. - DefaultFunc: func() (interface{}, error) { - return os.Getenv("CODER_URL"), nil - }, + DefaultFunc: schema.EnvDefaultFunc("CODER_URL", ""), ValidateFunc: func(i interface{}, s string) ([]string, []error) { _, err := url.Parse(s) if err != nil { @@ -90,8 +87,9 @@ func New() *schema.Provider { ValidateFunc: validation.StringInSlice([]string{"linux", "darwin", "windows"}, false), }, "arch": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"amd64"}, false), }, "value": { Type: schema.TypeString,