From 77757d9f5bca0613324cb842c65b1e45e98b103c Mon Sep 17 00:00:00 2001 From: Alex Pilon Date: Wed, 7 Aug 2019 17:50:59 -0400 Subject: [PATCH] prune references to config/module delete config/module prune references to config except in terraform/resource.go move, cleanup, and delete inert code --- config/module/copy_dir.go | 114 --- config/module/detector_test.go | 112 --- config/module/get.go | 57 -- config/module/inode.go | 21 - config/module/inode_freebsd.go | 21 - config/module/inode_windows.go | 8 - config/module/module.go | 9 - config/module/module_test.go | 48 -- config/module/storage.go | 346 -------- config/module/storage_test.go | 189 ----- config/module/testdata/basic-dot/.test/foo.tf | 1 - config/module/testdata/basic-dot/main.tf | 5 - .../testdata/basic-git/DOTgit/COMMIT_EDITMSG | 7 - config/module/testdata/basic-git/DOTgit/HEAD | 1 - .../module/testdata/basic-git/DOTgit/config | 7 - .../testdata/basic-git/DOTgit/description | 1 - .../DOTgit/hooks/applypatch-msg.sample | 15 - .../basic-git/DOTgit/hooks/commit-msg.sample | 24 - .../basic-git/DOTgit/hooks/post-update.sample | 8 - .../DOTgit/hooks/pre-applypatch.sample | 14 - .../basic-git/DOTgit/hooks/pre-commit.sample | 49 -- .../basic-git/DOTgit/hooks/pre-push.sample | 54 -- .../basic-git/DOTgit/hooks/pre-rebase.sample | 169 ---- .../DOTgit/hooks/prepare-commit-msg.sample | 36 - .../basic-git/DOTgit/hooks/update.sample | 128 --- config/module/testdata/basic-git/DOTgit/index | Bin 184 -> 0 bytes .../testdata/basic-git/DOTgit/info/exclude | 6 - .../testdata/basic-git/DOTgit/logs/HEAD | 7 - .../basic-git/DOTgit/logs/refs/heads/master | 4 - .../DOTgit/logs/refs/heads/test-branch | 2 - .../14/6492b04efe0aae2b8288c5c0aef6a951030fde | Bin 170 -> 0 bytes .../1d/3d6744266642cb7623e2c678c33c77b075c49f | Bin 84 -> 0 bytes .../1f/31e97f053caeb5d6b7bffa3faf82941c99efa2 | Bin 167 -> 0 bytes .../24/3f0fc5c4e586d1a3daa54c981b6f34e9ab1085 | Bin 164 -> 0 bytes .../38/30637158f774a20edcc0bf1c4d07b0bf87c43d | Bin 59 -> 0 bytes .../40/4618c9d96dfa0a5d365b518e0dfbb5a387c649 | Bin 84 -> 0 bytes .../49/7bc37401eb3c9b11865b1768725b64066eccee | 2 - .../7b/7614f8759ac8b5e4b02be65ad8e2667be6dd87 | 2 - .../8c/1a79ca1f98b6d00f5bf5c6cc9e8d3c092dd3ba | Bin 51 -> 0 bytes .../96/43088174e25a9bd91c27970a580af0085c9f32 | Bin 52 -> 0 bytes .../b7/757b6a3696ad036e9aa2f5b4856d09e7f17993 | Bin 82 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../basic-git/DOTgit/refs/heads/master | 1 - .../basic-git/DOTgit/refs/heads/test-branch | 1 - .../testdata/basic-git/DOTgit/refs/tags/v1.0 | 1 - config/module/testdata/basic-git/main.tf | 5 - .../module/testdata/basic-git/subdir/sub.tf | 0 .../testdata/basic-hg/.hg/00changelog.i | Bin 57 -> 0 bytes config/module/testdata/basic-hg/.hg/branch | 1 - .../basic-hg/.hg/cache/branch2-served | 3 - .../module/testdata/basic-hg/.hg/cache/tags | 2 - config/module/testdata/basic-hg/.hg/dirstate | Bin 64 -> 0 bytes .../testdata/basic-hg/.hg/last-message.txt | 2 - config/module/testdata/basic-hg/.hg/requires | 4 - .../testdata/basic-hg/.hg/store/00changelog.i | Bin 355 -> 0 bytes .../testdata/basic-hg/.hg/store/00manifest.i | Bin 246 -> 0 bytes .../basic-hg/.hg/store/data/main.tf.i | Bin 112 -> 0 bytes .../basic-hg/.hg/store/data/main__branch.tf.i | Bin 64 -> 0 bytes .../testdata/basic-hg/.hg/store/fncache | 2 - .../testdata/basic-hg/.hg/store/phaseroots | 1 - .../module/testdata/basic-hg/.hg/store/undo | Bin 59 -> 0 bytes .../basic-hg/.hg/store/undo.phaseroots | 1 - .../testdata/basic-hg/.hg/undo.bookmarks | 0 .../module/testdata/basic-hg/.hg/undo.branch | 1 - config/module/testdata/basic-hg/.hg/undo.desc | 2 - .../testdata/basic-hg/.hg/undo.dirstate | Bin 95 -> 0 bytes config/module/testdata/basic-hg/main.tf | 5 - config/module/testdata/basic-parent/a/a.tf | 3 - config/module/testdata/basic-parent/c/c.tf | 1 - config/module/testdata/basic-parent/main.tf | 3 - .../testdata/basic-subdir/foo/sub/baz/main.tf | 0 .../testdata/basic-subdir/foo/sub/main.tf | 3 - config/module/testdata/basic-subdir/main.tf | 3 - .../module/testdata/basic-tar-subdir/foo.tgz | Bin 236 -> 0 bytes .../module/testdata/basic-tar-subdir/main.tf | 3 - config/module/testdata/basic/foo/main.tf | 1 - config/module/testdata/basic/main.tf | 5 - config/module/testdata/basic/subdir/sub.tf | 0 .../change-intermediate-source/a/b/main.tf | 1 - .../change-intermediate-source/a/main.tf | 3 - .../change-intermediate-source/c/b/main.tf | 1 - .../change-intermediate-source/c/main.tf | 3 - .../change-intermediate-source/main.tf | 3 - .../main.tf.disabled | 3 - config/module/testdata/child/foo/bar/main.tf | 2 - config/module/testdata/child/foo/main.tf | 5 - config/module/testdata/child/main.tf | 5 - .../conficting-submodule-names/a/c/main.tf | 1 - .../conficting-submodule-names/a/main.tf | 3 - .../conficting-submodule-names/b/c/main.tf | 1 - .../conficting-submodule-names/b/main.tf | 3 - .../conficting-submodule-names/main.tf | 7 - .../identifier/provider/main.tf | 3 - .../testdata/discover-registry-local/main.tf | 3 - .../module/testdata/discover-subdirs/main.tf | 3 - .../namespace/identifier/provider/main.tf | 3 - config/module/testdata/dup/foo/main.tf | 0 config/module/testdata/dup/main.tf | 7 - config/module/testdata/registry-load/main.tf | 3 - .../module/testdata/registry-subdir/main.tf | 4 - .../testdata/registry-tar-subdir/foo.tgz | Bin 236 -> 0 bytes .../testdata/registry-tar-subdir/main.tf | 4 - .../testdata/tar-subdir-to-parent/foo.tgz | Bin 235 -> 0 bytes .../testdata/tar-subdir-to-parent/main.tf | 4 - .../testdata/validate-alias-bad/child/main.tf | 3 - .../testdata/validate-alias-bad/main.tf | 3 - .../validate-alias-good/child/main.tf | 3 - .../testdata/validate-alias-good/main.tf | 5 - .../child/main.tf | 1 - .../validate-bad-output-to-module/main.tf | 8 - .../validate-bad-output/child/main.tf | 0 .../testdata/validate-bad-output/main.tf | 7 - .../testdata/validate-bad-var/child/main.tf | 0 .../module/testdata/validate-bad-var/main.tf | 5 - .../testdata/validate-child-bad/child/main.tf | 3 - .../testdata/validate-child-bad/main.tf | 3 - .../validate-child-good/child/main.tf | 3 - .../testdata/validate-child-good/main.tf | 8 - .../child/child/main.tf | 1 - .../child/main.tf | 1 - .../validate-module-root-grandchild/main.tf | 3 - .../validate-module-root/child/main.tf | 1 - .../testdata/validate-module-root/main.tf | 3 - .../testdata/validate-module-unknown/main.tf | 3 - .../validate-required-var/child/main.tf | 2 - .../testdata/validate-required-var/main.tf | 3 - .../module/testdata/validate-root-bad/main.tf | 3 - config/module/testing.go | 36 - config/module/tree.go | 599 ------------- config/module/tree_gob.go | 57 -- config/module/tree_gob_test.go | 38 - config/module/tree_test.go | 675 --------------- config/module/validate_provider_alias.go | 118 --- config/module/versions.go | 129 --- config/module/versions_test.go | 90 -- flatmap/expand.go | 4 +- flatmap/expand_test.go | 6 +- helper/schema/provider.go | 8 +- helper/schema/resource.go | 24 +- terraform/context.go | 67 +- terraform/context_apply_test.go | 41 +- terraform/context_test.go | 10 +- terraform/eval_context_mock.go | 34 +- terraform/eval_count_computed.go | 25 - terraform/eval_variable.go | 89 +- terraform/interpolate.go | 800 ------------------ terraform/node_provisioner.go | 7 - terraform/resource_address.go | 57 +- terraform/resource_address_test.go | 150 ++-- terraform/resource_mode.go | 9 + terraform/resource_mode_string.go | 24 + terraform/state.go | 18 +- terraform/state_test.go | 10 +- terraform/transform_config_old.go | 23 - terraform/transform_reference.go | 39 +- 155 files changed, 203 insertions(+), 4652 deletions(-) delete mode 100644 config/module/copy_dir.go delete mode 100644 config/module/detector_test.go delete mode 100644 config/module/get.go delete mode 100644 config/module/inode.go delete mode 100644 config/module/inode_freebsd.go delete mode 100644 config/module/inode_windows.go delete mode 100644 config/module/module.go delete mode 100644 config/module/module_test.go delete mode 100644 config/module/storage.go delete mode 100644 config/module/storage_test.go delete mode 100644 config/module/testdata/basic-dot/.test/foo.tf delete mode 100644 config/module/testdata/basic-dot/main.tf delete mode 100644 config/module/testdata/basic-git/DOTgit/COMMIT_EDITMSG delete mode 100644 config/module/testdata/basic-git/DOTgit/HEAD delete mode 100644 config/module/testdata/basic-git/DOTgit/config delete mode 100644 config/module/testdata/basic-git/DOTgit/description delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/applypatch-msg.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/commit-msg.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/post-update.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/pre-applypatch.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/pre-commit.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/pre-push.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/pre-rebase.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/prepare-commit-msg.sample delete mode 100755 config/module/testdata/basic-git/DOTgit/hooks/update.sample delete mode 100644 config/module/testdata/basic-git/DOTgit/index delete mode 100644 config/module/testdata/basic-git/DOTgit/info/exclude delete mode 100644 config/module/testdata/basic-git/DOTgit/logs/HEAD delete mode 100644 config/module/testdata/basic-git/DOTgit/logs/refs/heads/master delete mode 100644 config/module/testdata/basic-git/DOTgit/logs/refs/heads/test-branch delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/14/6492b04efe0aae2b8288c5c0aef6a951030fde delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/1d/3d6744266642cb7623e2c678c33c77b075c49f delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/1f/31e97f053caeb5d6b7bffa3faf82941c99efa2 delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/24/3f0fc5c4e586d1a3daa54c981b6f34e9ab1085 delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/38/30637158f774a20edcc0bf1c4d07b0bf87c43d delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/40/4618c9d96dfa0a5d365b518e0dfbb5a387c649 delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/49/7bc37401eb3c9b11865b1768725b64066eccee delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/7b/7614f8759ac8b5e4b02be65ad8e2667be6dd87 delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/8c/1a79ca1f98b6d00f5bf5c6cc9e8d3c092dd3ba delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/96/43088174e25a9bd91c27970a580af0085c9f32 delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/b7/757b6a3696ad036e9aa2f5b4856d09e7f17993 delete mode 100644 config/module/testdata/basic-git/DOTgit/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 config/module/testdata/basic-git/DOTgit/refs/heads/master delete mode 100644 config/module/testdata/basic-git/DOTgit/refs/heads/test-branch delete mode 100644 config/module/testdata/basic-git/DOTgit/refs/tags/v1.0 delete mode 100644 config/module/testdata/basic-git/main.tf delete mode 100644 config/module/testdata/basic-git/subdir/sub.tf delete mode 100644 config/module/testdata/basic-hg/.hg/00changelog.i delete mode 100644 config/module/testdata/basic-hg/.hg/branch delete mode 100644 config/module/testdata/basic-hg/.hg/cache/branch2-served delete mode 100644 config/module/testdata/basic-hg/.hg/cache/tags delete mode 100644 config/module/testdata/basic-hg/.hg/dirstate delete mode 100644 config/module/testdata/basic-hg/.hg/last-message.txt delete mode 100644 config/module/testdata/basic-hg/.hg/requires delete mode 100644 config/module/testdata/basic-hg/.hg/store/00changelog.i delete mode 100644 config/module/testdata/basic-hg/.hg/store/00manifest.i delete mode 100644 config/module/testdata/basic-hg/.hg/store/data/main.tf.i delete mode 100644 config/module/testdata/basic-hg/.hg/store/data/main__branch.tf.i delete mode 100644 config/module/testdata/basic-hg/.hg/store/fncache delete mode 100644 config/module/testdata/basic-hg/.hg/store/phaseroots delete mode 100644 config/module/testdata/basic-hg/.hg/store/undo delete mode 100644 config/module/testdata/basic-hg/.hg/store/undo.phaseroots delete mode 100644 config/module/testdata/basic-hg/.hg/undo.bookmarks delete mode 100644 config/module/testdata/basic-hg/.hg/undo.branch delete mode 100644 config/module/testdata/basic-hg/.hg/undo.desc delete mode 100644 config/module/testdata/basic-hg/.hg/undo.dirstate delete mode 100644 config/module/testdata/basic-hg/main.tf delete mode 100644 config/module/testdata/basic-parent/a/a.tf delete mode 100644 config/module/testdata/basic-parent/c/c.tf delete mode 100644 config/module/testdata/basic-parent/main.tf delete mode 100644 config/module/testdata/basic-subdir/foo/sub/baz/main.tf delete mode 100644 config/module/testdata/basic-subdir/foo/sub/main.tf delete mode 100644 config/module/testdata/basic-subdir/main.tf delete mode 100644 config/module/testdata/basic-tar-subdir/foo.tgz delete mode 100644 config/module/testdata/basic-tar-subdir/main.tf delete mode 100644 config/module/testdata/basic/foo/main.tf delete mode 100644 config/module/testdata/basic/main.tf delete mode 100644 config/module/testdata/basic/subdir/sub.tf delete mode 100644 config/module/testdata/change-intermediate-source/a/b/main.tf delete mode 100644 config/module/testdata/change-intermediate-source/a/main.tf delete mode 100644 config/module/testdata/change-intermediate-source/c/b/main.tf delete mode 100644 config/module/testdata/change-intermediate-source/c/main.tf delete mode 100644 config/module/testdata/change-intermediate-source/main.tf delete mode 100644 config/module/testdata/change-intermediate-source/main.tf.disabled delete mode 100644 config/module/testdata/child/foo/bar/main.tf delete mode 100644 config/module/testdata/child/foo/main.tf delete mode 100644 config/module/testdata/child/main.tf delete mode 100644 config/module/testdata/conficting-submodule-names/a/c/main.tf delete mode 100644 config/module/testdata/conficting-submodule-names/a/main.tf delete mode 100644 config/module/testdata/conficting-submodule-names/b/c/main.tf delete mode 100644 config/module/testdata/conficting-submodule-names/b/main.tf delete mode 100644 config/module/testdata/conficting-submodule-names/main.tf delete mode 100644 config/module/testdata/discover-registry-local/exists-in-registry/identifier/provider/main.tf delete mode 100644 config/module/testdata/discover-registry-local/main.tf delete mode 100644 config/module/testdata/discover-subdirs/main.tf delete mode 100644 config/module/testdata/discover-subdirs/namespace/identifier/provider/main.tf delete mode 100644 config/module/testdata/dup/foo/main.tf delete mode 100644 config/module/testdata/dup/main.tf delete mode 100644 config/module/testdata/registry-load/main.tf delete mode 100644 config/module/testdata/registry-subdir/main.tf delete mode 100644 config/module/testdata/registry-tar-subdir/foo.tgz delete mode 100644 config/module/testdata/registry-tar-subdir/main.tf delete mode 100644 config/module/testdata/tar-subdir-to-parent/foo.tgz delete mode 100644 config/module/testdata/tar-subdir-to-parent/main.tf delete mode 100644 config/module/testdata/validate-alias-bad/child/main.tf delete mode 100644 config/module/testdata/validate-alias-bad/main.tf delete mode 100644 config/module/testdata/validate-alias-good/child/main.tf delete mode 100644 config/module/testdata/validate-alias-good/main.tf delete mode 100644 config/module/testdata/validate-bad-output-to-module/child/main.tf delete mode 100644 config/module/testdata/validate-bad-output-to-module/main.tf delete mode 100644 config/module/testdata/validate-bad-output/child/main.tf delete mode 100644 config/module/testdata/validate-bad-output/main.tf delete mode 100644 config/module/testdata/validate-bad-var/child/main.tf delete mode 100644 config/module/testdata/validate-bad-var/main.tf delete mode 100644 config/module/testdata/validate-child-bad/child/main.tf delete mode 100644 config/module/testdata/validate-child-bad/main.tf delete mode 100644 config/module/testdata/validate-child-good/child/main.tf delete mode 100644 config/module/testdata/validate-child-good/main.tf delete mode 100644 config/module/testdata/validate-module-root-grandchild/child/child/main.tf delete mode 100644 config/module/testdata/validate-module-root-grandchild/child/main.tf delete mode 100644 config/module/testdata/validate-module-root-grandchild/main.tf delete mode 100644 config/module/testdata/validate-module-root/child/main.tf delete mode 100644 config/module/testdata/validate-module-root/main.tf delete mode 100644 config/module/testdata/validate-module-unknown/main.tf delete mode 100644 config/module/testdata/validate-required-var/child/main.tf delete mode 100644 config/module/testdata/validate-required-var/main.tf delete mode 100644 config/module/testdata/validate-root-bad/main.tf delete mode 100644 config/module/testing.go delete mode 100644 config/module/tree.go delete mode 100644 config/module/tree_gob.go delete mode 100644 config/module/tree_gob_test.go delete mode 100644 config/module/tree_test.go delete mode 100644 config/module/validate_provider_alias.go delete mode 100644 config/module/versions.go delete mode 100644 config/module/versions_test.go delete mode 100644 terraform/eval_count_computed.go delete mode 100644 terraform/interpolate.go create mode 100644 terraform/resource_mode.go create mode 100644 terraform/resource_mode_string.go delete mode 100644 terraform/transform_config_old.go diff --git a/config/module/copy_dir.go b/config/module/copy_dir.go deleted file mode 100644 index 095f61d85..000000000 --- a/config/module/copy_dir.go +++ /dev/null @@ -1,114 +0,0 @@ -package module - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// copyDir copies the src directory contents into dst. Both directories -// should already exist. -func copyDir(dst, src string) error { - src, err := filepath.EvalSymlinks(src) - if err != nil { - return err - } - - walkFn := func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if path == src { - return nil - } - - if strings.HasPrefix(filepath.Base(path), ".") { - // Skip any dot files - if info.IsDir() { - return filepath.SkipDir - } else { - return nil - } - } - - // The "path" has the src prefixed to it. We need to join our - // destination with the path without the src on it. - dstPath := filepath.Join(dst, path[len(src):]) - - // we don't want to try and copy the same file over itself. - if eq, err := sameFile(path, dstPath); eq { - return nil - } else if err != nil { - return err - } - - // If we have a directory, make that subdirectory, then continue - // the walk. - if info.IsDir() { - if path == filepath.Join(src, dst) { - // dst is in src; don't walk it. - return nil - } - - if err := os.MkdirAll(dstPath, 0755); err != nil { - return err - } - - return nil - } - - // If we have a file, copy the contents. - srcF, err := os.Open(path) - if err != nil { - return err - } - defer srcF.Close() - - dstF, err := os.Create(dstPath) - if err != nil { - return err - } - defer dstF.Close() - - if _, err := io.Copy(dstF, srcF); err != nil { - return err - } - - // Chmod it - return os.Chmod(dstPath, info.Mode()) - } - - return filepath.Walk(src, walkFn) -} - -// sameFile tried to determine if to paths are the same file. -// If the paths don't match, we lookup the inode on supported systems. -func sameFile(a, b string) (bool, error) { - if a == b { - return true, nil - } - - aIno, err := inode(a) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - - bIno, err := inode(b) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - - if aIno > 0 && aIno == bIno { - return true, nil - } - - return false, nil -} diff --git a/config/module/detector_test.go b/config/module/detector_test.go deleted file mode 100644 index 8f727f4da..000000000 --- a/config/module/detector_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package module - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/registry/regsrc" -) - -func TestParseRegistrySource(t *testing.T) { - for _, tc := range []struct { - source string - host string - id string - err bool - notRegistry bool - }{ - { // simple source id - source: "namespace/id/provider", - id: "namespace/id/provider", - }, - { // source with hostname - source: "registry.com/namespace/id/provider", - host: "registry.com", - id: "namespace/id/provider", - }, - { // source with hostname and port - source: "registry.com:4443/namespace/id/provider", - host: "registry.com:4443", - id: "namespace/id/provider", - }, - { // too many parts - source: "registry.com/namespace/id/provider/extra", - err: true, - }, - { // local path - source: "./local/file/path", - notRegistry: true, - }, - { // local path with hostname - source: "./registry.com/namespace/id/provider", - notRegistry: true, - }, - { // full URL - source: "https://example.com/foo/bar/baz", - notRegistry: true, - }, - { // punycode host not allowed in source - source: "xn--80akhbyknj4f.com/namespace/id/provider", - err: true, - }, - { // simple source id with subdir - source: "namespace/id/provider//subdir", - id: "namespace/id/provider", - }, - { // source with hostname and subdir - source: "registry.com/namespace/id/provider//subdir", - host: "registry.com", - id: "namespace/id/provider", - }, - { // source with hostname - source: "registry.com/namespace/id/provider", - host: "registry.com", - id: "namespace/id/provider", - }, - { // we special case github - source: "github.com/namespace/id/provider", - notRegistry: true, - }, - { // we special case github ssh - source: "git@github.com:namespace/id/provider", - notRegistry: true, - }, - { // we special case bitbucket - source: "bitbucket.org/namespace/id/provider", - notRegistry: true, - }, - } { - t.Run(tc.source, func(t *testing.T) { - mod, err := regsrc.ParseModuleSource(tc.source) - if tc.notRegistry { - if err != regsrc.ErrInvalidModuleSource { - t.Fatalf("%q should not be a registry source, got err %v", tc.source, err) - } - return - } - - if tc.err { - if err == nil { - t.Fatal("expected error") - } - return - } - - if err != nil { - t.Fatal(err) - } - - id := fmt.Sprintf("%s/%s/%s", mod.RawNamespace, mod.RawName, mod.RawProvider) - - if tc.host != "" { - if mod.RawHost.Normalized() != tc.host { - t.Fatalf("expected host %q, got %q", tc.host, mod.RawHost) - } - } - - if tc.id != id { - t.Fatalf("expected id %q, got %q", tc.id, id) - } - }) - } -} diff --git a/config/module/get.go b/config/module/get.go deleted file mode 100644 index 5073d0d27..000000000 --- a/config/module/get.go +++ /dev/null @@ -1,57 +0,0 @@ -package module - -import ( - "io/ioutil" - "os" - "path/filepath" - - "github.com/hashicorp/go-getter" -) - -// GetMode is an enum that describes how modules are loaded. -// -// GetModeLoad says that modules will not be downloaded or updated, they will -// only be loaded from the storage. -// -// GetModeGet says that modules can be initially downloaded if they don't -// exist, but otherwise to just load from the current version in storage. -// -// GetModeUpdate says that modules should be checked for updates and -// downloaded prior to loading. If there are no updates, we load the version -// from disk, otherwise we download first and then load. -type GetMode byte - -const ( - GetModeNone GetMode = iota - GetModeGet - GetModeUpdate -) - -// GetCopy is the same as Get except that it downloads a copy of the -// module represented by source. -// -// This copy will omit and dot-prefixed files (such as .git/, .hg/) and -// can't be updated on its own. -func GetCopy(dst, src string) error { - // Create the temporary directory to do the real Get to - tmpDir, err := ioutil.TempDir("", "tf") - if err != nil { - return err - } - defer os.RemoveAll(tmpDir) - - tmpDir = filepath.Join(tmpDir, "module") - - // Get to that temporary dir - if err := getter.Get(tmpDir, src); err != nil { - return err - } - - // Make sure the destination exists - if err := os.MkdirAll(dst, 0755); err != nil { - return err - } - - // Copy to the final location - return copyDir(dst, tmpDir) -} diff --git a/config/module/inode.go b/config/module/inode.go deleted file mode 100644 index da520abcb..000000000 --- a/config/module/inode.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build linux darwin openbsd netbsd solaris dragonfly - -package module - -import ( - "fmt" - "os" - "syscall" -) - -// lookup the inode of a file on posix systems -func inode(path string) (uint64, error) { - stat, err := os.Stat(path) - if err != nil { - return 0, err - } - if st, ok := stat.Sys().(*syscall.Stat_t); ok { - return st.Ino, nil - } - return 0, fmt.Errorf("could not determine file inode") -} diff --git a/config/module/inode_freebsd.go b/config/module/inode_freebsd.go deleted file mode 100644 index 0d95730d9..000000000 --- a/config/module/inode_freebsd.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build freebsd - -package module - -import ( - "fmt" - "os" - "syscall" -) - -// lookup the inode of a file on posix systems -func inode(path string) (uint64, error) { - stat, err := os.Stat(path) - if err != nil { - return 0, err - } - if st, ok := stat.Sys().(*syscall.Stat_t); ok { - return uint64(st.Ino), nil - } - return 0, fmt.Errorf("could not determine file inode") -} diff --git a/config/module/inode_windows.go b/config/module/inode_windows.go deleted file mode 100644 index c0cf45538..000000000 --- a/config/module/inode_windows.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build windows - -package module - -// no syscall.Stat_t on windows, return 0 for inodes -func inode(path string) (uint64, error) { - return 0, nil -} diff --git a/config/module/module.go b/config/module/module.go deleted file mode 100644 index 7dc8fccda..000000000 --- a/config/module/module.go +++ /dev/null @@ -1,9 +0,0 @@ -package module - -// Module represents the metadata for a single module. -type Module struct { - Name string - Source string - Version string - Providers map[string]string -} diff --git a/config/module/module_test.go b/config/module/module_test.go deleted file mode 100644 index 73483c412..000000000 --- a/config/module/module_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package module - -import ( - "io/ioutil" - "log" - "os" - "path/filepath" - "testing" - - "github.com/hashicorp/terraform/config" - "github.com/hashicorp/terraform/svchost/disco" -) - -func init() { - if os.Getenv("TF_LOG") == "" { - log.SetOutput(ioutil.Discard) - } -} - -const fixtureDir = "./testdata" - -func tempDir(t *testing.T) string { - t.Helper() - dir, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - if err := os.RemoveAll(dir); err != nil { - t.Fatalf("err: %s", err) - } - - return dir -} - -func testConfig(t *testing.T, n string) *config.Config { - t.Helper() - c, err := config.LoadDir(filepath.Join(fixtureDir, n)) - if err != nil { - t.Fatalf("err: %s", err) - } - - return c -} - -func testStorage(t *testing.T, d *disco.Disco) *Storage { - t.Helper() - return NewStorage(tempDir(t), d) -} diff --git a/config/module/storage.go b/config/module/storage.go deleted file mode 100644 index 7734cbc0b..000000000 --- a/config/module/storage.go +++ /dev/null @@ -1,346 +0,0 @@ -package module - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" - "os" - "path/filepath" - - getter "github.com/hashicorp/go-getter" - "github.com/hashicorp/terraform/registry" - "github.com/hashicorp/terraform/registry/regsrc" - "github.com/hashicorp/terraform/svchost/disco" - "github.com/mitchellh/cli" -) - -const manifestName = "modules.json" - -// moduleManifest is the serialization structure used to record the stored -// module's metadata. -type moduleManifest struct { - Modules []moduleRecord -} - -// moduleRecords represents the stored module's metadata. -// This is compared for equality using '==', so all fields needs to remain -// comparable. -type moduleRecord struct { - // Source is the module source string from the config, minus any - // subdirectory. - Source string - - // Key is the locally unique identifier for this module. - Key string - - // Version is the exact version string for the stored module. - Version string - - // Dir is the directory name returned by the FileStorage. This is what - // allows us to correlate a particular module version with the location on - // disk. - Dir string - - // Root is the root directory containing the module. If the module is - // unpacked from an archive, and not located in the root directory, this is - // used to direct the loader to the correct subdirectory. This is - // independent from any subdirectory in the original source string, which - // may traverse further into the module tree. - Root string - - // url is the location of the module source - url string - - // Registry is true if this module is sourced from a registry - registry bool -} - -// Storage implements methods to manage the storage of modules. -// This is used by Tree.Load to query registries, authenticate requests, and -// store modules locally. -type Storage struct { - // StorageDir is the full path to the directory where all modules will be - // stored. - StorageDir string - - // Ui is an optional cli.Ui for user output - Ui cli.Ui - - // Mode is the GetMode that will be used for various operations. - Mode GetMode - - registry *registry.Client -} - -// NewStorage returns a new initialized Storage object. -func NewStorage(dir string, services *disco.Disco) *Storage { - regClient := registry.NewClient(services, nil) - - return &Storage{ - StorageDir: dir, - registry: regClient, - } -} - -// loadManifest returns the moduleManifest file from the parent directory. -func (s Storage) loadManifest() (moduleManifest, error) { - manifest := moduleManifest{} - - manifestPath := filepath.Join(s.StorageDir, manifestName) - data, err := ioutil.ReadFile(manifestPath) - if err != nil && !os.IsNotExist(err) { - return manifest, err - } - - if len(data) == 0 { - return manifest, nil - } - - if err := json.Unmarshal(data, &manifest); err != nil { - return manifest, err - } - return manifest, nil -} - -// Store the location of the module, along with the version used and the module -// root directory. The storage method loads the entire file and rewrites it -// each time. This is only done a few times during init, so efficiency is -// not a concern. -func (s Storage) recordModule(rec moduleRecord) error { - manifest, err := s.loadManifest() - if err != nil { - // if there was a problem with the file, we will attempt to write a new - // one. Any non-data related error should surface there. - log.Printf("[WARN] error reading module manifest: %s", err) - } - - // do nothing if we already have the exact module - for i, stored := range manifest.Modules { - if rec == stored { - return nil - } - - // they are not equal, but if the storage path is the same we need to - // remove this rec to be replaced. - if rec.Dir == stored.Dir { - manifest.Modules[i] = manifest.Modules[len(manifest.Modules)-1] - manifest.Modules = manifest.Modules[:len(manifest.Modules)-1] - break - } - } - - manifest.Modules = append(manifest.Modules, rec) - - js, err := json.Marshal(manifest) - if err != nil { - panic(err) - } - - manifestPath := filepath.Join(s.StorageDir, manifestName) - return ioutil.WriteFile(manifestPath, js, 0644) -} - -// load the manifest from dir, and return all module versions matching the -// provided source. Records with no version info will be skipped, as they need -// to be uniquely identified by other means. -func (s Storage) moduleVersions(source string) ([]moduleRecord, error) { - manifest, err := s.loadManifest() - if err != nil { - return manifest.Modules, err - } - - var matching []moduleRecord - - for _, m := range manifest.Modules { - if m.Source == source && m.Version != "" { - log.Printf("[DEBUG] found local version %q for module %s", m.Version, m.Source) - matching = append(matching, m) - } - } - - return matching, nil -} - -func (s Storage) moduleDir(key string) (string, error) { - manifest, err := s.loadManifest() - if err != nil { - return "", err - } - - for _, m := range manifest.Modules { - if m.Key == key { - return m.Dir, nil - } - } - - return "", nil -} - -// return only the root directory of the module stored in dir. -func (s Storage) getModuleRoot(dir string) (string, error) { - manifest, err := s.loadManifest() - if err != nil { - return "", err - } - - for _, mod := range manifest.Modules { - if mod.Dir == dir { - return mod.Root, nil - } - } - return "", nil -} - -// record only the Root directory for the module stored at dir. -func (s Storage) recordModuleRoot(dir, root string) error { - rec := moduleRecord{ - Dir: dir, - Root: root, - } - - return s.recordModule(rec) -} - -func (s Storage) output(msg string) { - if s.Ui == nil || s.Mode == GetModeNone { - return - } - s.Ui.Output(msg) -} - -func (s Storage) getStorage(key string, src string) (string, bool, error) { - storage := &getter.FolderStorage{ - StorageDir: s.StorageDir, - } - - log.Printf("[DEBUG] fetching module from %s", src) - - // Get the module with the level specified if we were told to. - if s.Mode > GetModeNone { - log.Printf("[DEBUG] fetching %q with key %q", src, key) - if err := storage.Get(key, src, s.Mode == GetModeUpdate); err != nil { - return "", false, err - } - } - - // Get the directory where the module is. - dir, found, err := storage.Dir(key) - log.Printf("[DEBUG] found %q in %q: %t", src, dir, found) - return dir, found, err -} - -// find a stored module that's not from a registry -func (s Storage) findModule(key string) (string, error) { - if s.Mode == GetModeUpdate { - return "", nil - } - - return s.moduleDir(key) -} - -// GetModule fetches a module source into the specified directory. This is used -// as a convenience function by the CLI to initialize a configuration. -func (s Storage) GetModule(dst, src string) error { - // reset this in case the caller was going to re-use it - mode := s.Mode - s.Mode = GetModeUpdate - defer func() { - s.Mode = mode - }() - - rec, err := s.findRegistryModule(src, anyVersion) - if err != nil { - return err - } - - pwd, err := os.Getwd() - if err != nil { - return err - } - - source := rec.url - if source == "" { - source, err = getter.Detect(src, pwd, getter.Detectors) - if err != nil { - return fmt.Errorf("module %s: %s", src, err) - } - } - - if source == "" { - return fmt.Errorf("module %q not found", src) - } - - return GetCopy(dst, source) -} - -// find a registry module -func (s Storage) findRegistryModule(mSource, constraint string) (moduleRecord, error) { - rec := moduleRecord{ - Source: mSource, - } - // detect if we have a registry source - mod, err := regsrc.ParseModuleSource(mSource) - switch err { - case nil: - //ok - case regsrc.ErrInvalidModuleSource: - return rec, nil - default: - return rec, err - } - rec.registry = true - - log.Printf("[TRACE] %q is a registry module", mod.Display()) - - versions, err := s.moduleVersions(mod.String()) - if err != nil { - log.Printf("[ERROR] error looking up versions for %q: %s", mod.Display(), err) - return rec, err - } - - match, err := newestRecord(versions, constraint) - if err != nil { - log.Printf("[INFO] no matching version for %q<%s>, %s", mod.Display(), constraint, err) - } - log.Printf("[DEBUG] matched %q version %s for %s", mod, match.Version, constraint) - - rec.Dir = match.Dir - rec.Version = match.Version - found := rec.Dir != "" - - // we need to lookup available versions - // Only on Get if it's not found, on unconditionally on Update - if (s.Mode == GetModeGet && !found) || (s.Mode == GetModeUpdate) { - resp, err := s.registry.ModuleVersions(mod) - if err != nil { - return rec, err - } - - if len(resp.Modules) == 0 { - return rec, fmt.Errorf("module %q not found in registry", mod.Display()) - } - - match, err := newestVersion(resp.Modules[0].Versions, constraint) - if err != nil { - return rec, err - } - - if match == nil { - return rec, fmt.Errorf("no versions for %q found matching %q", mod.Display(), constraint) - } - - rec.Version = match.Version - - rec.url, err = s.registry.ModuleLocation(mod, rec.Version) - if err != nil { - return rec, err - } - - // we've already validated this by now - host, _ := mod.SvcHost() - s.output(fmt.Sprintf(" Found version %s of %s on %s", rec.Version, mod.Module(), host.ForDisplay())) - - } - return rec, nil -} diff --git a/config/module/storage_test.go b/config/module/storage_test.go deleted file mode 100644 index e174ec181..000000000 --- a/config/module/storage_test.go +++ /dev/null @@ -1,189 +0,0 @@ -package module - -import ( - "io/ioutil" - "net/url" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/hashicorp/terraform/registry/regsrc" - "github.com/hashicorp/terraform/registry/test" -) - -func TestGetModule(t *testing.T) { - server := test.Registry() - defer server.Close() - disco := test.Disco(server) - - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) - storage := NewStorage(td, disco) - - // this module exists in a test fixture, and is known by the test.Registry - // relative to our cwd. - err = storage.GetModule(filepath.Join(td, "foo"), "registry/local/sub") - if err != nil { - t.Fatal(err) - } - - // list everything to make sure nothing else got unpacked in here - ls, err := ioutil.ReadDir(td) - if err != nil { - t.Fatal(err) - } - - var names []string - for _, info := range ls { - names = append(names, info.Name()) - } - - if !(len(names) == 1 && names[0] == "foo") { - t.Fatalf("expected only directory 'foo', found entries %q", names) - } - - _, err = os.Stat(filepath.Join(td, "foo", "main.tf")) - if err != nil { - t.Fatal(err) - } -} - -// GitHub archives always contain the module source in a single subdirectory, -// so the registry will return a path with with a `//*` suffix. We need to make -// sure this doesn't intefere with our internal handling of `//` subdir. -func TestRegistryGitHubArchive(t *testing.T) { - server := test.Registry() - defer server.Close() - - disco := test.Disco(server) - storage := testStorage(t, disco) - - tree := NewTree("", testConfig(t, "registry-tar-subdir")) - - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - // stop the registry server, and make sure that we don't need to call out again - server.Close() - tree = NewTree("", testConfig(t, "registry-tar-subdir")) - - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - actual := strings.TrimSpace(tree.String()) - expected := strings.TrimSpace(treeLoadSubdirStr) - if actual != expected { - t.Fatalf("got: \n\n%s\nexpected: \n\n%s", actual, expected) - } -} - -// Test that the //subdir notation can be used with registry modules -func TestRegisryModuleSubdir(t *testing.T) { - server := test.Registry() - defer server.Close() - - disco := test.Disco(server) - storage := testStorage(t, disco) - tree := NewTree("", testConfig(t, "registry-subdir")) - - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - actual := strings.TrimSpace(tree.String()) - expected := strings.TrimSpace(treeLoadRegistrySubdirStr) - if actual != expected { - t.Fatalf("got: \n\n%s\nexpected: \n\n%s", actual, expected) - } -} - -func TestAccRegistryDiscover(t *testing.T) { - if os.Getenv("TF_ACC") == "" { - t.Skip("skipping ACC test") - } - - // simply check that we get a valid github URL for this from the registry - module, err := regsrc.ParseModuleSource("hashicorp/consul/aws") - if err != nil { - t.Fatal(err) - } - - s := NewStorage("/tmp", nil) - loc, err := s.registry.ModuleLocation(module, "") - if err != nil { - t.Fatal(err) - } - - u, err := url.Parse(loc) - if err != nil { - t.Fatal(err) - } - - if !strings.HasSuffix(u.Host, "github.com") { - t.Fatalf("expected host 'github.com', got: %q", u.Host) - } - - if !strings.Contains(u.String(), "consul") { - t.Fatalf("url doesn't contain 'consul': %s", u.String()) - } -} - -func TestAccRegistryLoad(t *testing.T) { - if os.Getenv("TF_ACC") == "" { - t.Skip("skipping ACC test") - } - - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, "registry-load")) - - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - // TODO expand this further by fetching some metadata from the registry - actual := strings.TrimSpace(tree.String()) - if !strings.Contains(actual, "(path: vault)") { - t.Fatal("missing vault module, got:\n", actual) - } -} diff --git a/config/module/testdata/basic-dot/.test/foo.tf b/config/module/testdata/basic-dot/.test/foo.tf deleted file mode 100644 index 76f177f19..000000000 --- a/config/module/testdata/basic-dot/.test/foo.tf +++ /dev/null @@ -1 +0,0 @@ -# Hi diff --git a/config/module/testdata/basic-dot/main.tf b/config/module/testdata/basic-dot/main.tf deleted file mode 100644 index 383063715..000000000 --- a/config/module/testdata/basic-dot/main.tf +++ /dev/null @@ -1,5 +0,0 @@ -# Hello - -module "foo" { - source = "./foo" -} diff --git a/config/module/testdata/basic-git/DOTgit/COMMIT_EDITMSG b/config/module/testdata/basic-git/DOTgit/COMMIT_EDITMSG deleted file mode 100644 index a580d5737..000000000 --- a/config/module/testdata/basic-git/DOTgit/COMMIT_EDITMSG +++ /dev/null @@ -1,7 +0,0 @@ -add subdir -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# On branch master -# Changes to be committed: -# new file: subdir/sub.tf -# diff --git a/config/module/testdata/basic-git/DOTgit/HEAD b/config/module/testdata/basic-git/DOTgit/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/config/module/testdata/basic-git/DOTgit/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/config/module/testdata/basic-git/DOTgit/config b/config/module/testdata/basic-git/DOTgit/config deleted file mode 100644 index 6c9406b7d..000000000 --- a/config/module/testdata/basic-git/DOTgit/config +++ /dev/null @@ -1,7 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true - precomposeunicode = true diff --git a/config/module/testdata/basic-git/DOTgit/description b/config/module/testdata/basic-git/DOTgit/description deleted file mode 100644 index 498b267a8..000000000 --- a/config/module/testdata/basic-git/DOTgit/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/config/module/testdata/basic-git/DOTgit/hooks/applypatch-msg.sample b/config/module/testdata/basic-git/DOTgit/hooks/applypatch-msg.sample deleted file mode 100755 index 8b2a2fe84..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -test -x "$GIT_DIR/hooks/commit-msg" && - exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} -: diff --git a/config/module/testdata/basic-git/DOTgit/hooks/commit-msg.sample b/config/module/testdata/basic-git/DOTgit/hooks/commit-msg.sample deleted file mode 100755 index b58d1184a..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/config/module/testdata/basic-git/DOTgit/hooks/post-update.sample b/config/module/testdata/basic-git/DOTgit/hooks/post-update.sample deleted file mode 100755 index ec17ec193..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/config/module/testdata/basic-git/DOTgit/hooks/pre-applypatch.sample b/config/module/testdata/basic-git/DOTgit/hooks/pre-applypatch.sample deleted file mode 100755 index b1f187c2e..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -test -x "$GIT_DIR/hooks/pre-commit" && - exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} -: diff --git a/config/module/testdata/basic-git/DOTgit/hooks/pre-commit.sample b/config/module/testdata/basic-git/DOTgit/hooks/pre-commit.sample deleted file mode 100755 index 68d62d544..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/pre-commit.sample +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -# If you want to allow non-ASCII filenames set this variable to true. -allownonascii=$(git config --bool hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ASCII filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - cat <<\EOF -Error: Attempt to add a non-ASCII file name. - -This can cause problems if you want to work with people on other platforms. - -To be portable it is advisable to rename the file. - -If you know what you are doing you can disable this check using: - - git config hooks.allownonascii true -EOF - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/config/module/testdata/basic-git/DOTgit/hooks/pre-push.sample b/config/module/testdata/basic-git/DOTgit/hooks/pre-push.sample deleted file mode 100755 index 1f3bcebfd..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/pre-push.sample +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh - -# An example hook script to verify what is about to be pushed. Called by "git -# push" after it has checked the remote status, but before anything has been -# pushed. If this script exits with a non-zero status nothing will be pushed. -# -# This hook is called with the following parameters: -# -# $1 -- Name of the remote to which the push is being done -# $2 -- URL to which the push is being done -# -# If pushing without using a named remote those arguments will be equal. -# -# Information about the commits which are being pushed is supplied as lines to -# the standard input in the form: -# -# -# -# This sample shows how to prevent push of commits where the log message starts -# with "WIP" (work in progress). - -remote="$1" -url="$2" - -z40=0000000000000000000000000000000000000000 - -IFS=' ' -while read local_ref local_sha remote_ref remote_sha -do - if [ "$local_sha" = $z40 ] - then - # Handle delete - : - else - if [ "$remote_sha" = $z40 ] - then - # New branch, examine all commits - range="$local_sha" - else - # Update to existing branch, examine new commits - range="$remote_sha..$local_sha" - fi - - # Check for WIP commit - commit=`git rev-list -n 1 --grep '^WIP' "$range"` - if [ -n "$commit" ] - then - echo "Found WIP commit in $local_ref, not pushing" - exit 1 - fi - fi -done - -exit 0 diff --git a/config/module/testdata/basic-git/DOTgit/hooks/pre-rebase.sample b/config/module/testdata/basic-git/DOTgit/hooks/pre-rebase.sample deleted file mode 100755 index 9773ed4cb..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up-to-date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -exit 0 - -################################################################ - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". diff --git a/config/module/testdata/basic-git/DOTgit/hooks/prepare-commit-msg.sample b/config/module/testdata/basic-git/DOTgit/hooks/prepare-commit-msg.sample deleted file mode 100755 index f093a02ec..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/prepare-commit-msg.sample +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first comments out the -# "Conflicts:" part of a merge commit. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -case "$2,$3" in - merge,) - /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; - -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$1" ;; - - *) ;; -esac - -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/config/module/testdata/basic-git/DOTgit/hooks/update.sample b/config/module/testdata/basic-git/DOTgit/hooks/update.sample deleted file mode 100755 index d84758373..000000000 --- a/config/module/testdata/basic-git/DOTgit/hooks/update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to blocks unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --bool hooks.allowunannotated) -allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -denycreatebranch=$(git config --bool hooks.denycreatebranch) -allowdeletetag=$(git config --bool hooks.allowdeletetag) -allowmodifytag=$(git config --bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero="0000000000000000000000000000000000000000" -if [ "$newrev" = "$zero" ]; then - newrev_type=delete -else - newrev_type=$(git cat-file -t $newrev) -fi - -case "$refname","$newrev_type" in - refs/tags/*,commit) - # un-annotated tag - short_refname=${refname##refs/tags/} - if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 diff --git a/config/module/testdata/basic-git/DOTgit/index b/config/module/testdata/basic-git/DOTgit/index deleted file mode 100644 index 99b358e271f626bc5ee9ad355678185228a62198..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmZ?q402{*U|<5_5CyjoAk6@y85tN@7-Gyi7#JFtFfcHF1xkqkvA%^ta$&^xl0|%X z4(yllW#6#B{fI3Cdv0Q8o?b~BNWbcB4 1410850637 -0700 commit (initial): A commit -497bc37401eb3c9b11865b1768725b64066eccee 243f0fc5c4e586d1a3daa54c981b6f34e9ab1085 Mitchell Hashimoto 1410886526 -0700 commit: tag1 -243f0fc5c4e586d1a3daa54c981b6f34e9ab1085 1f31e97f053caeb5d6b7bffa3faf82941c99efa2 Mitchell Hashimoto 1410886536 -0700 commit: remove tag1 -1f31e97f053caeb5d6b7bffa3faf82941c99efa2 1f31e97f053caeb5d6b7bffa3faf82941c99efa2 Mitchell Hashimoto 1410886909 -0700 checkout: moving from master to test-branch -1f31e97f053caeb5d6b7bffa3faf82941c99efa2 7b7614f8759ac8b5e4b02be65ad8e2667be6dd87 Mitchell Hashimoto 1410886913 -0700 commit: Branch -7b7614f8759ac8b5e4b02be65ad8e2667be6dd87 1f31e97f053caeb5d6b7bffa3faf82941c99efa2 Mitchell Hashimoto 1410886916 -0700 checkout: moving from test-branch to master -1f31e97f053caeb5d6b7bffa3faf82941c99efa2 146492b04efe0aae2b8288c5c0aef6a951030fde Mitchell Hashimoto 1411767116 -0700 commit: add subdir diff --git a/config/module/testdata/basic-git/DOTgit/logs/refs/heads/master b/config/module/testdata/basic-git/DOTgit/logs/refs/heads/master deleted file mode 100644 index f30b1d9d3..000000000 --- a/config/module/testdata/basic-git/DOTgit/logs/refs/heads/master +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 497bc37401eb3c9b11865b1768725b64066eccee Mitchell Hashimoto 1410850637 -0700 commit (initial): A commit -497bc37401eb3c9b11865b1768725b64066eccee 243f0fc5c4e586d1a3daa54c981b6f34e9ab1085 Mitchell Hashimoto 1410886526 -0700 commit: tag1 -243f0fc5c4e586d1a3daa54c981b6f34e9ab1085 1f31e97f053caeb5d6b7bffa3faf82941c99efa2 Mitchell Hashimoto 1410886536 -0700 commit: remove tag1 -1f31e97f053caeb5d6b7bffa3faf82941c99efa2 146492b04efe0aae2b8288c5c0aef6a951030fde Mitchell Hashimoto 1411767116 -0700 commit: add subdir diff --git a/config/module/testdata/basic-git/DOTgit/logs/refs/heads/test-branch b/config/module/testdata/basic-git/DOTgit/logs/refs/heads/test-branch deleted file mode 100644 index 937067a2a..000000000 --- a/config/module/testdata/basic-git/DOTgit/logs/refs/heads/test-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 1f31e97f053caeb5d6b7bffa3faf82941c99efa2 Mitchell Hashimoto 1410886909 -0700 branch: Created from HEAD -1f31e97f053caeb5d6b7bffa3faf82941c99efa2 7b7614f8759ac8b5e4b02be65ad8e2667be6dd87 Mitchell Hashimoto 1410886913 -0700 commit: Branch diff --git a/config/module/testdata/basic-git/DOTgit/objects/14/6492b04efe0aae2b8288c5c0aef6a951030fde b/config/module/testdata/basic-git/DOTgit/objects/14/6492b04efe0aae2b8288c5c0aef6a951030fde deleted file mode 100644 index 2a713ec7cf4938e12e84fc7f0aa6231c45c9a946..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmV;b09F5Z0j^8 zP`O@wiXbUzWpDU7*Rk7Mo3iS**>8TVt&chE=W*a|=k?F7_s(rQ%jjPgA^;%)p#5;< YoH_I;rvA&A;Zp45nM>Qv3xnxYMYiKtt^fc4 diff --git a/config/module/testdata/basic-git/DOTgit/objects/1d/3d6744266642cb7623e2c678c33c77b075c49f b/config/module/testdata/basic-git/DOTgit/objects/1d/3d6744266642cb7623e2c678c33c77b075c49f deleted file mode 100644 index 2518fd6ac51a5a3b76ebf290ea8866b81746de0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84 zcmV-a0IUCa0V^p=O;s?nU@$Z=Ff%bx$W6@5(<@11urNq2jQC!%i0{sU{W8An8}_#! qu{ALO0)^tzq?F7eh90TPQ}Q#mUEq)YdhE=+UK>u`%ew&du^oyiI4LLq diff --git a/config/module/testdata/basic-git/DOTgit/objects/1f/31e97f053caeb5d6b7bffa3faf82941c99efa2 b/config/module/testdata/basic-git/DOTgit/objects/1f/31e97f053caeb5d6b7bffa3faf82941c99efa2 deleted file mode 100644 index 5793a840b76235dafcb144ed66d1b8d274ed76bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167 zcmV;Y09gNc0jde)V4 V5S{)q#u}CSCf;!s>;oX7Q=N++Phyo>KhY@))4ka?%IV3*@oJ1_}!Me>)YD$BHN~~{94vhTh*t2;A_M3v&+5kx(&IOvjz`l>`{yQXvi4V SwJ)0dC8iqRL45!N?@<9%)ls?t diff --git a/config/module/testdata/basic-git/DOTgit/objects/38/30637158f774a20edcc0bf1c4d07b0bf87c43d b/config/module/testdata/basic-git/DOTgit/objects/38/30637158f774a20edcc0bf1c4d07b0bf87c43d deleted file mode 100644 index ef8ebf7282975b2da2da3cfe6cef1477fcca395c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59 zcmV-B0L1@z0ZYosPf{>3XHZt~NX^N~=iAXD~D{Ff%bx$W6@5(<@11urNq2jQC!%i0{sU{W8An8}_#! qu|-l6pH!5Xmz)7o`E2f^*_$q2bN24mTvr}-x_ê­Uƒ´“-gˆ³³‚&—çx»G EBöyA >ÅÅÅ/)}ƒk•TòºÂ…Ÿ¥¶.ü´©üÚéѸ®SêíÚéàl öHˆjÔqHþ ¦ÎðõÔ%øD‡ \ No newline at end of file diff --git a/config/module/testdata/basic-git/DOTgit/objects/7b/7614f8759ac8b5e4b02be65ad8e2667be6dd87 b/config/module/testdata/basic-git/DOTgit/objects/7b/7614f8759ac8b5e4b02be65ad8e2667be6dd87 deleted file mode 100644 index abe281a74..000000000 --- a/config/module/testdata/basic-git/DOTgit/objects/7b/7614f8759ac8b5e4b02be65ad8e2667be6dd87 +++ /dev/null @@ -1,2 +0,0 @@ -x­ÎK -Â0…aÇYE6`Iš7ˆˆ#'.â&¹×šFbÜ¿EpN?ø'µZ—Ág££#r-´•>…l&`²²&éQdŠÑ€ò.YØ:nƒKRƒ#aTŒ&Ûè"(òsÐ2…€3ƒ÷(­óû2RÁuå7x•¥¶Ñøi?ðµ©üìò¨°¬SjõÌ¥–Â{¤âGá„`»îÅÀ¿Œ±k‡-öÛS„ \ No newline at end of file diff --git a/config/module/testdata/basic-git/DOTgit/objects/8c/1a79ca1f98b6d00f5bf5c6cc9e8d3c092dd3ba b/config/module/testdata/basic-git/DOTgit/objects/8c/1a79ca1f98b6d00f5bf5c6cc9e8d3c092dd3ba deleted file mode 100644 index 656ae8e33e7cb6dd2220cec705ebf707caad03c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51 zcmbc HOYk88vc(gk diff --git a/config/module/testdata/basic-git/DOTgit/objects/96/43088174e25a9bd91c27970a580af0085c9f32 b/config/module/testdata/basic-git/DOTgit/objects/96/43088174e25a9bd91c27970a580af0085c9f32 deleted file mode 100644 index 387943288da570c5373bc4f0cb7b8005536653e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52 zcmV-40L%Y)0V^p=O;s>9WiT`_Ff%bx$W6@5(<@11urNq2jQC!%i0{sU{W8An8}_#! Ku>}Anzz?PeB^DI` diff --git a/config/module/testdata/basic-git/DOTgit/objects/b7/757b6a3696ad036e9aa2f5b4856d09e7f17993 b/config/module/testdata/basic-git/DOTgit/objects/b7/757b6a3696ad036e9aa2f5b4856d09e7f17993 deleted file mode 100644 index 10192566594b6bfa1e9d04c558444006bb2f27fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmV-Y0ImOc0V^p=O;s>AWiT`_Ff%bx$W6@5(<@11urNq2jQC!%i0{sU{W8An8}_#! ou|-l6Uy_(^2vYZK?xWe8E?#r??$%sa9(Ci;lb+y-0LsiEdb9E;RsaA1 diff --git a/config/module/testdata/basic-git/DOTgit/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/config/module/testdata/basic-git/DOTgit/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 deleted file mode 100644 index 711223894375fe1186ac5bfffdc48fb1fa1e65cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15 Wcmb=^>}vhYRG!~=>ejxFxg7V^;JV-L`jXd&PhOer=+rTh@j}%%hBW{9?W+v?SN{IR z{@{bE57=&yOBoo7fp{vI#Q^aG$jQgzX7-lU|K9k|T86DEAkBO8@7N_!HDIb@PI3YR zv#)^P79V5JjV5N>P0anhjJ6qgZ}Zq_;$`M-WN75M$-vNWlaJ394$K# z%*;#-O*U-UU|?zE~8+H~68-ISJn6r11$%Jn~3hUUC O%+xn%FqHDjM*;v@nt`|g diff --git a/config/module/testdata/basic-hg/.hg/store/00manifest.i b/config/module/testdata/basic-hg/.hg/store/00manifest.i deleted file mode 100644 index e35c6bf121b04e9a520ae6fcb95a06e381132f86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmZQzWME`~03#q}2xT+;hXRIf+oy9R`GtjZS|7jmaf#B=uR&8JsyZaZ;PC)>%p#d_9?E$&b?Fbd>K5VinW9-mZ{n3tRZc7ugMN~&p! mp|ORzsfDSDVX|qOfvJ(1X<~|@iAiFTWm=+zS&Csw5*Gmeyggk2 diff --git a/config/module/testdata/basic-hg/.hg/store/data/main.tf.i b/config/module/testdata/basic-hg/.hg/store/data/main.tf.i deleted file mode 100644 index f45ddc33f19db6ef2a8f723ce4e36e10db12a436..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112 zcmZQzWME`~00SVU4`nm_hk{)i%ZqQMPS2Zr>zb=wCx2OxuW=Ym4TvsPR`5v8$;s#9 n%FRzH%}G^IO3TkzQmE!q0D|KD(xT*41zQCrJ$;ZcS1lI+ym=or diff --git a/config/module/testdata/basic-hg/.hg/store/data/main__branch.tf.i b/config/module/testdata/basic-hg/.hg/store/data/main__branch.tf.i deleted file mode 100644 index a6bdf46f1091be151835fda73ea8ccb9f8c70c21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64 ocmZQzWME{#1dRWoUQPrLGn6+WD*P;%#K*02?S1MgRZ+ diff --git a/config/module/testdata/basic-hg/.hg/store/fncache b/config/module/testdata/basic-hg/.hg/store/fncache deleted file mode 100644 index a1babe068..000000000 --- a/config/module/testdata/basic-hg/.hg/store/fncache +++ /dev/null @@ -1,2 +0,0 @@ -data/main.tf.i -data/main_branch.tf.i diff --git a/config/module/testdata/basic-hg/.hg/store/phaseroots b/config/module/testdata/basic-hg/.hg/store/phaseroots deleted file mode 100644 index a08565294..000000000 --- a/config/module/testdata/basic-hg/.hg/store/phaseroots +++ /dev/null @@ -1 +0,0 @@ -1 dcaed7754d58264cb9a5916215a5442377307bd1 diff --git a/config/module/testdata/basic-hg/.hg/store/undo b/config/module/testdata/basic-hg/.hg/store/undo deleted file mode 100644 index cf2be297d7083584b62cd4d06b4f2bb835f193ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59 zcmYdEEJ@VQP0Y-TPbx~xOU}?MNz=<@FyJyU$W6@4OiL{;0dfruO@IQ)8Hsu6sX6)S JAQ5vjE&xq(5=sC7 diff --git a/config/module/testdata/basic-hg/.hg/store/undo.phaseroots b/config/module/testdata/basic-hg/.hg/store/undo.phaseroots deleted file mode 100644 index a08565294..000000000 --- a/config/module/testdata/basic-hg/.hg/store/undo.phaseroots +++ /dev/null @@ -1 +0,0 @@ -1 dcaed7754d58264cb9a5916215a5442377307bd1 diff --git a/config/module/testdata/basic-hg/.hg/undo.bookmarks b/config/module/testdata/basic-hg/.hg/undo.bookmarks deleted file mode 100644 index e69de29bb..000000000 diff --git a/config/module/testdata/basic-hg/.hg/undo.branch b/config/module/testdata/basic-hg/.hg/undo.branch deleted file mode 100644 index a81bc2dd2..000000000 --- a/config/module/testdata/basic-hg/.hg/undo.branch +++ /dev/null @@ -1 +0,0 @@ -test-branch \ No newline at end of file diff --git a/config/module/testdata/basic-hg/.hg/undo.desc b/config/module/testdata/basic-hg/.hg/undo.desc deleted file mode 100644 index d678f64de..000000000 --- a/config/module/testdata/basic-hg/.hg/undo.desc +++ /dev/null @@ -1,2 +0,0 @@ -1 -commit diff --git a/config/module/testdata/basic-hg/.hg/undo.dirstate b/config/module/testdata/basic-hg/.hg/undo.dirstate deleted file mode 100644 index 62e4ca2e911f538d8040be23a460d47b8f786da2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95 zcmcb!?s}9?wF=3 z0z?2IgAnhtnT-|Aw)=O_#bcYz%y%wxTz9-gm_R z5zJ=tx9}=|Q*)VUqJCcZ=lSmrtMP6vMV!8n`&^>oF!sx}+(=PAErue0$bY*_r1HG~ m)9ru{-~XHaZ$Ulp9{>OV000000001h&w2zDNG!GhC;$MV9(o@D diff --git a/config/module/testdata/basic-tar-subdir/main.tf b/config/module/testdata/basic-tar-subdir/main.tf deleted file mode 100644 index ceb0a19de..000000000 --- a/config/module/testdata/basic-tar-subdir/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "foo" { - source = "./foo.tgz//sub" -} diff --git a/config/module/testdata/basic/foo/main.tf b/config/module/testdata/basic/foo/main.tf deleted file mode 100644 index fec56017d..000000000 --- a/config/module/testdata/basic/foo/main.tf +++ /dev/null @@ -1 +0,0 @@ -# Hello diff --git a/config/module/testdata/basic/main.tf b/config/module/testdata/basic/main.tf deleted file mode 100644 index 383063715..000000000 --- a/config/module/testdata/basic/main.tf +++ /dev/null @@ -1,5 +0,0 @@ -# Hello - -module "foo" { - source = "./foo" -} diff --git a/config/module/testdata/basic/subdir/sub.tf b/config/module/testdata/basic/subdir/sub.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/config/module/testdata/change-intermediate-source/a/b/main.tf b/config/module/testdata/change-intermediate-source/a/b/main.tf deleted file mode 100644 index b91fad57a..000000000 --- a/config/module/testdata/change-intermediate-source/a/b/main.tf +++ /dev/null @@ -1 +0,0 @@ -resource "test_resource" "a-b" {} diff --git a/config/module/testdata/change-intermediate-source/a/main.tf b/config/module/testdata/change-intermediate-source/a/main.tf deleted file mode 100644 index acbf03927..000000000 --- a/config/module/testdata/change-intermediate-source/a/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "b" { - source = "./b" -} diff --git a/config/module/testdata/change-intermediate-source/c/b/main.tf b/config/module/testdata/change-intermediate-source/c/b/main.tf deleted file mode 100644 index 5a3565b33..000000000 --- a/config/module/testdata/change-intermediate-source/c/b/main.tf +++ /dev/null @@ -1 +0,0 @@ -resource "test_resource" "c-b" {} diff --git a/config/module/testdata/change-intermediate-source/c/main.tf b/config/module/testdata/change-intermediate-source/c/main.tf deleted file mode 100644 index acbf03927..000000000 --- a/config/module/testdata/change-intermediate-source/c/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "b" { - source = "./b" -} diff --git a/config/module/testdata/change-intermediate-source/main.tf b/config/module/testdata/change-intermediate-source/main.tf deleted file mode 100644 index 2326ee22a..000000000 --- a/config/module/testdata/change-intermediate-source/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "a" { - source = "./a" -} diff --git a/config/module/testdata/change-intermediate-source/main.tf.disabled b/config/module/testdata/change-intermediate-source/main.tf.disabled deleted file mode 100644 index 52dabca93..000000000 --- a/config/module/testdata/change-intermediate-source/main.tf.disabled +++ /dev/null @@ -1,3 +0,0 @@ -module "a" { - source = "./c" -} diff --git a/config/module/testdata/child/foo/bar/main.tf b/config/module/testdata/child/foo/bar/main.tf deleted file mode 100644 index df5927501..000000000 --- a/config/module/testdata/child/foo/bar/main.tf +++ /dev/null @@ -1,2 +0,0 @@ -# Hello - diff --git a/config/module/testdata/child/foo/main.tf b/config/module/testdata/child/foo/main.tf deleted file mode 100644 index 548d21b99..000000000 --- a/config/module/testdata/child/foo/main.tf +++ /dev/null @@ -1,5 +0,0 @@ -# Hello - -module "bar" { - source = "./bar" -} diff --git a/config/module/testdata/child/main.tf b/config/module/testdata/child/main.tf deleted file mode 100644 index 383063715..000000000 --- a/config/module/testdata/child/main.tf +++ /dev/null @@ -1,5 +0,0 @@ -# Hello - -module "foo" { - source = "./foo" -} diff --git a/config/module/testdata/conficting-submodule-names/a/c/main.tf b/config/module/testdata/conficting-submodule-names/a/c/main.tf deleted file mode 100644 index cd38281d3..000000000 --- a/config/module/testdata/conficting-submodule-names/a/c/main.tf +++ /dev/null @@ -1 +0,0 @@ -resource "test_instance" "a-c" {} diff --git a/config/module/testdata/conficting-submodule-names/a/main.tf b/config/module/testdata/conficting-submodule-names/a/main.tf deleted file mode 100644 index 35a6ec7e0..000000000 --- a/config/module/testdata/conficting-submodule-names/a/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "c" { - source = "./c" -} diff --git a/config/module/testdata/conficting-submodule-names/b/c/main.tf b/config/module/testdata/conficting-submodule-names/b/c/main.tf deleted file mode 100644 index bcf3f52f9..000000000 --- a/config/module/testdata/conficting-submodule-names/b/c/main.tf +++ /dev/null @@ -1 +0,0 @@ -resource "test_instance" "b-c" {} diff --git a/config/module/testdata/conficting-submodule-names/b/main.tf b/config/module/testdata/conficting-submodule-names/b/main.tf deleted file mode 100644 index 35a6ec7e0..000000000 --- a/config/module/testdata/conficting-submodule-names/b/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "c" { - source = "./c" -} diff --git a/config/module/testdata/conficting-submodule-names/main.tf b/config/module/testdata/conficting-submodule-names/main.tf deleted file mode 100644 index ed5ac91c7..000000000 --- a/config/module/testdata/conficting-submodule-names/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -module "a" { - source = "./a" -} - -module "b" { - source = "./b" -} diff --git a/config/module/testdata/discover-registry-local/exists-in-registry/identifier/provider/main.tf b/config/module/testdata/discover-registry-local/exists-in-registry/identifier/provider/main.tf deleted file mode 100644 index 907b0c7e4..000000000 --- a/config/module/testdata/discover-registry-local/exists-in-registry/identifier/provider/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "local" { - value = "test" -} diff --git a/config/module/testdata/discover-registry-local/main.tf b/config/module/testdata/discover-registry-local/main.tf deleted file mode 100644 index 93bd57972..000000000 --- a/config/module/testdata/discover-registry-local/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "provider" { - source = "exists-in-registry/identifier/provider" -} diff --git a/config/module/testdata/discover-subdirs/main.tf b/config/module/testdata/discover-subdirs/main.tf deleted file mode 100644 index 7ece92721..000000000 --- a/config/module/testdata/discover-subdirs/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "provider" { - source = "namespace/identifier/provider" -} diff --git a/config/module/testdata/discover-subdirs/namespace/identifier/provider/main.tf b/config/module/testdata/discover-subdirs/namespace/identifier/provider/main.tf deleted file mode 100644 index 907b0c7e4..000000000 --- a/config/module/testdata/discover-subdirs/namespace/identifier/provider/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "local" { - value = "test" -} diff --git a/config/module/testdata/dup/foo/main.tf b/config/module/testdata/dup/foo/main.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/config/module/testdata/dup/main.tf b/config/module/testdata/dup/main.tf deleted file mode 100644 index 98efd6e4f..000000000 --- a/config/module/testdata/dup/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -module "foo" { - source = "./foo" -} - -module "foo" { - source = "./foo" -} diff --git a/config/module/testdata/registry-load/main.tf b/config/module/testdata/registry-load/main.tf deleted file mode 100644 index 19ce51328..000000000 --- a/config/module/testdata/registry-load/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -module "vault" { - source = "hashicorp/vault/aws" -} diff --git a/config/module/testdata/registry-subdir/main.tf b/config/module/testdata/registry-subdir/main.tf deleted file mode 100644 index 2f008a73b..000000000 --- a/config/module/testdata/registry-subdir/main.tf +++ /dev/null @@ -1,4 +0,0 @@ -module "foo" { - // the mock test registry will redirect this to the local tar file - source = "registry/local/sub//baz" -} diff --git a/config/module/testdata/registry-tar-subdir/foo.tgz b/config/module/testdata/registry-tar-subdir/foo.tgz deleted file mode 100644 index 7ea938b7b3d689b9463009f22ee76ab1f6f8b47e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 236 zcmV9?wF=3 z0z?2IgAnhtnT-|Aw)=O_#bcYz%y%wxTz9-gm_R z5zJ=tx9}=|Q*)VUqJCcZ=lSmrtMP6vMV!8n`&^>oF!sx}+(=PAErue0$bY*_r1HG~ m)9ru{-~XHaZ$Ulp9{>OV000000001h&w2zDNG!GhC;$MV9(o@D diff --git a/config/module/testdata/registry-tar-subdir/main.tf b/config/module/testdata/registry-tar-subdir/main.tf deleted file mode 100644 index 660f23764..000000000 --- a/config/module/testdata/registry-tar-subdir/main.tf +++ /dev/null @@ -1,4 +0,0 @@ -module "foo" { - // the mock test registry will redirect this to the local tar file - source = "registry/local/sub" -} diff --git a/config/module/testdata/tar-subdir-to-parent/foo.tgz b/config/module/testdata/tar-subdir-to-parent/foo.tgz deleted file mode 100644 index 62125bf1a1259dc01162c56f2d29a1fe0392263b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235 zcmV" for the root -// tree and then the module name given for any children. -func (t *Tree) Name() string { - if t.name == "" { - return RootName - } - - return t.name -} - -// Load loads the configuration of the entire tree. -// -// The parameters are used to tell the tree where to find modules and -// whether it can download/update modules along the way. -// -// Calling this multiple times will reload the tree. -// -// Various semantic-like checks are made along the way of loading since -// module trees inherently require the configuration to be in a reasonably -// sane state: no circular dependencies, proper module sources, etc. A full -// suite of validations can be done by running Validate (after loading). -func (t *Tree) Load(s *Storage) error { - t.lock.Lock() - defer t.lock.Unlock() - - children, err := t.getChildren(s) - if err != nil { - return err - } - - // Go through all the children and load them. - for _, c := range children { - if err := c.Load(s); err != nil { - return err - } - } - - // Set our tree up - t.children = children - - return nil -} - -func (t *Tree) getChildren(s *Storage) (map[string]*Tree, error) { - children := make(map[string]*Tree) - - // Go through all the modules and get the directory for them. - for _, m := range t.Modules() { - if _, ok := children[m.Name]; ok { - return nil, fmt.Errorf( - "module %s: duplicated. module names must be unique", m.Name) - } - - // Determine the path to this child - modPath := make([]string, len(t.path), len(t.path)+1) - copy(modPath, t.path) - modPath = append(modPath, m.Name) - - log.Printf("[TRACE] module source: %q", m.Source) - - // add the module path to help indicate where modules with relative - // paths are being loaded from - s.output(fmt.Sprintf("- module.%s", strings.Join(modPath, "."))) - - // Lookup the local location of the module. - // dir is the local directory where the module is stored - mod, err := s.findRegistryModule(m.Source, m.Version) - if err != nil { - return nil, err - } - - // The key is the string that will be used to uniquely id the Source in - // the local storage. The prefix digit can be incremented to - // invalidate the local module storage. - key := "1." + t.versionedPathKey(m) - if mod.Version != "" { - key += "." + mod.Version - } - - // Check for the exact key if it's not a registry module - if !mod.registry { - mod.Dir, err = s.findModule(key) - if err != nil { - return nil, err - } - } - - if mod.Dir != "" && s.Mode != GetModeUpdate { - // We found it locally, but in order to load the Tree we need to - // find out if there was another subDir stored from detection. - subDir, err := s.getModuleRoot(mod.Dir) - if err != nil { - // If there's a problem with the subdir record, we'll let the - // recordSubdir method fix it up. Any other filesystem errors - // will turn up again below. - log.Println("[WARN] error reading subdir record:", err) - } - - fullDir := filepath.Join(mod.Dir, subDir) - - child, err := NewTreeModule(m.Name, fullDir) - if err != nil { - return nil, fmt.Errorf("module %s: %s", m.Name, err) - } - child.path = modPath - child.parent = t - child.version = mod.Version - child.source = m.Source - children[m.Name] = child - continue - } - - // Split out the subdir if we have one. - // Terraform keeps the entire requested tree, so that modules can - // reference sibling modules from the same archive or repo. - rawSource, subDir := getter.SourceDirSubdir(m.Source) - - // we haven't found a source, so fallback to the go-getter detectors - source := mod.url - if source == "" { - source, err = getter.Detect(rawSource, t.config.Dir, getter.Detectors) - if err != nil { - return nil, fmt.Errorf("module %s: %s", m.Name, err) - } - } - - log.Printf("[TRACE] detected module source %q", source) - - // Check if the detector introduced something new. - // For example, the registry always adds a subdir of `//*`, - // indicating that we need to strip off the first component from the - // tar archive, though we may not yet know what it is called. - source, detectedSubDir := getter.SourceDirSubdir(source) - if detectedSubDir != "" { - subDir = filepath.Join(detectedSubDir, subDir) - } - - output := "" - switch s.Mode { - case GetModeUpdate: - output = fmt.Sprintf(" Updating source %q", m.Source) - default: - output = fmt.Sprintf(" Getting source %q", m.Source) - } - s.output(output) - - dir, ok, err := s.getStorage(key, source) - if err != nil { - return nil, err - } - if !ok { - return nil, fmt.Errorf("module %s: not found, may need to run 'terraform init'", m.Name) - } - - log.Printf("[TRACE] %q stored in %q", source, dir) - - // expand and record the subDir for later - fullDir := dir - if subDir != "" { - fullDir, err = getter.SubdirGlob(dir, subDir) - if err != nil { - return nil, err - } - - // +1 to account for the pathsep - if len(dir)+1 > len(fullDir) { - return nil, fmt.Errorf("invalid module storage path %q", fullDir) - } - subDir = fullDir[len(dir)+1:] - } - - // add new info to the module record - mod.Key = key - mod.Dir = dir - mod.Root = subDir - - // record the module in our manifest - if err := s.recordModule(mod); err != nil { - return nil, err - } - - child, err := NewTreeModule(m.Name, fullDir) - if err != nil { - return nil, fmt.Errorf("module %s: %s", m.Name, err) - } - child.path = modPath - child.parent = t - child.version = mod.Version - child.source = m.Source - children[m.Name] = child - } - - return children, nil -} - -// Path is the full path to this tree. -func (t *Tree) Path() []string { - return t.path -} - -// String gives a nice output to describe the tree. -func (t *Tree) String() string { - var result bytes.Buffer - path := strings.Join(t.path, ", ") - if path != "" { - path = fmt.Sprintf(" (path: %s)", path) - } - result.WriteString(t.Name() + path + "\n") - - cs := t.Children() - if cs == nil { - result.WriteString(" not loaded") - } else { - // Go through each child and get its string value, then indent it - // by two. - for _, c := range cs { - r := strings.NewReader(c.String()) - scanner := bufio.NewScanner(r) - for scanner.Scan() { - result.WriteString(" ") - result.WriteString(scanner.Text()) - result.WriteString("\n") - } - } - } - - return result.String() -} - -// Validate does semantic checks on the entire tree of configurations. -// -// This will call the respective config.Config.Validate() functions as well -// as verifying things such as parameters/outputs between the various modules. -// -// Load must be called prior to calling Validate or an error will be returned. -func (t *Tree) Validate() tfdiags.Diagnostics { - var diags tfdiags.Diagnostics - - if !t.Loaded() { - diags = diags.Append(fmt.Errorf( - "tree must be loaded before calling Validate", - )) - return diags - } - - // Terraform core does not handle root module children named "root". - // We plan to fix this in the future but this bug was brought up in - // the middle of a release and we don't want to introduce wide-sweeping - // changes at that time. - if len(t.path) == 1 && t.name == "root" { - diags = diags.Append(fmt.Errorf( - "root module cannot contain module named 'root'", - )) - return diags - } - - // Validate our configuration first. - diags = diags.Append(t.config.Validate()) - - // If we're the root, we do extra validation. This validation usually - // requires the entire tree (since children don't have parent pointers). - if len(t.path) == 0 { - if err := t.validateProviderAlias(); err != nil { - diags = diags.Append(err) - } - } - - // Get the child trees - children := t.Children() - - // Validate all our children - for _, c := range children { - childDiags := c.Validate() - diags = diags.Append(childDiags) - if diags.HasErrors() { - continue - } - } - - // Go over all the modules and verify that any parameters are valid - // variables into the module in question. - for _, m := range t.config.Modules { - tree, ok := children[m.Name] - if !ok { - // This should never happen because Load watches us - panic("module not found in children: " + m.Name) - } - - // Build the variables that the module defines - requiredMap := make(map[string]struct{}) - varMap := make(map[string]struct{}) - for _, v := range tree.config.Variables { - varMap[v.Name] = struct{}{} - - if v.Required() { - requiredMap[v.Name] = struct{}{} - } - } - - // Compare to the keys in our raw config for the module - for k, _ := range m.RawConfig.Raw { - if _, ok := varMap[k]; !ok { - diags = diags.Append(fmt.Errorf( - "module %q: %q is not a valid argument", - m.Name, k, - )) - } - - // Remove the required - delete(requiredMap, k) - } - - // If we have any required left over, they aren't set. - for k, _ := range requiredMap { - diags = diags.Append(fmt.Errorf( - "module %q: missing required argument %q", - m.Name, k, - )) - } - } - - // Go over all the variables used and make sure that any module - // variables represent outputs properly. - for source, vs := range t.config.InterpolatedVariables() { - for _, v := range vs { - mv, ok := v.(*config.ModuleVariable) - if !ok { - continue - } - - tree, ok := children[mv.Name] - if !ok { - diags = diags.Append(fmt.Errorf( - "%s: reference to undefined module %q", - source, mv.Name, - )) - continue - } - - found := false - for _, o := range tree.config.Outputs { - if o.Name == mv.Field { - found = true - break - } - } - if !found { - diags = diags.Append(fmt.Errorf( - "%s: %q is not a valid output for module %q", - source, mv.Field, mv.Name, - )) - } - } - } - - return diags -} - -// versionedPathKey returns a path string with every levels full name, version -// and source encoded. This is to provide a unique key for our module storage, -// since submodules need to know which versions of their ancestor modules they -// are loaded from. -// For example, if module A has a subdirectory B, if module A's source or -// version is updated B's storage key must reflect this change in order for the -// correct version of B's source to be loaded. -func (t *Tree) versionedPathKey(m *Module) string { - path := make([]string, len(t.path)+1) - path[len(path)-1] = m.Name + ";" + m.Source - // We're going to load these in order for easier reading and debugging, but - // in practice they only need to be unique and consistent. - - p := t - i := len(path) - 2 - for ; i >= 0; i-- { - if p == nil { - break - } - // we may have been loaded under a blank Tree, so always check for a name - // too. - if p.name == "" { - break - } - seg := p.name - if p.version != "" { - seg += "#" + p.version - } - - if p.source != "" { - seg += ";" + p.source - } - - path[i] = seg - p = p.parent - } - - key := strings.Join(path, "|") - return key -} - -// treeError is an error use by Tree.Validate to accumulates all -// validation errors. -type treeError struct { - Name []string - Errs []error - Children []*treeError -} - -func (e *treeError) Add(err error) { - e.Errs = append(e.Errs, err) -} - -func (e *treeError) AddChild(err *treeError) { - e.Children = append(e.Children, err) -} - -func (e *treeError) ErrOrNil() error { - if len(e.Errs) > 0 || len(e.Children) > 0 { - return e - } - return nil -} - -func (e *treeError) Error() string { - name := strings.Join(e.Name, ".") - var out bytes.Buffer - fmt.Fprintf(&out, "module %s: ", name) - - if len(e.Errs) == 1 { - // single like error - out.WriteString(e.Errs[0].Error()) - } else { - // multi-line error - for _, err := range e.Errs { - fmt.Fprintf(&out, "\n %s", err) - } - } - - if len(e.Children) > 0 { - // start the next error on a new line - out.WriteString("\n ") - } - for _, child := range e.Children { - out.WriteString(child.Error()) - } - - return out.String() -} diff --git a/config/module/tree_gob.go b/config/module/tree_gob.go deleted file mode 100644 index fcd37f4e7..000000000 --- a/config/module/tree_gob.go +++ /dev/null @@ -1,57 +0,0 @@ -package module - -import ( - "bytes" - "encoding/gob" - - "github.com/hashicorp/terraform/config" -) - -func (t *Tree) GobDecode(bs []byte) error { - t.lock.Lock() - defer t.lock.Unlock() - - // Decode the gob data - var data treeGob - dec := gob.NewDecoder(bytes.NewReader(bs)) - if err := dec.Decode(&data); err != nil { - return err - } - - // Set the fields - t.name = data.Name - t.config = data.Config - t.children = data.Children - t.path = data.Path - - return nil -} - -func (t *Tree) GobEncode() ([]byte, error) { - data := &treeGob{ - Config: t.config, - Children: t.children, - Name: t.name, - Path: t.path, - } - - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - if err := enc.Encode(data); err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -// treeGob is used as a structure to Gob encode a tree. -// -// This structure is private so it can't be referenced but the fields are -// public, allowing Gob to properly encode this. When we decode this, we are -// able to turn it into a Tree. -type treeGob struct { - Config *config.Config - Children map[string]*Tree - Name string - Path []string -} diff --git a/config/module/tree_gob_test.go b/config/module/tree_gob_test.go deleted file mode 100644 index 1d2d7d5b5..000000000 --- a/config/module/tree_gob_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package module - -import ( - "bytes" - "encoding/gob" - "strings" - "testing" -) - -func TestTreeEncodeDecodeGob(t *testing.T) { - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, "basic")) - - // This should get things - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - // Encode it. - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - if err := enc.Encode(tree); err != nil { - t.Fatalf("err: %s", err) - } - - dec := gob.NewDecoder(&buf) - var actual Tree - if err := dec.Decode(&actual); err != nil { - t.Fatalf("err: %s", err) - } - - actualStr := strings.TrimSpace(actual.String()) - expectedStr := strings.TrimSpace(tree.String()) - if actualStr != expectedStr { - t.Fatalf("\n%s\n\nexpected:\n\n%s", actualStr, expectedStr) - } -} diff --git a/config/module/tree_test.go b/config/module/tree_test.go deleted file mode 100644 index 5c642962f..000000000 --- a/config/module/tree_test.go +++ /dev/null @@ -1,675 +0,0 @@ -package module - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/hashicorp/terraform/config" - "github.com/hashicorp/terraform/helper/copy" -) - -func TestTreeChild(t *testing.T) { - var nilTree *Tree - if nilTree.Child(nil) != nil { - t.Fatal("child should be nil") - } - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - tree := NewTree("", testConfig(t, "child")) - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - // Should be able to get the root child - if c := tree.Child([]string{}); c == nil { - t.Fatal("should not be nil") - } else if c.Name() != "root" { - t.Fatalf("bad: %#v", c.Name()) - } else if !reflect.DeepEqual(c.Path(), []string(nil)) { - t.Fatalf("bad: %#v", c.Path()) - } - - // Should be able to get the root child - if c := tree.Child(nil); c == nil { - t.Fatal("should not be nil") - } else if c.Name() != "root" { - t.Fatalf("bad: %#v", c.Name()) - } else if !reflect.DeepEqual(c.Path(), []string(nil)) { - t.Fatalf("bad: %#v", c.Path()) - } - - // Should be able to get the foo child - if c := tree.Child([]string{"foo"}); c == nil { - t.Fatal("should not be nil") - } else if c.Name() != "foo" { - t.Fatalf("bad: %#v", c.Name()) - } else if !reflect.DeepEqual(c.Path(), []string{"foo"}) { - t.Fatalf("bad: %#v", c.Path()) - } - - // Should be able to get the nested child - if c := tree.Child([]string{"foo", "bar"}); c == nil { - t.Fatal("should not be nil") - } else if c.Name() != "bar" { - t.Fatalf("bad: %#v", c.Name()) - } else if !reflect.DeepEqual(c.Path(), []string{"foo", "bar"}) { - t.Fatalf("bad: %#v", c.Path()) - } -} - -func TestTreeLoad(t *testing.T) { - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, "basic")) - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should error because we haven't gotten things yet - if err := tree.Load(storage); err == nil { - t.Fatal("should error") - } - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should get things - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - // This should no longer error - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - actual := strings.TrimSpace(tree.String()) - expected := strings.TrimSpace(treeLoadStr) - if actual != expected { - t.Fatalf("bad: \n\n%s", actual) - } -} - -func TestTreeLoad_duplicate(t *testing.T) { - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, "dup")) - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should get things - storage.Mode = GetModeGet - if err := tree.Load(storage); err == nil { - t.Fatalf("should error") - } -} - -func TestTreeLoad_copyable(t *testing.T) { - dir := tempDir(t) - storage := &Storage{ - StorageDir: dir, - Mode: GetModeGet, - } - cfg := testConfig(t, "basic") - tree := NewTree("", cfg) - - // This should get things - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - // This should no longer error - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - // Now we copy the directory, this COPIES symlink values, and - // doesn't create symlinks themselves. That is important. - dir2 := tempDir(t) - os.RemoveAll(dir2) - defer os.RemoveAll(dir2) - if err := copy.CopyDir(dir, dir2); err != nil { - t.Fatalf("err: %s", err) - } - - // Now copy the configuration - cfgDir := tempDir(t) - os.RemoveAll(cfgDir) - defer os.RemoveAll(cfgDir) - if err := copy.CopyDir(cfg.Dir, cfgDir); err != nil { - t.Fatalf("err: %s", err) - } - - { - cfg, err := config.LoadDir(cfgDir) - if err != nil { - t.Fatalf("err: %s", err) - } - - tree := NewTree("", cfg) - storage := &Storage{ - StorageDir: dir2, - Mode: GetModeNone, - } - - // This should not error since we already got it! - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - } -} - -func TestTreeLoad_parentRef(t *testing.T) { - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, "basic-parent")) - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should error because we haven't gotten things yet - storage.Mode = GetModeNone - if err := tree.Load(storage); err == nil { - t.Fatal("should error") - } - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should get things - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - // This should no longer error - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - actual := strings.TrimSpace(tree.String()) - expected := strings.TrimSpace(treeLoadParentStr) - if actual != expected { - t.Fatalf("bad: \n\n%s", actual) - } -} - -func TestTreeLoad_subdir(t *testing.T) { - fixtures := []string{ - "basic-subdir", - "basic-tar-subdir", - "tar-subdir-to-parent", - } - - for _, tc := range fixtures { - t.Run(tc, func(t *testing.T) { - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, tc)) - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should error because we haven't gotten things yet - storage.Mode = GetModeNone - if err := tree.Load(storage); err == nil { - t.Fatal("should error") - } - - if tree.Loaded() { - t.Fatal("should not be loaded") - } - - // This should get things - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - // This should no longer error - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - actual := strings.TrimSpace(tree.String()) - expected := strings.TrimSpace(treeLoadSubdirStr) - if actual != expected { - t.Fatalf("bad: \n\n%s", actual) - } - }) - } -} - -func TestTree_recordManifest(t *testing.T) { - td, err := ioutil.TempDir("", "tf-module") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) - - storage := Storage{StorageDir: td} - - dir := filepath.Join(td, "0131bf0fef686e090b16bdbab4910ddf") - - subDir := "subDirName" - - // record and read the subdir path - if err := storage.recordModuleRoot(dir, subDir); err != nil { - t.Fatal(err) - } - actual, err := storage.getModuleRoot(dir) - if err != nil { - t.Fatal(err) - } - - if actual != subDir { - t.Fatalf("expected subDir %q, got %q", subDir, actual) - } - - // overwrite the path, and nmake sure we get the new one - subDir = "newSubDir" - if err := storage.recordModuleRoot(dir, subDir); err != nil { - t.Fatal(err) - } - actual, err = storage.getModuleRoot(dir) - if err != nil { - t.Fatal(err) - } - - if actual != subDir { - t.Fatalf("expected subDir %q, got %q", subDir, actual) - } - - // create a fake entry - if err := ioutil.WriteFile(filepath.Join(td, manifestName), []byte("BAD DATA"), 0644); err != nil { - t.Fatal(err) - } - - // this should fail because there aare now 2 entries - actual, err = storage.getModuleRoot(dir) - if err == nil { - t.Fatal("expected multiple subdir entries") - } - - // writing the subdir entry should remove the incorrect value - if err := storage.recordModuleRoot(dir, subDir); err != nil { - t.Fatal(err) - } - actual, err = storage.getModuleRoot(dir) - if err != nil { - t.Fatal(err) - } - - if actual != subDir { - t.Fatalf("expected subDir %q, got %q", subDir, actual) - } -} - -func TestTreeModules(t *testing.T) { - tree := NewTree("", testConfig(t, "basic")) - actual := tree.Modules() - - expected := []*Module{ - &Module{Name: "foo", Source: "./foo"}, - } - - if !reflect.DeepEqual(actual, expected) { - t.Fatalf("bad: %#v", actual) - } -} - -func TestTreeName(t *testing.T) { - tree := NewTree("", testConfig(t, "basic")) - actual := tree.Name() - - if actual != RootName { - t.Fatalf("bad: %#v", actual) - } -} - -// This is a table-driven test for tree validation. This is the preferred -// way to test Validate. Non table-driven tests exist historically but -// that style shouldn't be done anymore. -func TestTreeValidate_table(t *testing.T) { - cases := []struct { - Name string - Fixture string - Err string - }{ - { - "provider alias in child", - "validate-alias-good", - "", - }, - - { - "undefined provider alias in child", - "validate-alias-bad", - "alias must be defined", - }, - - { - "root module named root", - "validate-module-root", - "cannot contain module", - }, - - { - "grandchild module named root", - "validate-module-root-grandchild", - "", - }, - } - - for i, tc := range cases { - t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { - tree := NewTree("", testConfig(t, tc.Fixture)) - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - diags := tree.Validate() - if (diags.HasErrors()) != (tc.Err != "") { - t.Fatalf("err: %s", diags.Err()) - } - if len(diags) == 0 { - return - } - if !strings.Contains(diags.Err().Error(), tc.Err) { - t.Fatalf("err should contain %q: %s", tc.Err, diags.Err().Error()) - } - }) - } -} - -func TestTreeValidate_badChild(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-child-bad")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeValidate_badChildOutput(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-bad-output")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeValidate_badChildOutputToModule(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-bad-output-to-module")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeValidate_badChildVar(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-bad-var")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeValidate_badRoot(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-root-bad")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeValidate_good(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-child-good")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestTreeValidate_notLoaded(t *testing.T) { - tree := NewTree("", testConfig(t, "basic")) - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeValidate_requiredChildVar(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-required-var")) - - storage := testStorage(t, nil) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - diags := tree.Validate() - if !diags.HasErrors() { - t.Fatal("should error") - } - - // ensure both variables are mentioned in the output - errMsg := diags.Err().Error() - for _, v := range []string{"feature", "memory"} { - if !strings.Contains(errMsg, v) { - t.Fatalf("no mention of missing variable %q", v) - } - } -} - -func TestTreeValidate_unknownModule(t *testing.T) { - tree := NewTree("", testConfig(t, "validate-module-unknown")) - - storage := testStorage(t, nil) - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("err: %s", err) - } - - if err := tree.Validate(); err == nil { - t.Fatal("should error") - } -} - -func TestTreeLoad_conflictingSubmoduleNames(t *testing.T) { - storage := testStorage(t, nil) - tree := NewTree("", testConfig(t, "conficting-submodule-names")) - - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("load failed: %s", err) - } - - if !tree.Loaded() { - t.Fatal("should be loaded") - } - - // Try to reload - storage.Mode = GetModeNone - if err := tree.Load(storage); err != nil { - t.Fatalf("reload failed: %s", err) - } - - // verify that the grand-children are correctly loaded - for _, c := range tree.Children() { - for _, gc := range c.Children() { - if len(gc.config.Resources) != 1 { - t.Fatalf("expected 1 resource in %s, got %d", gc.name, len(gc.config.Resources)) - } - res := gc.config.Resources[0] - switch gc.path[0] { - case "a": - if res.Name != "a-c" { - t.Fatal("found wrong resource in a/c:", res.Name) - } - case "b": - if res.Name != "b-c" { - t.Fatal("found wrong resource in b/c:", res.Name) - } - } - } - } -} - -// changing the source for a module but not the module "path" -func TestTreeLoad_changeIntermediateSource(t *testing.T) { - // copy the config to our tempdir this time, since we're going to edit it - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(td) - - if err := copyDir(td, filepath.Join(fixtureDir, "change-intermediate-source")); err != nil { - t.Fatal(err) - } - - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(td); err != nil { - t.Fatal(err) - } - defer os.Chdir(wd) - - if err := os.MkdirAll(".terraform/modules", 0777); err != nil { - t.Fatal(err) - } - storage := &Storage{StorageDir: ".terraform/modules"} - cfg, err := config.LoadDir("./") - if err != nil { - t.Fatal(err) - } - tree := NewTree("", cfg) - storage.Mode = GetModeGet - if err := tree.Load(storage); err != nil { - t.Fatalf("load failed: %s", err) - } - - // now we change the source of our module, without changing its path - if err := os.Rename("main.tf.disabled", "main.tf"); err != nil { - t.Fatal(err) - } - - // reload the tree - cfg, err = config.LoadDir("./") - if err != nil { - t.Fatal(err) - } - tree = NewTree("", cfg) - if err := tree.Load(storage); err != nil { - t.Fatalf("load failed: %s", err) - } - - // check for our resource in b - for _, c := range tree.Children() { - for _, gc := range c.Children() { - if len(gc.config.Resources) != 1 { - t.Fatalf("expected 1 resource in %s, got %d", gc.name, len(gc.config.Resources)) - } - res := gc.config.Resources[0] - expected := "c-b" - if res.Name != expected { - t.Fatalf("expexted resource %q, got %q", expected, res.Name) - } - } - } -} - -const treeLoadStr = ` -root - foo (path: foo) -` - -const treeLoadParentStr = ` -root - a (path: a) - b (path: a, b) -` -const treeLoadSubdirStr = ` -root - foo (path: foo) - bar (path: foo, bar) -` - -const treeLoadRegistrySubdirStr = ` -root - foo (path: foo) -` diff --git a/config/module/validate_provider_alias.go b/config/module/validate_provider_alias.go deleted file mode 100644 index f203556c1..000000000 --- a/config/module/validate_provider_alias.go +++ /dev/null @@ -1,118 +0,0 @@ -package module - -import ( - "fmt" - "strings" - - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform/dag" -) - -// validateProviderAlias validates that all provider alias references are -// defined at some point in the parent tree. This improves UX by catching -// alias typos at the slight cost of requiring a declaration of usage. This -// is usually a good tradeoff since not many aliases are used. -func (t *Tree) validateProviderAlias() error { - // If we're not the root, don't perform this validation. We must be the - // root since we require full tree visibilty. - if len(t.path) != 0 { - return nil - } - - // We'll use a graph to keep track of defined aliases at each level. - // As long as a parent defines an alias, it is okay. - var g dag.AcyclicGraph - t.buildProviderAliasGraph(&g, nil) - - // Go through the graph and check that the usage is all good. - var err error - for _, v := range g.Vertices() { - pv, ok := v.(*providerAliasVertex) - if !ok { - // This shouldn't happen, just ignore it. - continue - } - - // If we're not using any aliases, fast track and just continue - if len(pv.Used) == 0 { - continue - } - - // Grab the ancestors since we're going to have to check if our - // parents define any of our aliases. - var parents []*providerAliasVertex - ancestors, _ := g.Ancestors(v) - for _, raw := range ancestors.List() { - if pv, ok := raw.(*providerAliasVertex); ok { - parents = append(parents, pv) - } - } - for k, _ := range pv.Used { - // Check if we define this - if _, ok := pv.Defined[k]; ok { - continue - } - - // Check for a parent - found := false - for _, parent := range parents { - _, found = parent.Defined[k] - if found { - break - } - } - if found { - continue - } - - // We didn't find the alias, error! - err = multierror.Append(err, fmt.Errorf( - "module %s: provider alias must be defined by the module: %s", - strings.Join(pv.Path, "."), k)) - } - } - - return err -} - -func (t *Tree) buildProviderAliasGraph(g *dag.AcyclicGraph, parent dag.Vertex) { - // Add all our defined aliases - defined := make(map[string]struct{}) - for _, p := range t.config.ProviderConfigs { - defined[p.FullName()] = struct{}{} - } - - // Add all our used aliases - used := make(map[string]struct{}) - for _, r := range t.config.Resources { - if r.Provider != "" { - used[r.Provider] = struct{}{} - } - } - - // Add it to the graph - vertex := &providerAliasVertex{ - Path: t.Path(), - Defined: defined, - Used: used, - } - g.Add(vertex) - - // Connect to our parent if we have one - if parent != nil { - g.Connect(dag.BasicEdge(vertex, parent)) - } - - // Build all our children - for _, c := range t.Children() { - c.buildProviderAliasGraph(g, vertex) - } -} - -// providerAliasVertex is the vertex for the graph that keeps track of -// defined provider aliases. -type providerAliasVertex struct { - Path []string - Defined map[string]struct{} - Used map[string]struct{} -} diff --git a/config/module/versions.go b/config/module/versions.go deleted file mode 100644 index 29701b931..000000000 --- a/config/module/versions.go +++ /dev/null @@ -1,129 +0,0 @@ -package module - -import ( - "errors" - "fmt" - "regexp" - "sort" - "strings" - - version "github.com/hashicorp/go-version" - "github.com/hashicorp/terraform/registry/response" -) - -const anyVersion = ">=0.0.0" - -var explicitEqualityConstraint = regexp.MustCompile("^=[0-9]") - -// return the newest version that satisfies the provided constraint -func newest(versions []string, constraint string) (string, error) { - if constraint == "" { - constraint = anyVersion - } - cs, err := version.NewConstraint(constraint) - if err != nil { - return "", err - } - - // Find any build metadata in the constraints, and - // store whether the constraint is an explicit equality that - // contains a build metadata requirement, so we can return a specific, - // if requested, build metadata version - var constraintMetas []string - var equalsConstraint bool - for i := range cs { - constraintMeta := strings.SplitAfterN(cs[i].String(), "+", 2) - if len(constraintMeta) > 1 { - constraintMetas = append(constraintMetas, constraintMeta[1]) - } - } - - if len(cs) == 1 { - equalsConstraint = explicitEqualityConstraint.MatchString(cs.String()) - } - - // If the version string includes metadata, this is valid in go-version, - // However, it's confusing as to what expected behavior should be, - // so give an error so the user can do something more logical - if (len(cs) > 1 || !equalsConstraint) && len(constraintMetas) > 0 { - return "", fmt.Errorf("Constraints including build metadata must have explicit equality, or are otherwise too ambiguous: %s", cs.String()) - } - - switch len(versions) { - case 0: - return "", errors.New("no versions found") - case 1: - v, err := version.NewVersion(versions[0]) - if err != nil { - return "", err - } - - if !cs.Check(v) { - return "", fmt.Errorf("no version found matching constraint %q", constraint) - } - return versions[0], nil - } - - sort.Slice(versions, func(i, j int) bool { - // versions should have already been validated - // sort invalid version strings to the end - iv, err := version.NewVersion(versions[i]) - if err != nil { - return true - } - jv, err := version.NewVersion(versions[j]) - if err != nil { - return true - } - return iv.GreaterThan(jv) - }) - - // versions are now in order, so just find the first which satisfies the - // constraint - for i := range versions { - v, err := version.NewVersion(versions[i]) - if err != nil { - continue - } - if cs.Check(v) { - // Constraint has metadata and is explicit equality - if equalsConstraint && len(constraintMetas) > 0 { - if constraintMetas[0] != v.Metadata() { - continue - } - } - return versions[i], nil - } - } - - return "", nil -} - -// return the newest *moduleVersion that matches the given constraint -// TODO: reconcile these two types and newest* functions -func newestVersion(moduleVersions []*response.ModuleVersion, constraint string) (*response.ModuleVersion, error) { - var versions []string - modules := make(map[string]*response.ModuleVersion) - - for _, m := range moduleVersions { - versions = append(versions, m.Version) - modules[m.Version] = m - } - - match, err := newest(versions, constraint) - return modules[match], err -} - -// return the newest moduleRecord that matches the given constraint -func newestRecord(moduleVersions []moduleRecord, constraint string) (moduleRecord, error) { - var versions []string - modules := make(map[string]moduleRecord) - - for _, m := range moduleVersions { - versions = append(versions, m.Version) - modules[m.Version] = m - } - - match, err := newest(versions, constraint) - return modules[match], err -} diff --git a/config/module/versions_test.go b/config/module/versions_test.go deleted file mode 100644 index a9d4941eb..000000000 --- a/config/module/versions_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package module - -import ( - "testing" - - "github.com/hashicorp/terraform/registry/response" -) - -func TestNewestModuleVersion(t *testing.T) { - mpv := &response.ModuleProviderVersions{ - Source: "registry/test/module", - Versions: []*response.ModuleVersion{ - {Version: "0.0.4"}, - {Version: "0.3.1"}, - {Version: "2.0.1"}, - {Version: "1.2.0"}, - }, - } - - m, err := newestVersion(mpv.Versions, "") - if err != nil { - t.Fatal(err) - } - - expected := "2.0.1" - if m.Version != expected { - t.Fatalf("expected version %q, got %q", expected, m.Version) - } - - // now with a constraint - m, err = newestVersion(mpv.Versions, "~>1.0") - if err != nil { - t.Fatal(err) - } - - expected = "1.2.0" - if m.Version != expected { - t.Fatalf("expected version %q, got %q", expected, m.Version) - } -} - -func TestNewestInvalidModuleVersion(t *testing.T) { - mpv := &response.ModuleProviderVersions{ - Source: "registry/test/module", - Versions: []*response.ModuleVersion{ - {Version: "WTF"}, - {Version: "2.0.1"}, - }, - } - - m, err := newestVersion(mpv.Versions, "") - if err != nil { - t.Fatal(err) - } - - expected := "2.0.1" - if m.Version != expected { - t.Fatalf("expected version %q, got %q", expected, m.Version) - } -} - -func TestNewestModulesWithMetadata(t *testing.T) { - mpv := &response.ModuleProviderVersions{ - Source: "registry/test/module", - Versions: []*response.ModuleVersion{ - {Version: "0.9.0"}, - {Version: "0.9.0+def"}, - {Version: "0.9.0+abc"}, - {Version: "0.9.0+xyz"}, - }, - } - - // with metadata and explicit version request - expected := "0.9.0+def" - m, _ := newestVersion(mpv.Versions, "=0.9.0+def") - if m.Version != expected { - t.Fatalf("expected version %q, got %q", expected, m.Version) - } - - // respect explicit equality, but >/0.9.0+abc") - if err == nil { - t.Fatalf("expected an error, but did not get one") - } - - _, err = newestVersion(mpv.Versions, ">0.8.0+abc, <1.0.0") - if err == nil { - t.Fatalf("expected an error, but did not get one") - } -} diff --git a/flatmap/expand.go b/flatmap/expand.go index 1449065e9..b9d15461e 100644 --- a/flatmap/expand.go +++ b/flatmap/expand.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/hashicorp/hil" + "github.com/hashicorp/terraform/configs/hcl2shim" ) // Expand takes a map and a key (prefix) and expands that value into @@ -28,7 +28,7 @@ func Expand(m map[string]string, key string) interface{} { // If the count of the key is unknown, then just put the unknown // value in the value itself. This will be detected by Terraform // core later. - if v == hil.UnknownValue { + if v == hcl2shim.UnknownVariableValue { return v } diff --git a/flatmap/expand_test.go b/flatmap/expand_test.go index a64eb9c54..707c015da 100644 --- a/flatmap/expand_test.go +++ b/flatmap/expand_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/hashicorp/hil" + "github.com/hashicorp/terraform/configs/hcl2shim" ) func TestExpand(t *testing.T) { @@ -171,13 +171,13 @@ func TestExpand(t *testing.T) { Map: map[string]string{ "struct.#": "1", "struct.0.name": "hello", - "struct.0.rules.#": hil.UnknownValue, + "struct.0.rules.#": hcl2shim.UnknownVariableValue, }, Key: "struct", Output: []interface{}{ map[string]interface{}{ "name": "hello", - "rules": hil.UnknownValue, + "rules": hcl2shim.UnknownVariableValue, }, }, }, diff --git a/helper/schema/provider.go b/helper/schema/provider.go index 97024479d..9efc90e7b 100644 --- a/helper/schema/provider.go +++ b/helper/schema/provider.go @@ -8,11 +8,15 @@ import ( "sync" "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/terraform" ) +var ReservedProviderFields = []string{ + "alias", + "version", +} + // Provider represents a resource provider in Terraform, and properly // implements all of the ResourceProvider API. // @@ -116,7 +120,7 @@ func (p *Provider) InternalValidate() error { } func isReservedProviderFieldName(name string) bool { - for _, reservedName := range config.ReservedProviderFields { + for _, reservedName := range ReservedProviderFields { if name == reservedName { return true } diff --git a/helper/schema/resource.go b/helper/schema/resource.go index b59e4e82e..8cd2703aa 100644 --- a/helper/schema/resource.go +++ b/helper/schema/resource.go @@ -6,11 +6,29 @@ import ( "log" "strconv" - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/terraform" "github.com/zclconf/go-cty/cty" ) +var ReservedDataSourceFields = []string{ + "connection", + "count", + "depends_on", + "lifecycle", + "provider", + "provisioner", +} + +var ReservedResourceFields = []string{ + "connection", + "count", + "depends_on", + "id", + "lifecycle", + "provider", + "provisioner", +} + // Resource represents a thing in Terraform that has a set of configurable // attributes and a lifecycle (create, read, update, delete). // @@ -682,7 +700,7 @@ func (r *Resource) InternalValidate(topSchemaMap schemaMap, writable bool) error } func isReservedDataSourceFieldName(name string) bool { - for _, reservedName := range config.ReservedDataSourceFields { + for _, reservedName := range ReservedDataSourceFields { if name == reservedName { return true } @@ -697,7 +715,7 @@ func isReservedResourceFieldName(name string, s *Schema) bool { return false } - for _, reservedName := range config.ReservedResourceFields { + for _, reservedName := range ReservedResourceFields { if name == reservedName { return true } diff --git a/terraform/context.go b/terraform/context.go index afdba99c1..065cf9295 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -5,14 +5,9 @@ import ( "context" "fmt" "log" - "strings" "sync" - "github.com/hashicorp/hcl" - "github.com/zclconf/go-cty/cty" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" @@ -21,6 +16,7 @@ import ( "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states/statefile" "github.com/hashicorp/terraform/tfdiags" + "github.com/zclconf/go-cty/cty" ) // InputMode defines what sort of input will be asked for when Input @@ -415,14 +411,6 @@ func (c *Context) Eval(path addrs.ModuleInstance) (*lang.Scope, tfdiags.Diagnost return evalCtx.EvaluationScope(nil, EvalDataForNoInstanceKey), diags } -// Interpolater is no longer used. Use Evaluator instead. -// -// The interpolator returned from this function will return an error on any use. -func (c *Context) Interpolater() *Interpolater { - // FIXME: Remove this once all callers are updated to no longer use it. - return &Interpolater{} -} - // Apply applies the changes represented by this context and returns // the resulting state. // @@ -850,59 +838,6 @@ func (c *Context) watchStop(walker *ContextGraphWalker) (chan struct{}, <-chan s return stop, wait } -// parseVariableAsHCL parses the value of a single variable as would have been specified -// on the command line via -var or in an environment variable named TF_VAR_x, where x is -// the name of the variable. In order to get around the restriction of HCL requiring a -// top level object, we prepend a sentinel key, decode the user-specified value as its -// value and pull the value back out of the resulting map. -func parseVariableAsHCL(name string, input string, targetType config.VariableType) (interface{}, error) { - // expecting a string so don't decode anything, just strip quotes - if targetType == config.VariableTypeString { - return strings.Trim(input, `"`), nil - } - - // return empty types - if strings.TrimSpace(input) == "" { - switch targetType { - case config.VariableTypeList: - return []interface{}{}, nil - case config.VariableTypeMap: - return make(map[string]interface{}), nil - } - } - - const sentinelValue = "SENTINEL_TERRAFORM_VAR_OVERRIDE_KEY" - inputWithSentinal := fmt.Sprintf("%s = %s", sentinelValue, input) - - var decoded map[string]interface{} - err := hcl.Decode(&decoded, inputWithSentinal) - if err != nil { - return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", name, input, err) - } - - if len(decoded) != 1 { - return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. Only one value may be specified.", name, input) - } - - parsedValue, ok := decoded[sentinelValue] - if !ok { - return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input) - } - - switch targetType { - case config.VariableTypeList: - return parsedValue, nil - case config.VariableTypeMap: - if list, ok := parsedValue.([]map[string]interface{}); ok { - return list[0], nil - } - - return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input) - default: - panic(fmt.Errorf("unknown type %s", targetType.Printable())) - } -} - // ShimLegacyState is a helper that takes the legacy state type and // converts it to the new state type. // diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index c3ce2ce3b..20c6212c6 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -18,8 +18,6 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/go-test/deep" "github.com/google/go-cmp/cmp" - "github.com/zclconf/go-cty/cty" - "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs/configschema" @@ -29,6 +27,7 @@ import ( "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" + "github.com/zclconf/go-cty/cty" ) func TestContext2Apply_basic(t *testing.T) { @@ -3849,33 +3848,33 @@ func TestContext2Apply_multiVarComprehensive(t *testing.T) { } checkConfig("multi_count_var.0", map[string]interface{}{ - "source_id": unknownValue(), + "source_id": hcl2shim.UnknownVariableValue, "source_name": "source.0", }) checkConfig("multi_count_var.2", map[string]interface{}{ - "source_id": unknownValue(), + "source_id": hcl2shim.UnknownVariableValue, "source_name": "source.2", }) checkConfig("multi_count_derived.0", map[string]interface{}{ - "source_id": unknownValue(), + "source_id": hcl2shim.UnknownVariableValue, "source_name": "source.0", }) checkConfig("multi_count_derived.2", map[string]interface{}{ - "source_id": unknownValue(), + "source_id": hcl2shim.UnknownVariableValue, "source_name": "source.2", }) checkConfig("whole_splat", map[string]interface{}{ "source_ids": []interface{}{ - unknownValue(), - unknownValue(), - unknownValue(), + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, }, "source_names": []interface{}{ "source.0", "source.1", "source.2", }, - "source_ids_from_func": unknownValue(), + "source_ids_from_func": hcl2shim.UnknownVariableValue, "source_names_from_func": []interface{}{ "source.0", "source.1", @@ -3884,9 +3883,9 @@ func TestContext2Apply_multiVarComprehensive(t *testing.T) { "source_ids_wrapped": []interface{}{ []interface{}{ - unknownValue(), - unknownValue(), - unknownValue(), + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, }, }, "source_names_wrapped": []interface{}{ @@ -3897,14 +3896,14 @@ func TestContext2Apply_multiVarComprehensive(t *testing.T) { }, }, - "first_source_id": unknownValue(), + "first_source_id": hcl2shim.UnknownVariableValue, "first_source_name": "source.0", }) checkConfig("child.whole_splat", map[string]interface{}{ "source_ids": []interface{}{ - unknownValue(), - unknownValue(), - unknownValue(), + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, }, "source_names": []interface{}{ "source.0", @@ -3914,9 +3913,9 @@ func TestContext2Apply_multiVarComprehensive(t *testing.T) { "source_ids_wrapped": []interface{}{ []interface{}{ - unknownValue(), - unknownValue(), - unknownValue(), + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, + hcl2shim.UnknownVariableValue, }, }, "source_names_wrapped": []interface{}{ @@ -4938,7 +4937,7 @@ func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) { return &InstanceDiff{ Attributes: map[string]*ResourceAttrDiff{ "id": { - New: unknownValue(), + New: hcl2shim.UnknownVariableValue, NewComputed: true, RequiresNew: true, }, diff --git a/terraform/context_test.go b/terraform/context_test.go index abf121405..5b7579051 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "fmt" - "github.com/davecgh/go-spew/spew" "io/ioutil" "log" "os" @@ -15,12 +14,10 @@ import ( "testing" "time" + "github.com/davecgh/go-spew/spew" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/go-version" - "github.com/hashicorp/hil" - "github.com/zclconf/go-cty/cty" - "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs/configload" "github.com/hashicorp/terraform/configs/configschema" @@ -34,6 +31,7 @@ import ( "github.com/hashicorp/terraform/states/statefile" "github.com/hashicorp/terraform/tfdiags" tfversion "github.com/hashicorp/terraform/version" + "github.com/zclconf/go-cty/cty" ) var ( @@ -217,7 +215,7 @@ func testDiffFn( default: new = fmt.Sprintf("%#v", v) } - if new == hil.UnknownValue { + if new == hcl2shim.UnknownVariableValue { diff.Attributes[k] = &ResourceAttrDiff{ Old: old, New: "", @@ -257,7 +255,7 @@ func testDiffFn( } } - if v == hil.UnknownValue || v == "unknown" { + if v == hcl2shim.UnknownVariableValue || v == "unknown" { // compute wasn't set in the config, so don't use these // computed values from the schema. delete(c.Raw, k) diff --git a/terraform/eval_context_mock.go b/terraform/eval_context_mock.go index 195ecc5c2..23c908798 100644 --- a/terraform/eval_context_mock.go +++ b/terraform/eval_context_mock.go @@ -3,11 +3,7 @@ package terraform import ( "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcldec" - "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/convert" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" @@ -15,6 +11,8 @@ import ( "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" + "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/convert" ) // MockEvalContext is a mock version of EvalContext that can be used @@ -110,18 +108,6 @@ type MockEvalContext struct { EvaluationScopeKeyData InstanceKeyEvalData EvaluationScopeScope *lang.Scope - InterpolateCalled bool - InterpolateConfig *config.RawConfig - InterpolateResource *Resource - InterpolateConfigResult *ResourceConfig - InterpolateError error - - InterpolateProviderCalled bool - InterpolateProviderConfig *config.ProviderConfig - InterpolateProviderResource *Resource - InterpolateProviderConfigResult *ResourceConfig - InterpolateProviderError error - PathCalled bool PathPath addrs.ModuleInstance @@ -311,22 +297,6 @@ func (c *MockEvalContext) EvaluationScope(self addrs.Referenceable, keyData Inst return c.EvaluationScopeScope } -func (c *MockEvalContext) Interpolate( - config *config.RawConfig, resource *Resource) (*ResourceConfig, error) { - c.InterpolateCalled = true - c.InterpolateConfig = config - c.InterpolateResource = resource - return c.InterpolateConfigResult, c.InterpolateError -} - -func (c *MockEvalContext) InterpolateProvider( - config *config.ProviderConfig, resource *Resource) (*ResourceConfig, error) { - c.InterpolateProviderCalled = true - c.InterpolateProviderConfig = config - c.InterpolateProviderResource = resource - return c.InterpolateProviderConfigResult, c.InterpolateError -} - func (c *MockEvalContext) Path() addrs.ModuleInstance { c.PathCalled = true return c.PathPath diff --git a/terraform/eval_count_computed.go b/terraform/eval_count_computed.go deleted file mode 100644 index 54a8333e0..000000000 --- a/terraform/eval_count_computed.go +++ /dev/null @@ -1,25 +0,0 @@ -package terraform - -import ( - "fmt" - - "github.com/hashicorp/terraform/config" -) - -// EvalCountCheckComputed is an EvalNode that checks if a resource count -// is computed and errors if so. This can possibly happen across a -// module boundary and we don't yet support this. -type EvalCountCheckComputed struct { - Resource *config.Resource -} - -// TODO: test -func (n *EvalCountCheckComputed) Eval(ctx EvalContext) (interface{}, error) { - if n.Resource.RawCount.Value() == unknownValue() { - return nil, fmt.Errorf( - "%s: value of 'count' cannot be computed", - n.Resource.Id()) - } - - return nil, nil -} diff --git a/terraform/eval_variable.go b/terraform/eval_variable.go index f21761b77..7d9115c75 100644 --- a/terraform/eval_variable.go +++ b/terraform/eval_variable.go @@ -4,101 +4,14 @@ import ( "fmt" "log" "reflect" - "strings" "github.com/hashicorp/hcl2/hcl" - "github.com/hashicorp/terraform/configs" - "github.com/hashicorp/terraform/addrs" - - "github.com/hashicorp/terraform/config" - "github.com/hashicorp/terraform/config/module" - "github.com/hashicorp/terraform/configs/hcl2shim" + "github.com/hashicorp/terraform/configs" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/convert" ) -// EvalTypeCheckVariable is an EvalNode which ensures that the variable -// values which are assigned as inputs to a module (including the root) -// match the types which are either declared for the variables explicitly -// or inferred from the default values. -// -// In order to achieve this three things are required: -// - a map of the proposed variable values -// - the configuration tree of the module in which the variable is -// declared -// - the path to the module (so we know which part of the tree to -// compare the values against). -type EvalTypeCheckVariable struct { - Variables map[string]interface{} - ModulePath []string - ModuleTree *module.Tree -} - -func (n *EvalTypeCheckVariable) Eval(ctx EvalContext) (interface{}, error) { - currentTree := n.ModuleTree - for _, pathComponent := range n.ModulePath[1:] { - currentTree = currentTree.Children()[pathComponent] - } - targetConfig := currentTree.Config() - - prototypes := make(map[string]config.VariableType) - for _, variable := range targetConfig.Variables { - prototypes[variable.Name] = variable.Type() - } - - // Only display a module in an error message if we are not in the root module - modulePathDescription := fmt.Sprintf(" in module %s", strings.Join(n.ModulePath[1:], ".")) - if len(n.ModulePath) == 1 { - modulePathDescription = "" - } - - for name, declaredType := range prototypes { - proposedValue, ok := n.Variables[name] - if !ok { - // This means the default value should be used as no overriding value - // has been set. Therefore we should continue as no check is necessary. - continue - } - - if proposedValue == hcl2shim.UnknownVariableValue { - continue - } - - switch declaredType { - case config.VariableTypeString: - switch proposedValue.(type) { - case string: - continue - default: - return nil, fmt.Errorf("variable %s%s should be type %s, got %s", - name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue)) - } - case config.VariableTypeMap: - switch proposedValue.(type) { - case map[string]interface{}: - continue - default: - return nil, fmt.Errorf("variable %s%s should be type %s, got %s", - name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue)) - } - case config.VariableTypeList: - switch proposedValue.(type) { - case []interface{}: - continue - default: - return nil, fmt.Errorf("variable %s%s should be type %s, got %s", - name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue)) - } - default: - return nil, fmt.Errorf("variable %s%s should be type %s, got type string", - name, modulePathDescription, declaredType.Printable()) - } - } - - return nil, nil -} - // EvalSetModuleCallArguments is an EvalNode implementation that sets values // for arguments of a child module call, for later retrieval during // expression evaluation. diff --git a/terraform/interpolate.go b/terraform/interpolate.go deleted file mode 100644 index a43da971c..000000000 --- a/terraform/interpolate.go +++ /dev/null @@ -1,800 +0,0 @@ -package terraform - -import ( - "fmt" - "log" - "os" - "strconv" - "strings" - "sync" - - "github.com/hashicorp/hil" - "github.com/hashicorp/hil/ast" - "github.com/hashicorp/terraform/config" - "github.com/hashicorp/terraform/config/module" - "github.com/hashicorp/terraform/configs/hcl2shim" - "github.com/hashicorp/terraform/flatmap" -) - -// Interpolater is the structure responsible for determining the values -// for interpolations such as `aws_instance.foo.bar`. -type Interpolater struct { - Operation walkOperation - Meta *ContextMeta - Module *module.Tree - State *State - StateLock *sync.RWMutex - VariableValues map[string]interface{} - VariableValuesLock *sync.Mutex -} - -// InterpolationScope is the current scope of execution. This is required -// since some variables which are interpolated are dependent on what we're -// operating on and where we are. -type InterpolationScope struct { - Path []string - Resource *Resource -} - -// Values returns the values for all the variables in the given map. -func (i *Interpolater) Values( - scope *InterpolationScope, - vars map[string]config.InterpolatedVariable) (map[string]ast.Variable, error) { - return nil, fmt.Errorf("type Interpolator is no longer supported; use the evaluator API instead") -} - -func (i *Interpolater) valueCountVar( - scope *InterpolationScope, - n string, - v *config.CountVariable, - result map[string]ast.Variable) error { - switch v.Type { - case config.CountValueIndex: - if scope.Resource == nil { - return fmt.Errorf("%s: count.index is only valid within resources", n) - } - result[n] = ast.Variable{ - Value: scope.Resource.CountIndex, - Type: ast.TypeInt, - } - return nil - default: - return fmt.Errorf("%s: unknown count type: %#v", n, v.Type) - } -} - -func unknownVariable() ast.Variable { - return ast.Variable{ - Type: ast.TypeUnknown, - Value: hcl2shim.UnknownVariableValue, - } -} - -func unknownValue() string { - return hil.UnknownValue -} - -func (i *Interpolater) valueModuleVar( - scope *InterpolationScope, - n string, - v *config.ModuleVariable, - result map[string]ast.Variable) error { - // Build the path to the child module we want - path := make([]string, len(scope.Path), len(scope.Path)+1) - copy(path, scope.Path) - path = append(path, v.Name) - - // Grab the lock so that if other interpolations are running or - // state is being modified, we'll be safe. - i.StateLock.RLock() - defer i.StateLock.RUnlock() - - // Get the module where we're looking for the value - mod := i.State.ModuleByPath(normalizeModulePath(path)) - if mod == nil { - // If the module doesn't exist, then we can return an empty string. - // This happens usually only in Refresh() when we haven't populated - // a state. During validation, we semantically verify that all - // modules reference other modules, and graph ordering should - // ensure that the module is in the state, so if we reach this - // point otherwise it really is a panic. - result[n] = unknownVariable() - - // During apply this is always an error - if i.Operation == walkApply { - return fmt.Errorf( - "Couldn't find module %q for var: %s", - v.Name, v.FullKey()) - } - } else { - // Get the value from the outputs - if outputState, ok := mod.Outputs[v.Field]; ok { - output, err := hil.InterfaceToVariable(outputState.Value) - if err != nil { - return err - } - result[n] = output - } else { - // Same reasons as the comment above. - result[n] = unknownVariable() - - // During apply this is always an error - if i.Operation == walkApply { - return fmt.Errorf( - "Couldn't find output %q for module var: %s", - v.Field, v.FullKey()) - } - } - } - - return nil -} - -func (i *Interpolater) valuePathVar( - scope *InterpolationScope, - n string, - v *config.PathVariable, - result map[string]ast.Variable) error { - switch v.Type { - case config.PathValueCwd: - wd, err := os.Getwd() - if err != nil { - return fmt.Errorf( - "Couldn't get cwd for var %s: %s", - v.FullKey(), err) - } - - result[n] = ast.Variable{ - Value: wd, - Type: ast.TypeString, - } - case config.PathValueModule: - if t := i.Module.Child(scope.Path[1:]); t != nil { - result[n] = ast.Variable{ - Value: t.Config().Dir, - Type: ast.TypeString, - } - } - case config.PathValueRoot: - result[n] = ast.Variable{ - Value: i.Module.Config().Dir, - Type: ast.TypeString, - } - default: - return fmt.Errorf("%s: unknown path type: %#v", n, v.Type) - } - - return nil - -} - -func (i *Interpolater) valueResourceVar( - scope *InterpolationScope, - n string, - v *config.ResourceVariable, - result map[string]ast.Variable) error { - // If we're computing all dynamic fields, then module vars count - // and we mark it as computed. - if i.Operation == walkValidate { - result[n] = unknownVariable() - return nil - } - - var variable *ast.Variable - var err error - - if v.Multi && v.Index == -1 { - variable, err = i.computeResourceMultiVariable(scope, v) - } else { - variable, err = i.computeResourceVariable(scope, v) - } - - if err != nil { - return err - } - - if variable == nil { - // During the refresh walk we tolerate missing variables because - // we haven't yet had a chance to refresh state, so dynamic data may - // not yet be complete. - // If it truly is missing, we'll catch it on a later walk. - // This applies only to graph nodes that interpolate during the - // refresh walk, e.g. providers. - if i.Operation == walkRefresh { - result[n] = unknownVariable() - return nil - } - - return fmt.Errorf("variable %q is nil, but no error was reported", v.Name) - } - - result[n] = *variable - return nil -} - -func (i *Interpolater) valueSelfVar( - scope *InterpolationScope, - n string, - v *config.SelfVariable, - result map[string]ast.Variable) error { - if scope == nil || scope.Resource == nil { - return fmt.Errorf( - "%s: invalid scope, self variables are only valid on resources", n) - } - - rv, err := config.NewResourceVariable(fmt.Sprintf( - "%s.%s.%d.%s", - scope.Resource.Type, - scope.Resource.Name, - scope.Resource.CountIndex, - v.Field)) - if err != nil { - return err - } - - return i.valueResourceVar(scope, n, rv, result) -} - -func (i *Interpolater) valueSimpleVar( - scope *InterpolationScope, - n string, - v *config.SimpleVariable, - result map[string]ast.Variable) error { - // This error message includes some information for people who - // relied on this for their template_file data sources. We should - // remove this at some point but there isn't any rush. - return fmt.Errorf( - "invalid variable syntax: %q. Did you mean 'var.%s'? If this is part of inline `template` parameter\n"+ - "then you must escape the interpolation with two dollar signs. For\n"+ - "example: ${a} becomes $${a}.", - n, n) -} - -func (i *Interpolater) valueTerraformVar( - scope *InterpolationScope, - n string, - v *config.TerraformVariable, - result map[string]ast.Variable) error { - // "env" is supported for backward compatibility, but it's deprecated and - // so we won't advertise it as being allowed in the error message. It will - // be removed in a future version of Terraform. - if v.Field != "workspace" && v.Field != "env" { - return fmt.Errorf( - "%s: only supported key for 'terraform.X' interpolations is 'workspace'", n) - } - - if i.Meta == nil { - return fmt.Errorf( - "%s: internal error: nil Meta. Please report a bug.", n) - } - - result[n] = ast.Variable{Type: ast.TypeString, Value: i.Meta.Env} - return nil -} - -func (i *Interpolater) valueLocalVar( - scope *InterpolationScope, - n string, - v *config.LocalVariable, - result map[string]ast.Variable, -) error { - i.StateLock.RLock() - defer i.StateLock.RUnlock() - - modTree := i.Module - if len(scope.Path) > 1 { - modTree = i.Module.Child(scope.Path[1:]) - } - - // Get the resource from the configuration so we can verify - // that the resource is in the configuration and so we can access - // the configuration if we need to. - var cl *config.Local - for _, l := range modTree.Config().Locals { - if l.Name == v.Name { - cl = l - break - } - } - - if cl == nil { - return fmt.Errorf("%s: no local value of this name has been declared", n) - } - - // Get the relevant module - module := i.State.ModuleByPath(normalizeModulePath(scope.Path)) - if module == nil { - result[n] = unknownVariable() - return nil - } - - rawV, exists := module.Locals[v.Name] - if !exists { - result[n] = unknownVariable() - return nil - } - - varV, err := hil.InterfaceToVariable(rawV) - if err != nil { - // Should never happen, since interpolation should always produce - // something we can feed back in to interpolation. - return fmt.Errorf("%s: %s", n, err) - } - - result[n] = varV - return nil -} - -func (i *Interpolater) valueUserVar( - scope *InterpolationScope, - n string, - v *config.UserVariable, - result map[string]ast.Variable) error { - i.VariableValuesLock.Lock() - defer i.VariableValuesLock.Unlock() - val, ok := i.VariableValues[v.Name] - if ok { - varValue, err := hil.InterfaceToVariable(val) - if err != nil { - return fmt.Errorf("cannot convert %s value %q to an ast.Variable for interpolation: %s", - v.Name, val, err) - } - result[n] = varValue - return nil - } - - if _, ok := result[n]; !ok && i.Operation == walkValidate { - result[n] = unknownVariable() - return nil - } - - // Look up if we have any variables with this prefix because - // those are map overrides. Include those. - for k, val := range i.VariableValues { - if strings.HasPrefix(k, v.Name+".") { - keyComponents := strings.Split(k, ".") - overrideKey := keyComponents[len(keyComponents)-1] - - mapInterface, ok := result["var."+v.Name] - if !ok { - return fmt.Errorf("override for non-existent variable: %s", v.Name) - } - - mapVariable := mapInterface.Value.(map[string]ast.Variable) - - varValue, err := hil.InterfaceToVariable(val) - if err != nil { - return fmt.Errorf("cannot convert %s value %q to an ast.Variable for interpolation: %s", - v.Name, val, err) - } - mapVariable[overrideKey] = varValue - } - } - - return nil -} - -func (i *Interpolater) computeResourceVariable( - scope *InterpolationScope, - v *config.ResourceVariable) (*ast.Variable, error) { - id := v.ResourceId() - if v.Multi { - id = fmt.Sprintf("%s.%d", id, v.Index) - } - - i.StateLock.RLock() - defer i.StateLock.RUnlock() - - unknownVariable := unknownVariable() - - // These variables must be declared early because of the use of GOTO - var isList bool - var isMap bool - - // Get the information about this resource variable, and verify - // that it exists and such. - module, cr, err := i.resourceVariableInfo(scope, v) - if err != nil { - return nil, err - } - - // If we're requesting "count" its a special variable that we grab - // directly from the config itself. - if v.Field == "count" { - var count int - if cr != nil { - count, err = cr.Count() - } else { - count, err = i.resourceCountMax(module, cr, v) - } - if err != nil { - return nil, fmt.Errorf( - "Error reading %s count: %s", - v.ResourceId(), - err) - } - - return &ast.Variable{Type: ast.TypeInt, Value: count}, nil - } - - // Get the resource out from the state. We know the state exists - // at this point and if there is a state, we expect there to be a - // resource with the given name. - var r *ResourceState - if module != nil && len(module.Resources) > 0 { - var ok bool - r, ok = module.Resources[id] - if !ok && v.Multi && v.Index == 0 { - r, ok = module.Resources[v.ResourceId()] - } - if !ok { - r = nil - } - } - if r == nil || r.Primary == nil { - if i.Operation == walkApply || i.Operation == walkPlan { - return nil, fmt.Errorf( - "Resource '%s' not found for variable '%s'", - v.ResourceId(), - v.FullKey()) - } - - // If we have no module in the state yet or count, return empty. - // NOTE(@mitchellh): I actually don't know why this is here. During - // a refactor I kept this here to maintain the same behavior, but - // I'm not sure why its here. - if module == nil || len(module.Resources) == 0 { - return nil, nil - } - - goto MISSING - } - - if attr, ok := r.Primary.Attributes[v.Field]; ok { - v, err := hil.InterfaceToVariable(attr) - return &v, err - } - - // special case for the "id" field which is usually also an attribute - if v.Field == "id" && r.Primary.ID != "" { - // This is usually pulled from the attributes, but is sometimes missing - // during destroy. We can return the ID field in this case. - // FIXME: there should only be one ID to rule them all. - log.Printf("[WARN] resource %s missing 'id' attribute", v.ResourceId()) - v, err := hil.InterfaceToVariable(r.Primary.ID) - return &v, err - } - - // computed list or map attribute - _, isList = r.Primary.Attributes[v.Field+".#"] - _, isMap = r.Primary.Attributes[v.Field+".%"] - if isList || isMap { - variable, err := i.interpolateComplexTypeAttribute(v.Field, r.Primary.Attributes) - return &variable, err - } - - // At apply time, we can't do the "maybe has it" check below - // that we need for plans since parent elements might be computed. - // Therefore, it is an error and we're missing the key. - // - // TODO: test by creating a state and configuration that is referencing - // a non-existent variable "foo.bar" where the state only has "foo" - // and verify plan works, but apply doesn't. - if i.Operation == walkApply || i.Operation == walkDestroy { - goto MISSING - } - - // We didn't find the exact field, so lets separate the dots - // and see if anything along the way is a computed set. i.e. if - // we have "foo.0.bar" as the field, check to see if "foo" is - // a computed list. If so, then the whole thing is computed. - if parts := strings.Split(v.Field, "."); len(parts) > 1 { - for i := 1; i < len(parts); i++ { - // Lists and sets make this - key := fmt.Sprintf("%s.#", strings.Join(parts[:i], ".")) - if attr, ok := r.Primary.Attributes[key]; ok { - v, err := hil.InterfaceToVariable(attr) - return &v, err - } - - // Maps make this - key = fmt.Sprintf("%s", strings.Join(parts[:i], ".")) - if attr, ok := r.Primary.Attributes[key]; ok { - v, err := hil.InterfaceToVariable(attr) - return &v, err - } - } - } - -MISSING: - // Validation for missing interpolations should happen at a higher - // semantic level. If we reached this point and don't have variables, - // just return the computed value. - if scope == nil && scope.Resource == nil { - return &unknownVariable, nil - } - - // If the operation is refresh, it isn't an error for a value to - // be unknown. Instead, we return that the value is computed so - // that the graph can continue to refresh other nodes. It doesn't - // matter because the config isn't interpolated anyways. - // - // For a Destroy, we're also fine with computed values, since our goal is - // only to get destroy nodes for existing resources. - if i.Operation == walkRefresh || i.Operation == walkPlanDestroy { - return &unknownVariable, nil - } - - return nil, fmt.Errorf( - "Resource '%s' does not have attribute '%s' "+ - "for variable '%s'", - id, - v.Field, - v.FullKey()) -} - -func (i *Interpolater) computeResourceMultiVariable( - scope *InterpolationScope, - v *config.ResourceVariable) (*ast.Variable, error) { - i.StateLock.RLock() - defer i.StateLock.RUnlock() - - unknownVariable := unknownVariable() - - // Get the information about this resource variable, and verify - // that it exists and such. - module, cr, err := i.resourceVariableInfo(scope, v) - if err != nil { - return nil, err - } - - // Get the keys for all the resources that are created for this resource - countMax, err := i.resourceCountMax(module, cr, v) - if err != nil { - return nil, err - } - - // If count is zero, we return an empty list - if countMax == 0 { - return &ast.Variable{Type: ast.TypeList, Value: []ast.Variable{}}, nil - } - - // If we have no module in the state yet or count, return unknown - if module == nil || len(module.Resources) == 0 { - return &unknownVariable, nil - } - - var values []interface{} - for idx := 0; idx < countMax; idx++ { - id := fmt.Sprintf("%s.%d", v.ResourceId(), idx) - - // ID doesn't have a trailing index. We try both here, but if a value - // without a trailing index is found we prefer that. This choice - // is for legacy reasons: older versions of TF preferred it. - if id == v.ResourceId()+".0" { - potential := v.ResourceId() - if _, ok := module.Resources[potential]; ok { - id = potential - } - } - - r, ok := module.Resources[id] - if !ok { - continue - } - - if r.Primary == nil { - continue - } - - if singleAttr, ok := r.Primary.Attributes[v.Field]; ok { - values = append(values, singleAttr) - continue - } - - if v.Field == "id" && r.Primary.ID != "" { - log.Printf("[WARN] resource %s missing 'id' attribute", v.ResourceId()) - values = append(values, r.Primary.ID) - } - - // computed list or map attribute - _, isList := r.Primary.Attributes[v.Field+".#"] - _, isMap := r.Primary.Attributes[v.Field+".%"] - if !(isList || isMap) { - continue - } - multiAttr, err := i.interpolateComplexTypeAttribute(v.Field, r.Primary.Attributes) - if err != nil { - return nil, err - } - - values = append(values, multiAttr) - } - - if len(values) == 0 { - // If the operation is refresh, it isn't an error for a value to - // be unknown. Instead, we return that the value is computed so - // that the graph can continue to refresh other nodes. It doesn't - // matter because the config isn't interpolated anyways. - // - // For a Destroy, we're also fine with computed values, since our goal is - // only to get destroy nodes for existing resources. - // - // For an input walk, computed values are okay to return because we're only - // looking for missing variables to prompt the user for. - if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkDestroy { - return &unknownVariable, nil - } - - return nil, fmt.Errorf( - "Resource '%s' does not have attribute '%s' "+ - "for variable '%s'", - v.ResourceId(), - v.Field, - v.FullKey()) - } - - variable, err := hil.InterfaceToVariable(values) - return &variable, err -} - -func (i *Interpolater) interpolateComplexTypeAttribute( - resourceID string, - attributes map[string]string) (ast.Variable, error) { - // We can now distinguish between lists and maps in state by the count field: - // - lists (and by extension, sets) use the traditional .# notation - // - maps use the newer .% notation - // Consequently here we can decide how to deal with the keys appropriately - // based on whether the type is a map of list. - if lengthAttr, isList := attributes[resourceID+".#"]; isList { - log.Printf("[DEBUG] Interpolating computed list element attribute %s (%s)", - resourceID, lengthAttr) - - // In Terraform's internal dotted representation of list-like attributes, the - // ".#" count field is marked as unknown to indicate "this whole list is - // unknown". We must honor that meaning here so computed references can be - // treated properly during the plan phase. - if lengthAttr == hcl2shim.UnknownVariableValue { - return unknownVariable(), nil - } - - expanded := flatmap.Expand(attributes, resourceID) - return hil.InterfaceToVariable(expanded) - } - - if lengthAttr, isMap := attributes[resourceID+".%"]; isMap { - log.Printf("[DEBUG] Interpolating computed map element attribute %s (%s)", - resourceID, lengthAttr) - - // In Terraform's internal dotted representation of map attributes, the - // ".%" count field is marked as unknown to indicate "this whole list is - // unknown". We must honor that meaning here so computed references can be - // treated properly during the plan phase. - if lengthAttr == hcl2shim.UnknownVariableValue { - return unknownVariable(), nil - } - - expanded := flatmap.Expand(attributes, resourceID) - return hil.InterfaceToVariable(expanded) - } - - return ast.Variable{}, fmt.Errorf("No complex type %s found", resourceID) -} - -func (i *Interpolater) resourceVariableInfo( - scope *InterpolationScope, - v *config.ResourceVariable) (*ModuleState, *config.Resource, error) { - // Get the module tree that contains our current path. This is - // either the current module (path is empty) or a child. - modTree := i.Module - if len(scope.Path) > 1 { - modTree = i.Module.Child(scope.Path[1:]) - } - - // Get the resource from the configuration so we can verify - // that the resource is in the configuration and so we can access - // the configuration if we need to. - var cr *config.Resource - for _, r := range modTree.Config().Resources { - if r.Id() == v.ResourceId() { - cr = r - break - } - } - - // Get the relevant module - module := i.State.ModuleByPath(normalizeModulePath(scope.Path)) - return module, cr, nil -} - -func (i *Interpolater) resourceCountMax( - ms *ModuleState, - cr *config.Resource, - v *config.ResourceVariable) (int, error) { - id := v.ResourceId() - - // If we're NOT applying, then we assume we can read the count - // from the state. Plan and so on may not have any state yet so - // we do a full interpolation. - // Don't forget walkDestroy, which is a special case of walkApply - if !(i.Operation == walkApply || i.Operation == walkDestroy) { - if cr == nil { - return 0, nil - } - - count, err := cr.Count() - if err != nil { - return 0, err - } - - return count, nil - } - - // If we have no module state in the apply walk, that suggests we've hit - // a rather awkward edge-case: the resource this variable refers to - // has count = 0 and is the only resource processed so far on this walk, - // and so we've ended up not creating any resource states yet. We don't - // create a module state until the first resource is written into it, - // so the module state doesn't exist when we get here. - // - // In this case we act as we would if we had been passed a module - // with an empty resource state map. - if ms == nil { - return 0, nil - } - - // We need to determine the list of resource keys to get values from. - // This needs to be sorted so the order is deterministic. We used to - // use "cr.Count()" but that doesn't work if the count is interpolated - // and we can't guarantee that so we instead depend on the state. - max := -1 - for k, s := range ms.Resources { - // This resource may have been just removed, in which case the Primary - // may be nil, or just empty. - if s == nil || s.Primary == nil || len(s.Primary.Attributes) == 0 { - continue - } - - // Get the index number for this resource - index := "" - if k == id { - // If the key is the id, then its just 0 (no explicit index) - index = "0" - } else if strings.HasPrefix(k, id+".") { - // Grab the index number out of the state - index = k[len(id+"."):] - if idx := strings.IndexRune(index, '.'); idx >= 0 { - index = index[:idx] - } - } - - // If there was no index then this resource didn't match - // the one we're looking for, exit. - if index == "" { - continue - } - - // Turn the index into an int - raw, err := strconv.ParseInt(index, 0, 0) - if err != nil { - return 0, fmt.Errorf( - "%s: error parsing index %q as int: %s", - id, index, err) - } - - // Keep track of this index if its the max - if new := int(raw); new > max { - max = new - } - } - - // If we never found any matching resources in the state, we - // have zero. - if max == -1 { - return 0, nil - } - - // The result value is "max+1" because we're returning the - // max COUNT, not the max INDEX, and we zero-index. - return max + 1, nil -} diff --git a/terraform/node_provisioner.go b/terraform/node_provisioner.go index 31ed1a8c8..cf51cf06c 100644 --- a/terraform/node_provisioner.go +++ b/terraform/node_provisioner.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/config" ) // NodeProvisioner represents a provider that has no associated operations. @@ -12,12 +11,6 @@ import ( type NodeProvisioner struct { NameValue string PathValue addrs.ModuleInstance - - // The fields below will be automatically set using the Attach - // interfaces if you're running those transforms, but also be explicitly - // set if you already have that information. - - Config *config.ProviderConfig } var ( diff --git a/terraform/resource_address.go b/terraform/resource_address.go index 5d8261a67..ca833fe13 100644 --- a/terraform/resource_address.go +++ b/terraform/resource_address.go @@ -8,8 +8,6 @@ import ( "strings" "github.com/hashicorp/terraform/addrs" - - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs" ) @@ -27,7 +25,7 @@ type ResourceAddress struct { InstanceTypeSet bool Name string Type string - Mode config.ResourceMode // significant only if InstanceTypeSet + Mode ResourceMode // significant only if InstanceTypeSet } // Copy returns a copy of this ResourceAddress @@ -58,9 +56,9 @@ func (r *ResourceAddress) String() string { } switch r.Mode { - case config.ManagedResourceMode: + case ManagedResourceMode: // nothing to do - case config.DataResourceMode: + case DataResourceMode: result = append(result, "data") default: panic(fmt.Errorf("unsupported resource mode %s", r.Mode)) @@ -127,11 +125,11 @@ func (r *ResourceAddress) MatchesResourceConfig(path addrs.Module, rc *configs.R // completely, but for now we'll need to translate to the old // way of representing resource modes. switch r.Mode { - case config.ManagedResourceMode: + case ManagedResourceMode: if rc.Mode != addrs.ManagedResourceMode { return false } - case config.DataResourceMode: + case DataResourceMode: if rc.Mode != addrs.DataResourceMode { return false } @@ -160,9 +158,9 @@ func (r *ResourceAddress) MatchesResourceConfig(path addrs.Module, rc *configs.R func (r *ResourceAddress) stateId() string { result := fmt.Sprintf("%s.%s", r.Type, r.Name) switch r.Mode { - case config.ManagedResourceMode: + case ManagedResourceMode: // Done - case config.DataResourceMode: + case DataResourceMode: result = fmt.Sprintf("data.%s", result) default: panic(fmt.Errorf("unknown resource mode: %s", r.Mode)) @@ -174,17 +172,6 @@ func (r *ResourceAddress) stateId() string { return result } -// parseResourceAddressConfig creates a resource address from a config.Resource -func parseResourceAddressConfig(r *config.Resource) (*ResourceAddress, error) { - return &ResourceAddress{ - Type: r.Type, - Name: r.Name, - Index: -1, - InstanceType: TypePrimary, - Mode: r.Mode, - }, nil -} - // parseResourceAddressInternal parses the somewhat bespoke resource // identifier used in states and diffs, such as "instance.name.0". func parseResourceAddressInternal(s string) (*ResourceAddress, error) { @@ -196,14 +183,14 @@ func parseResourceAddressInternal(s string) (*ResourceAddress, error) { } // Data resource if we have at least 3 parts and the first one is data - mode := config.ManagedResourceMode + mode := ManagedResourceMode if len(parts) > 2 && parts[0] == "data" { - mode = config.DataResourceMode + mode = DataResourceMode parts = parts[1:] } // If we're not a data resource and we have more than 3, then it is an error - if len(parts) > 3 && mode != config.DataResourceMode { + if len(parts) > 3 && mode != DataResourceMode { return nil, fmt.Errorf("Invalid internal resource address format: %s", s) } @@ -234,9 +221,9 @@ func ParseResourceAddress(s string) (*ResourceAddress, error) { if err != nil { return nil, err } - mode := config.ManagedResourceMode + mode := ManagedResourceMode if matches["data_prefix"] != "" { - mode = config.DataResourceMode + mode = DataResourceMode } resourceIndex, err := ParseResourceIndex(matches["index"]) if err != nil { @@ -249,7 +236,7 @@ func ParseResourceAddress(s string) (*ResourceAddress, error) { path := ParseResourcePath(matches["path"]) // not allowed to say "data." without a type following - if mode == config.DataResourceMode && matches["type"] == "" { + if mode == DataResourceMode && matches["type"] == "" { return nil, fmt.Errorf( "invalid resource address %q: must target specific data instance", s, @@ -302,11 +289,11 @@ func NewLegacyResourceAddress(addr addrs.AbsResource) *ResourceAddress { switch addr.Resource.Mode { case addrs.ManagedResourceMode: - ret.Mode = config.ManagedResourceMode + ret.Mode = ManagedResourceMode case addrs.DataResourceMode: - ret.Mode = config.DataResourceMode + ret.Mode = DataResourceMode default: - panic(fmt.Errorf("cannot shim %s to legacy config.ResourceMode value", addr.Resource.Mode)) + panic(fmt.Errorf("cannot shim %s to legacy ResourceMode value", addr.Resource.Mode)) } path := make([]string, len(addr.Module)) @@ -340,11 +327,11 @@ func NewLegacyResourceInstanceAddress(addr addrs.AbsResourceInstance) *ResourceA switch addr.Resource.Resource.Mode { case addrs.ManagedResourceMode: - ret.Mode = config.ManagedResourceMode + ret.Mode = ManagedResourceMode case addrs.DataResourceMode: - ret.Mode = config.DataResourceMode + ret.Mode = DataResourceMode default: - panic(fmt.Errorf("cannot shim %s to legacy config.ResourceMode value", addr.Resource.Resource.Mode)) + panic(fmt.Errorf("cannot shim %s to legacy ResourceMode value", addr.Resource.Resource.Mode)) } path := make([]string, len(addr.Module)) @@ -404,9 +391,9 @@ func (addr *ResourceAddress) AbsResourceInstanceAddr() addrs.AbsResourceInstance } switch addr.Mode { - case config.ManagedResourceMode: + case ManagedResourceMode: ret.Resource.Resource.Mode = addrs.ManagedResourceMode - case config.DataResourceMode: + case DataResourceMode: ret.Resource.Resource.Mode = addrs.DataResourceMode default: panic(fmt.Errorf("cannot shim %s to addrs.ResourceMode value", addr.Mode)) @@ -534,7 +521,7 @@ func (addr *ResourceAddress) Less(other *ResourceAddress) bool { return addrStr < otherStr case addr.Mode != other.Mode: - return addr.Mode == config.DataResourceMode + return addr.Mode == DataResourceMode case addr.Type != other.Type: return addr.Type < other.Type diff --git a/terraform/resource_address_test.go b/terraform/resource_address_test.go index c7dbfd274..3bb5f2082 100644 --- a/terraform/resource_address_test.go +++ b/terraform/resource_address_test.go @@ -6,8 +6,6 @@ import ( "testing" "github.com/hashicorp/terraform/addrs" - - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs" ) @@ -20,7 +18,7 @@ func TestParseResourceAddressInternal(t *testing.T) { "basic resource": { "aws_instance.foo", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -32,7 +30,7 @@ func TestParseResourceAddressInternal(t *testing.T) { "basic resource with count": { "aws_instance.foo.1", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -44,7 +42,7 @@ func TestParseResourceAddressInternal(t *testing.T) { "data resource": { "data.aws_ami.foo", &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_ami", Name: "foo", InstanceType: TypePrimary, @@ -56,7 +54,7 @@ func TestParseResourceAddressInternal(t *testing.T) { "data resource with count": { "data.aws_ami.foo.1", &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_ami", Name: "foo", InstanceType: TypePrimary, @@ -114,7 +112,7 @@ func TestParseResourceAddress(t *testing.T) { "implicit primary managed instance, no specific index": { "aws_instance.foo", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -126,7 +124,7 @@ func TestParseResourceAddress(t *testing.T) { "implicit primary data instance, no specific index": { "data.aws_instance.foo", &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -138,7 +136,7 @@ func TestParseResourceAddress(t *testing.T) { "implicit primary, explicit index": { "aws_instance.foo[2]", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -150,7 +148,7 @@ func TestParseResourceAddress(t *testing.T) { "implicit primary, explicit index over ten": { "aws_instance.foo[12]", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -162,7 +160,7 @@ func TestParseResourceAddress(t *testing.T) { "explicit primary, explicit index": { "aws_instance.foo.primary[2]", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -175,7 +173,7 @@ func TestParseResourceAddress(t *testing.T) { "tainted": { "aws_instance.foo.tainted", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypeTainted, @@ -188,7 +186,7 @@ func TestParseResourceAddress(t *testing.T) { "deposed": { "aws_instance.foo.deposed", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypeDeposed, @@ -201,7 +199,7 @@ func TestParseResourceAddress(t *testing.T) { "with a hyphen": { "aws_instance.foo-bar", &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo-bar", InstanceType: TypePrimary, @@ -214,7 +212,7 @@ func TestParseResourceAddress(t *testing.T) { "module.child.aws_instance.foo", &ResourceAddress{ Path: []string{"child"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -227,7 +225,7 @@ func TestParseResourceAddress(t *testing.T) { "module.child.data.aws_instance.foo", &ResourceAddress{ Path: []string{"child"}, - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -240,7 +238,7 @@ func TestParseResourceAddress(t *testing.T) { "module.a.module.b.module.forever.aws_instance.foo", &ResourceAddress{ Path: []string{"a", "b", "forever"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -314,7 +312,7 @@ func TestResourceAddressContains(t *testing.T) { }{ { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -322,7 +320,7 @@ func TestResourceAddressContains(t *testing.T) { Index: 0, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -333,14 +331,14 @@ func TestResourceAddressContains(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, Index: 0, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -351,14 +349,14 @@ func TestResourceAddressContains(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, Index: -1, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -369,14 +367,14 @@ func TestResourceAddressContains(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, Index: -1, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -390,7 +388,7 @@ func TestResourceAddressContains(t *testing.T) { Index: -1, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -405,7 +403,7 @@ func TestResourceAddressContains(t *testing.T) { }, &ResourceAddress{ Path: []string{"bar"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -421,7 +419,7 @@ func TestResourceAddressContains(t *testing.T) { }, &ResourceAddress{ Path: []string{"bar"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -437,7 +435,7 @@ func TestResourceAddressContains(t *testing.T) { }, &ResourceAddress{ Path: []string{"bar", "baz"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -474,7 +472,7 @@ func TestResourceAddressContains(t *testing.T) { { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "bar", InstanceTypeSet: true, @@ -482,7 +480,7 @@ func TestResourceAddressContains(t *testing.T) { Index: 0, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -493,7 +491,7 @@ func TestResourceAddressContains(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -501,7 +499,7 @@ func TestResourceAddressContains(t *testing.T) { Index: 0, }, &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -518,7 +516,7 @@ func TestResourceAddressContains(t *testing.T) { }, &ResourceAddress{ Path: []string{"baz"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -534,7 +532,7 @@ func TestResourceAddressContains(t *testing.T) { }, &ResourceAddress{ Path: []string{"baz", "bar"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -544,7 +542,7 @@ func TestResourceAddressContains(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: true, @@ -552,7 +550,7 @@ func TestResourceAddressContains(t *testing.T) { Index: 0, }, &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceTypeSet: false, @@ -579,14 +577,14 @@ func TestResourceAddressContains(t *testing.T) { Name: "foo", Index: 1, InstanceType: TypePrimary, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, }, &ResourceAddress{ Type: "aws_instance", Name: "foo", Index: -1, InstanceType: TypePrimary, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, }, false, }, @@ -614,14 +612,14 @@ func TestResourceAddressEquals(t *testing.T) { }{ "basic match": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 0, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -631,14 +629,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "address does not set index": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: -1, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -648,14 +646,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "other does not set index": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 3, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -665,14 +663,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "neither sets index": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: -1, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -682,14 +680,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "index over ten": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 1, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -699,14 +697,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "different type": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 0, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_vpc", Name: "foo", InstanceType: TypePrimary, @@ -716,14 +714,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "different mode": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 0, }, Other: &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -733,14 +731,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "different name": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 0, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "bar", InstanceType: TypePrimary, @@ -750,14 +748,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "different instance type": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 0, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypeTainted, @@ -767,14 +765,14 @@ func TestResourceAddressEquals(t *testing.T) { }, "different index": { Address: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, Index: 0, }, Other: &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -792,7 +790,7 @@ func TestResourceAddressEquals(t *testing.T) { }, Other: &ResourceAddress{ Path: []string{"a", "b"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -810,7 +808,7 @@ func TestResourceAddressEquals(t *testing.T) { }, Other: &ResourceAddress{ Path: []string{"a", "b"}, - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -828,7 +826,7 @@ func TestResourceAddressEquals(t *testing.T) { }, Other: &ResourceAddress{ Path: []string{"a"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -846,7 +844,7 @@ func TestResourceAddressEquals(t *testing.T) { }, Other: &ResourceAddress{ Path: []string{"a"}, - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -857,7 +855,7 @@ func TestResourceAddressEquals(t *testing.T) { "nil path vs empty path should match": { Address: &ResourceAddress{ Path: []string{}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -865,7 +863,7 @@ func TestResourceAddressEquals(t *testing.T) { }, Other: &ResourceAddress{ Path: nil, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -891,7 +889,7 @@ func TestResourceAddressStateId(t *testing.T) { }{ "basic resource": { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -902,7 +900,7 @@ func TestResourceAddressStateId(t *testing.T) { "basic resource with index": { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -913,7 +911,7 @@ func TestResourceAddressStateId(t *testing.T) { "data resource": { &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_instance", Name: "foo", InstanceType: TypePrimary, @@ -1062,7 +1060,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { }{ { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1078,7 +1076,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { { &ResourceAddress{ Path: []string{"child"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1094,7 +1092,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { { &ResourceAddress{ Path: []string{"child", "grandchild"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1135,7 +1133,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { }, { &ResourceAddress{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1150,7 +1148,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1165,7 +1163,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { }, { &ResourceAddress{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1181,7 +1179,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { { &ResourceAddress{ Path: []string{"child", "grandchild"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, @@ -1197,7 +1195,7 @@ func TestResourceAddressMatchesResourceConfig(t *testing.T) { { &ResourceAddress{ Path: []string{"child"}, - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "null_resource", Name: "baz", Index: -1, diff --git a/terraform/resource_mode.go b/terraform/resource_mode.go new file mode 100644 index 000000000..7b2f372aa --- /dev/null +++ b/terraform/resource_mode.go @@ -0,0 +1,9 @@ +package terraform + +//go:generate stringer -type=ResourceMode -output=resource_mode_string.go resource_mode.go +type ResourceMode int + +const ( + ManagedResourceMode ResourceMode = iota + DataResourceMode +) diff --git a/terraform/resource_mode_string.go b/terraform/resource_mode_string.go new file mode 100644 index 000000000..ba84346a2 --- /dev/null +++ b/terraform/resource_mode_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=ResourceMode -output=resource_mode_string.go resource_mode.go"; DO NOT EDIT. + +package terraform + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ManagedResourceMode-0] + _ = x[DataResourceMode-1] +} + +const _ResourceMode_name = "ManagedResourceModeDataResourceMode" + +var _ResourceMode_index = [...]uint8{0, 19, 35} + +func (i ResourceMode) String() string { + if i < 0 || i >= ResourceMode(len(_ResourceMode_index)-1) { + return "ResourceMode(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ResourceMode_name[_ResourceMode_index[i]:_ResourceMode_index[i+1]] +} diff --git a/terraform/state.go b/terraform/state.go index ff1cfe745..c973980bf 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -22,18 +22,16 @@ import ( version "github.com/hashicorp/go-version" "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcl/hclsyntax" - "github.com/mitchellh/copystructure" - "github.com/zclconf/go-cty/cty" - ctyjson "github.com/zclconf/go-cty/cty/json" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/hcl2shim" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/tfdiags" tfversion "github.com/hashicorp/terraform/version" + "github.com/mitchellh/copystructure" + "github.com/zclconf/go-cty/cty" + ctyjson "github.com/zclconf/go-cty/cty/json" ) const ( @@ -1342,7 +1340,7 @@ func (m *ModuleState) Empty() bool { type ResourceStateKey struct { Name string Type string - Mode config.ResourceMode + Mode ResourceMode Index int } @@ -1372,9 +1370,9 @@ func (rsk *ResourceStateKey) String() string { } var prefix string switch rsk.Mode { - case config.ManagedResourceMode: + case ManagedResourceMode: prefix = "" - case config.DataResourceMode: + case DataResourceMode: prefix = "data." default: panic(fmt.Errorf("unknown resource mode %s", rsk.Mode)) @@ -1391,9 +1389,9 @@ func (rsk *ResourceStateKey) String() string { // latter case, the index is returned as -1. func ParseResourceStateKey(k string) (*ResourceStateKey, error) { parts := strings.Split(k, ".") - mode := config.ManagedResourceMode + mode := ManagedResourceMode if len(parts) > 0 && parts[0] == "data" { - mode = config.DataResourceMode + mode = DataResourceMode // Don't need the constant "data" prefix for parsing // now that we've figured out the mode. parts = parts[1:] diff --git a/terraform/state_test.go b/terraform/state_test.go index 6fd07b5c5..beac79705 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -12,8 +12,6 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/hashicorp/terraform/addrs" - - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/configs/hcl2shim" ) @@ -1704,7 +1702,7 @@ func TestParseResourceStateKey(t *testing.T) { { Input: "aws_instance.foo.3", Expected: &ResourceStateKey{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", Index: 3, @@ -1713,7 +1711,7 @@ func TestParseResourceStateKey(t *testing.T) { { Input: "aws_instance.foo.0", Expected: &ResourceStateKey{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", Index: 0, @@ -1722,7 +1720,7 @@ func TestParseResourceStateKey(t *testing.T) { { Input: "aws_instance.foo", Expected: &ResourceStateKey{ - Mode: config.ManagedResourceMode, + Mode: ManagedResourceMode, Type: "aws_instance", Name: "foo", Index: -1, @@ -1731,7 +1729,7 @@ func TestParseResourceStateKey(t *testing.T) { { Input: "data.aws_ami.foo", Expected: &ResourceStateKey{ - Mode: config.DataResourceMode, + Mode: DataResourceMode, Type: "aws_ami", Name: "foo", Index: -1, diff --git a/terraform/transform_config_old.go b/terraform/transform_config_old.go deleted file mode 100644 index ec4125822..000000000 --- a/terraform/transform_config_old.go +++ /dev/null @@ -1,23 +0,0 @@ -package terraform - -import ( - "fmt" - - "github.com/hashicorp/terraform/config" -) - -// varNameForVar returns the VarName value for an interpolated variable. -// This value is compared to the VarName() value for the nodes within the -// graph to build the graph edges. -func varNameForVar(raw config.InterpolatedVariable) string { - switch v := raw.(type) { - case *config.ModuleVariable: - return fmt.Sprintf("module.%s.output.%s", v.Name, v.Field) - case *config.ResourceVariable: - return v.ResourceId() - case *config.UserVariable: - return fmt.Sprintf("var.%s", v.Name) - default: - return "" - } -} diff --git a/terraform/transform_reference.go b/terraform/transform_reference.go index 23bc8cd20..11196b849 100644 --- a/terraform/transform_reference.go +++ b/terraform/transform_reference.go @@ -5,12 +5,10 @@ import ( "log" "github.com/hashicorp/hcl2/hcl" - "github.com/hashicorp/terraform/configs/configschema" - "github.com/hashicorp/terraform/lang" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/config" + "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/dag" + "github.com/hashicorp/terraform/lang" ) // GraphNodeReferenceable must be implemented by any node that represents @@ -424,39 +422,6 @@ func ReferencesFromConfig(body hcl.Body, schema *configschema.Block) []*addrs.Re return refs } -// ReferenceFromInterpolatedVar returns the reference from this variable, -// or an empty string if there is no reference. -func ReferenceFromInterpolatedVar(v config.InterpolatedVariable) []string { - switch v := v.(type) { - case *config.ModuleVariable: - return []string{fmt.Sprintf("module.%s.output.%s", v.Name, v.Field)} - case *config.ResourceVariable: - id := v.ResourceId() - - // If we have a multi-reference (splat), then we depend on ALL - // resources with this type/name. - if v.Multi && v.Index == -1 { - return []string{fmt.Sprintf("%s.*", id)} - } - - // Otherwise, we depend on a specific index. - idx := v.Index - if !v.Multi || v.Index == -1 { - idx = 0 - } - - // Depend on the index, as well as "N" which represents the - // un-expanded set of resources. - return []string{fmt.Sprintf("%s.%d/%s.N", id, idx, id)} - case *config.UserVariable: - return []string{fmt.Sprintf("var.%s", v.Name)} - case *config.LocalVariable: - return []string{fmt.Sprintf("local.%s", v.Name)} - default: - return nil - } -} - // appendResourceDestroyReferences identifies resource and resource instance // references in the given slice and appends to it the "destroy-phase" // equivalents of those references, returning the result.