diff --git a/command/plugin.go b/command/plugin.go index f5bb2ab61..1614f9375 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -71,8 +71,6 @@ import ( vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud" yandexexportpostprocessor "github.com/hashicorp/packer/post-processor/yandex-export" yandeximportpostprocessor "github.com/hashicorp/packer/post-processor/yandex-import" - ansibleprovisioner "github.com/hashicorp/packer/provisioner/ansible" - ansiblelocalprovisioner "github.com/hashicorp/packer/provisioner/ansible-local" azuredtlartifactprovisioner "github.com/hashicorp/packer/provisioner/azure-dtlartifact" breakpointprovisioner "github.com/hashicorp/packer/provisioner/breakpoint" chefclientprovisioner "github.com/hashicorp/packer/provisioner/chef-client" @@ -143,8 +141,6 @@ var Builders = map[string]packersdk.Builder{ } var Provisioners = map[string]packersdk.Provisioner{ - "ansible": new(ansibleprovisioner.Provisioner), - "ansible-local": new(ansiblelocalprovisioner.Provisioner), "azure-dtlartifact": new(azuredtlartifactprovisioner.Provisioner), "breakpoint": new(breakpointprovisioner.Provisioner), "chef-client": new(chefclientprovisioner.Provisioner), diff --git a/command/vendored_plugins.go b/command/vendored_plugins.go index 092bd4b90..5cd42931a 100644 --- a/command/vendored_plugins.go +++ b/command/vendored_plugins.go @@ -15,6 +15,8 @@ import ( amazonamidatasource "github.com/hashicorp/packer-plugin-amazon/datasource/ami" amazonsecretsmanagerdatasource "github.com/hashicorp/packer-plugin-amazon/datasource/secretsmanager" anazibimportpostprocessor "github.com/hashicorp/packer-plugin-amazon/post-processor/import" + ansibleprovisioner "github.com/hashicorp/packer-plugin-ansible/provisioner/ansible" + ansiblelocalprovisioner "github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local" dockerbuilder "github.com/hashicorp/packer-plugin-docker/builder/docker" dockerimportpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-import" dockerpushpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-push" @@ -48,7 +50,10 @@ var VendoredBuilders = map[string]packersdk.Builder{ // VendoredProvisioners are provisioner components that were once bundled with the // Packer core, but are now being imported from their counterpart plugin repos -var VendoredProvisioners = map[string]packersdk.Provisioner{} +var VendoredProvisioners = map[string]packersdk.Provisioner{ + "ansible": new(ansibleprovisioner.Provisioner), + "ansible-local": new(ansiblelocalprovisioner.Provisioner), +} // VendoredPostProcessors are post-processor components that were once bundled with the // Packer core, but are now being imported from their counterpart plugin repos diff --git a/go.mod b/go.mod index d6dccd95e..068c38d6f 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( github.com/hashicorp/go-version v1.2.0 github.com/hashicorp/hcl/v2 v2.9.1 github.com/hashicorp/packer-plugin-amazon v0.0.1 + github.com/hashicorp/packer-plugin-ansible v0.0.2 github.com/hashicorp/packer-plugin-docker v0.0.7 github.com/hashicorp/packer-plugin-sdk v0.1.3 github.com/hashicorp/packer-plugin-vsphere v0.0.0-20210415100050-d0269b5646e6 diff --git a/go.sum b/go.sum index c4aa579c3..c8460acf8 100644 --- a/go.sum +++ b/go.sum @@ -433,6 +433,8 @@ github.com/hashicorp/packer v1.7.0/go.mod h1:3KRJcwOctl2JaAGpQMI1bWQRArfWNWqcYjO github.com/hashicorp/packer v1.7.1/go.mod h1:ApnmMINvuhhnfPyTVqZu6jznDWPVYDJUw7e188DFCmo= github.com/hashicorp/packer-plugin-amazon v0.0.1 h1:EuyjNK9bL7WhQeIJzhBJxOx8nyc61ai5UbOsb1PIVwI= github.com/hashicorp/packer-plugin-amazon v0.0.1/go.mod h1:12c9msibyHdId+Mk/pCbdRb1KaLIhaNyxeJ6n8bZt30= +github.com/hashicorp/packer-plugin-ansible v0.0.2 h1:nvBtCedXhUI5T6Up5+bmhlY7rmk8FjWuFv9A2joK7TU= +github.com/hashicorp/packer-plugin-ansible v0.0.2/go.mod h1:ocXB4KTU+I+DBRGfMP4XE7dPlURaUnb7NJvyddZ6bh0= github.com/hashicorp/packer-plugin-docker v0.0.7 h1:hMTrH7vrkFIjphtbbtpuzffTzSjMNgxayo2DPLz9y+c= github.com/hashicorp/packer-plugin-docker v0.0.7/go.mod h1:IpeKlwOSy2kdgQcysqd3gCsoqjME9jtmpFoKxn7RRNI= github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU= @@ -446,6 +448,7 @@ github.com/hashicorp/packer-plugin-sdk v0.0.14/go.mod h1:tNb3XzJPnjMl3QuUdKmF47B github.com/hashicorp/packer-plugin-sdk v0.1.0/go.mod h1:CFsC20uZjtER/EnTn/CSMKD0kEdkqOVev8mtOmfnZiI= github.com/hashicorp/packer-plugin-sdk v0.1.1/go.mod h1:1d3nqB9LUsXMQaNUiL67Q+WYEtjsVcLNTX8ikVlpBrc= github.com/hashicorp/packer-plugin-sdk v0.1.2/go.mod h1:KRjczE1/c9NV5Re+PXt3myJsVTI/FxEHpZjRjOH0Fug= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407232143-c217d82aefb6/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ= github.com/hashicorp/packer-plugin-sdk v0.1.3 h1:oHTVlgoX2piUzL54+LBo9uIMfW+L/kY7or83dDStdIY= github.com/hashicorp/packer-plugin-sdk v0.1.3/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ= github.com/hashicorp/packer-plugin-vsphere v0.0.0-20210415100050-d0269b5646e6 h1:pOv7Apd4P3KEpNBHLV4E7tKlwHoInCU/bnPVadGSDxY= diff --git a/provisioner/ansible-local/provisioner_test.go b/provisioner/ansible-local/provisioner_test.go deleted file mode 100644 index 0cf4555a7..000000000 --- a/provisioner/ansible-local/provisioner_test.go +++ /dev/null @@ -1,497 +0,0 @@ -package ansiblelocal - -import ( - "context" - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" - - "fmt" - "os/exec" - - "github.com/hashicorp/packer-plugin-docker/builder/docker" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - builderT "github.com/hashicorp/packer/acctest" - "github.com/hashicorp/packer/provisioner/file" -) - -func TestProvisioner_Impl(t *testing.T) { - var raw interface{} - raw = &Provisioner{} - if _, ok := raw.(packersdk.Provisioner); !ok { - t.Fatalf("must be a Provisioner") - } -} - -func TestProvisionerPrepare_Defaults(t *testing.T) { - var p Provisioner - config := testConfig() - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.HasPrefix(filepath.ToSlash(p.config.StagingDir), DefaultStagingDir) { - t.Fatalf("unexpected staging dir %s, expected %s", - p.config.StagingDir, DefaultStagingDir) - } -} - -func TestProvisionerPrepare_PlaybookFile(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["playbook_file"] = "" - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_PlaybookFiles(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["playbook_file"] = "" - config["playbook_files"] = []string{} - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - config["playbook_files"] = []string{"some_other_file"} - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - p = Provisioner{} - config["playbook_file"] = playbook_file.Name() - config["playbook_files"] = []string{} - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - config["playbook_file"] = "" - config["playbook_files"] = []string{playbook_file.Name()} - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerProvision_PlaybookFiles(t *testing.T) { - var p Provisioner - config := testConfig() - - playbooks := createTempFiles("", 3) - defer removeFiles(playbooks...) - - config["playbook_files"] = playbooks - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - comm := &communicatorMock{} - if err := p.Provision(context.Background(), packersdk.TestUi(t), comm, make(map[string]interface{})); err != nil { - t.Fatalf("err: %s", err) - } - - assertPlaybooksUploaded(comm, playbooks) - assertPlaybooksExecuted(comm, playbooks) -} - -func TestProvisionerProvision_PlaybookFilesWithPlaybookDir(t *testing.T) { - var p Provisioner - config := testConfig() - - playbook_dir, err := ioutil.TempDir("", "") - if err != nil { - t.Fatalf("Failed to create playbook_dir: %s", err) - } - defer os.RemoveAll(playbook_dir) - playbooks := createTempFiles(playbook_dir, 3) - - playbookNames := make([]string, 0, len(playbooks)) - playbooksInPlaybookDir := make([]string, 0, len(playbooks)) - for _, playbook := range playbooks { - playbooksInPlaybookDir = append(playbooksInPlaybookDir, strings.TrimPrefix(playbook, playbook_dir)) - playbookNames = append(playbookNames, filepath.Base(playbook)) - } - - config["playbook_files"] = playbooks - config["playbook_dir"] = playbook_dir - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - comm := &communicatorMock{} - if err := p.Provision(context.Background(), packersdk.TestUi(t), comm, make(map[string]interface{})); err != nil { - t.Fatalf("err: %s", err) - } - - assertPlaybooksNotUploaded(comm, playbookNames) - assertPlaybooksExecuted(comm, playbooksInPlaybookDir) -} - -func TestProvisionerPrepare_InventoryFile(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["playbook_file"] = "" - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - inventory_file, err := ioutil.TempFile("", "inventory") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(inventory_file.Name()) - - config["inventory_file"] = inventory_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_Dirs(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["playbook_file"] = "" - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - config["playbook_paths"] = []string{playbook_file.Name()} - err = p.Prepare(config) - if err == nil { - t.Fatal("should error if playbook paths is not a dir") - } - - config["playbook_paths"] = []string{os.TempDir()} - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - config["role_paths"] = []string{playbook_file.Name()} - err = p.Prepare(config) - if err == nil { - t.Fatal("should error if role paths is not a dir") - } - - config["role_paths"] = []string{os.TempDir()} - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - config["group_vars"] = playbook_file.Name() - err = p.Prepare(config) - if err == nil { - t.Fatalf("should error if group_vars path is not a dir") - } - - config["group_vars"] = os.TempDir() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - config["host_vars"] = playbook_file.Name() - err = p.Prepare(config) - if err == nil { - t.Fatalf("should error if host_vars path is not a dir") - } - - config["host_vars"] = os.TempDir() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_CleanStagingDir(t *testing.T) { - var p Provisioner - config := testConfig() - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - config["clean_staging_directory"] = true - - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !p.config.CleanStagingDir { - t.Fatalf("expected clean_staging_directory to be set") - } -} - -func TestProvisionerProvisionDocker_PlaybookFiles(t *testing.T) { - testProvisionerProvisionDockerWithPlaybookFiles(t, playbookFilesDockerTemplate) -} - -func TestProvisionerProvisionDocker_PlaybookFilesWithPlaybookDir(t *testing.T) { - testProvisionerProvisionDockerWithPlaybookFiles(t, playbookFilesWithPlaybookDirDockerTemplate) -} - -func testProvisionerProvisionDockerWithPlaybookFiles(t *testing.T, templateString string) { - if os.Getenv("PACKER_ACC") == "" { - t.Skip("This test is only run with PACKER_ACC=1") - } - - // this should be a precheck - cmd := exec.Command("docker", "-v") - err := cmd.Run() - if err != nil { - t.Error("docker command not found; please make sure docker is installed") - } - - builderT.Test(t, builderT.TestCase{ - Builder: &docker.Builder{}, - Template: templateString, - Check: func(a []packersdk.Artifact) error { - - actualContent, err := ioutil.ReadFile("hello_world") - if err != nil { - return fmt.Errorf("Expected file not found: %s", err) - } - - expectedContent := "Hello world!" - if string(actualContent) != expectedContent { - return fmt.Errorf(`Unexpected file content: expected="%s", actual="%s"`, expectedContent, actualContent) - } - return nil - }, - Teardown: func() error { - os.Remove("hello_world") - return nil - }, - ProvisionerStore: packersdk.MapOfProvisioner{ - "ansible-local": func() (packersdk.Provisioner, error) { return &Provisioner{}, nil }, - "file": func() (packersdk.Provisioner, error) { return &file.Provisioner{}, nil }, - }, - }) -} - -func assertPlaybooksExecuted(comm *communicatorMock, playbooks []string) { - cmdIndex := 0 - for _, playbook := range playbooks { - playbook = filepath.ToSlash(playbook) - for ; cmdIndex < len(comm.startCommand); cmdIndex++ { - cmd := comm.startCommand[cmdIndex] - if strings.Contains(cmd, "ansible-playbook") && strings.Contains(cmd, playbook) { - break - } - } - if cmdIndex == len(comm.startCommand) { - panic(fmt.Sprintf("Playbook %s was not executed", playbook)) - } - } -} - -func assertPlaybooksUploaded(comm *communicatorMock, playbooks []string) { - uploadIndex := 0 - for _, playbook := range playbooks { - playbook = filepath.ToSlash(playbook) - for ; uploadIndex < len(comm.uploadDestination); uploadIndex++ { - dest := comm.uploadDestination[uploadIndex] - if strings.HasSuffix(dest, playbook) { - break - } - } - if uploadIndex == len(comm.uploadDestination) { - panic(fmt.Sprintf("Playbook %s was not uploaded", playbook)) - } - } -} - -func assertPlaybooksNotUploaded(comm *communicatorMock, playbooks []string) { - for _, playbook := range playbooks { - playbook = filepath.ToSlash(playbook) - for _, destination := range comm.uploadDestination { - if strings.HasSuffix(destination, playbook) { - panic(fmt.Sprintf("Playbook %s was uploaded", playbook)) - } - } - } -} - -func testConfig() map[string]interface{} { - m := make(map[string]interface{}) - return m -} - -func createTempFile(dir string) string { - file, err := ioutil.TempFile(dir, "") - if err != nil { - panic(fmt.Sprintf("err: %s", err)) - } - return file.Name() -} - -func createTempFiles(dir string, numFiles int) []string { - files := make([]string, 0, numFiles) - defer func() { - // Cleanup the files if not all were created. - if len(files) < numFiles { - for _, file := range files { - os.Remove(file) - } - } - }() - - for i := 0; i < numFiles; i++ { - files = append(files, createTempFile(dir)) - } - return files -} - -func removeFiles(files ...string) { - for _, file := range files { - os.Remove(file) - } -} - -const playbookFilesDockerTemplate = ` -{ - "builders": [ - { - "type": "test", - "image": "williamyeh/ansible:centos7", - "discard": true - } - ], - "provisioners": [ - { - "type": "ansible-local", - "playbook_files": [ - "test-fixtures/hello.yml", - "test-fixtures/world.yml" - ] - }, - { - "type": "file", - "source": "/tmp/hello_world", - "destination": "hello_world", - "direction": "download" - } - ] -} -` - -const playbookFilesWithPlaybookDirDockerTemplate = ` -{ - "builders": [ - { - "type": "test", - "image": "williamyeh/ansible:centos7", - "discard": true - } - ], - "provisioners": [ - { - "type": "ansible-local", - "playbook_files": [ - "test-fixtures/hello.yml", - "test-fixtures/world.yml" - ], - "playbook_dir": "test-fixtures" - }, - { - "type": "file", - "source": "/tmp/hello_world", - "destination": "hello_world", - "direction": "download" - } - ] -} -` diff --git a/provisioner/ansible-local/test-fixtures/hello.yml b/provisioner/ansible-local/test-fixtures/hello.yml deleted file mode 100644 index 6bb8797d8..000000000 --- a/provisioner/ansible-local/test-fixtures/hello.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- hosts: all - tasks: - - name: write Hello - shell: echo -n "Hello" >> /tmp/hello_world \ No newline at end of file diff --git a/provisioner/ansible-local/test-fixtures/world.yml b/provisioner/ansible-local/test-fixtures/world.yml deleted file mode 100644 index 98a205c7b..000000000 --- a/provisioner/ansible-local/test-fixtures/world.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- hosts: all - tasks: - - name: write world! - shell: echo -n " world!" >> /tmp/hello_world \ No newline at end of file diff --git a/provisioner/ansible-local/version/version.go b/provisioner/ansible-local/version/version.go deleted file mode 100644 index a4d455aad..000000000 --- a/provisioner/ansible-local/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var AnsibleLocalPluginVersion *version.PluginVersion - -func init() { - AnsibleLocalPluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/provisioner/ansible/examples/connection-plugin/2.4.x/packer.py b/provisioner/ansible/examples/connection-plugin/2.4.x/packer.py deleted file mode 100644 index ea4210d32..000000000 --- a/provisioner/ansible/examples/connection-plugin/2.4.x/packer.py +++ /dev/null @@ -1,186 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.connection.ssh import Connection as SSHConnection - -DOCUMENTATION = ''' - connection: packer - short_description: ssh based connections for powershell via packer - description: - - This connection plugin allows ansible to communicate to the target packer machines via ssh based connections for powershell. - author: Packer Community - version_added: na - options: - host: - description: Hostname/ip to connect to. - default: inventory_hostname - vars: - - name: ansible_host - - name: ansible_ssh_host - host_key_checking: - #constant: HOST_KEY_CHECKING - description: Determines if ssh should check host keys - type: boolean - ini: - - section: defaults - key: 'host_key_checking' - env: - - name: ANSIBLE_HOST_KEY_CHECKING - password: - description: Authentication password for the C(remote_user). Can be supplied as CLI option. - vars: - - name: ansible_password - - name: ansible_ssh_pass - ssh_args: - description: Arguments to pass to all ssh cli tools - default: '-C -o ControlMaster=auto -o ControlPersist=60s' - ini: - - section: 'ssh_connection' - key: 'ssh_args' - env: - - name: ANSIBLE_SSH_ARGS - ssh_common_args: - description: Common extra args for all ssh CLI tools - vars: - - name: ansible_ssh_common_args - ssh_executable: - default: ssh - description: - - This defines the location of the ssh binary. It defaults to `ssh` which will use the first ssh binary available in $PATH. - - This option is usually not required, it might be useful when access to system ssh is restricted, - or when using ssh wrappers to connect to remote hosts. - env: [{name: ANSIBLE_SSH_EXECUTABLE}] - ini: - - {key: ssh_executable, section: ssh_connection} - yaml: {key: ssh_connection.ssh_executable} - #const: ANSIBLE_SSH_EXECUTABLE - version_added: "2.2" - scp_extra_args: - description: Extra exclusive to the 'scp' CLI - vars: - - name: ansible_scp_extra_args - sftp_extra_args: - description: Extra exclusive to the 'sftp' CLI - vars: - - name: ansible_sftp_extra_args - ssh_extra_args: - description: Extra exclusive to the 'ssh' CLI - vars: - - name: ansible_ssh_extra_args - retries: - # constant: ANSIBLE_SSH_RETRIES - description: Number of attempts to connect. - default: 3 - type: integer - env: - - name: ANSIBLE_SSH_RETRIES - ini: - - section: connection - key: retries - - section: ssh_connection - key: retries - port: - description: Remote port to connect to. - type: int - default: 22 - ini: - - section: defaults - key: remote_port - env: - - name: ANSIBLE_REMOTE_PORT - vars: - - name: ansible_port - - name: ansible_ssh_port - remote_user: - description: - - User name with which to login to the remote server, normally set by the remote_user keyword. - - If no user is supplied, Ansible will let the ssh client binary choose the user as it normally - ini: - - section: defaults - key: remote_user - env: - - name: ANSIBLE_REMOTE_USER - vars: - - name: ansible_user - - name: ansible_ssh_user - pipelining: - default: ANSIBLE_PIPELINING - description: - - Pipelining reduces the number of SSH operations required to execute a module on the remote server, - by executing many Ansible modules without actual file transfer. - - This can result in a very significant performance improvement when enabled. - - However this conflicts with privilege escalation (become). - For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts, - which is why this feature is disabled by default. - env: - - name: ANSIBLE_PIPELINING - #- name: ANSIBLE_SSH_PIPELINING - ini: - - section: defaults - key: pipelining - #- section: ssh_connection - # key: pipelining - type: boolean - vars: - - name: ansible_pipelining - - name: ansible_ssh_pipelining - private_key_file: - description: - - Path to private key file to use for authentication - ini: - - section: defaults - key: private_key_file - env: - - name: ANSIBLE_PRIVATE_KEY_FILE - vars: - - name: ansible_private_key_file - - name: ansible_ssh_private_key_file - control_path: - default: null - description: - - This is the location to save ssh's ControlPath sockets, it uses ssh's variable substitution. - - Since 2.3, if null, ansible will generate a unique hash. Use `%(directory)s` to indicate where to use the control dir path setting. - env: - - name: ANSIBLE_SSH_CONTROL_PATH - ini: - - key: control_path - section: ssh_connection - control_path_dir: - default: ~/.ansible/cp - description: - - This sets the directory to use for ssh control path if the control path setting is null. - - Also, provides the `%(directory)s` variable for the control path setting. - env: - - name: ANSIBLE_SSH_CONTROL_PATH_DIR - ini: - - section: ssh_connection - key: control_path_dir - sftp_batch_mode: - default: True - description: 'TODO: write it' - env: [{name: ANSIBLE_SFTP_BATCH_MODE}] - ini: - - {key: sftp_batch_mode, section: ssh_connection} - type: boolean - scp_if_ssh: - default: smart - description: - - "Prefered method to use when transfering files over ssh" - - When set to smart, Ansible will try them until one succeeds or they all fail - - If set to True, it will force 'scp', if False it will use 'sftp' - env: [{name: ANSIBLE_SCP_IF_SSH}] - ini: - - {key: scp_if_ssh, section: ssh_connection} -''' - -class Connection(SSHConnection): - ''' ssh based connections for powershell via packer''' - - transport = 'packer' - has_pipelining = True - become_methods = [] - allow_executable = False - module_implementation_preferences = ('.ps1', '') - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) \ No newline at end of file diff --git a/provisioner/ansible/examples/connection-plugin/2.5.x/packer.py b/provisioner/ansible/examples/connection-plugin/2.5.x/packer.py deleted file mode 100644 index e133aeea4..000000000 --- a/provisioner/ansible/examples/connection-plugin/2.5.x/packer.py +++ /dev/null @@ -1,204 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.connection.ssh import Connection as SSHConnection - -DOCUMENTATION = ''' - connection: packer - short_description: ssh based connections for powershell via packer - description: - - This connection plugin allows ansible to communicate to the target packer machines via ssh based connections for powershell. - author: Packer Community - version_added: na - options: - host: - description: Hostname/ip to connect to. - default: inventory_hostname - vars: - - name: ansible_host - - name: ansible_ssh_host - host_key_checking: - description: Determines if ssh should check host keys - type: boolean - ini: - - section: defaults - key: 'host_key_checking' - - section: ssh_connection - key: 'host_key_checking' - version_added: '2.5' - env: - - name: ANSIBLE_HOST_KEY_CHECKING - - name: ANSIBLE_SSH_HOST_KEY_CHECKING - version_added: '2.5' - vars: - - name: ansible_host_key_checking - version_added: '2.5' - - name: ansible_ssh_host_key_checking - version_added: '2.5' - password: - description: Authentication password for the C(remote_user). Can be supplied as CLI option. - vars: - - name: ansible_password - - name: ansible_ssh_pass - ssh_args: - description: Arguments to pass to all ssh cli tools - default: '-C -o ControlMaster=auto -o ControlPersist=60s' - ini: - - section: 'ssh_connection' - key: 'ssh_args' - env: - - name: ANSIBLE_SSH_ARGS - ssh_common_args: - description: Common extra args for all ssh CLI tools - vars: - - name: ansible_ssh_common_args - ssh_executable: - default: ssh - description: - - This defines the location of the ssh binary. It defaults to `ssh` which will use the first ssh binary available in $PATH. - - This option is usually not required, it might be useful when access to system ssh is restricted, - or when using ssh wrappers to connect to remote hosts. - env: [{name: ANSIBLE_SSH_EXECUTABLE}] - ini: - - {key: ssh_executable, section: ssh_connection} - yaml: {key: ssh_connection.ssh_executable} - #const: ANSIBLE_SSH_EXECUTABLE - version_added: "2.2" - scp_extra_args: - description: Extra exclusive to the 'scp' CLI - vars: - - name: ansible_scp_extra_args - sftp_extra_args: - description: Extra exclusive to the 'sftp' CLI - vars: - - name: ansible_sftp_extra_args - ssh_extra_args: - description: Extra exclusive to the 'ssh' CLI - vars: - - name: ansible_ssh_extra_args - retries: - # constant: ANSIBLE_SSH_RETRIES - description: Number of attempts to connect. - default: 3 - type: integer - env: - - name: ANSIBLE_SSH_RETRIES - ini: - - section: connection - key: retries - - section: ssh_connection - key: retries - port: - description: Remote port to connect to. - type: int - default: 22 - ini: - - section: defaults - key: remote_port - env: - - name: ANSIBLE_REMOTE_PORT - vars: - - name: ansible_port - - name: ansible_ssh_port - remote_user: - description: - - User name with which to login to the remote server, normally set by the remote_user keyword. - - If no user is supplied, Ansible will let the ssh client binary choose the user as it normally - ini: - - section: defaults - key: remote_user - env: - - name: ANSIBLE_REMOTE_USER - vars: - - name: ansible_user - - name: ansible_ssh_user - pipelining: - default: ANSIBLE_PIPELINING - description: - - Pipelining reduces the number of SSH operations required to execute a module on the remote server, - by executing many Ansible modules without actual file transfer. - - This can result in a very significant performance improvement when enabled. - - However this conflicts with privilege escalation (become). - For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts, - which is why this feature is disabled by default. - env: - - name: ANSIBLE_PIPELINING - #- name: ANSIBLE_SSH_PIPELINING - ini: - - section: defaults - key: pipelining - #- section: ssh_connection - # key: pipelining - type: boolean - vars: - - name: ansible_pipelining - - name: ansible_ssh_pipelining - private_key_file: - description: - - Path to private key file to use for authentication - ini: - - section: defaults - key: private_key_file - env: - - name: ANSIBLE_PRIVATE_KEY_FILE - vars: - - name: ansible_private_key_file - - name: ansible_ssh_private_key_file - control_path: - default: null - description: - - This is the location to save ssh's ControlPath sockets, it uses ssh's variable substitution. - - Since 2.3, if null, ansible will generate a unique hash. Use `%(directory)s` to indicate where to use the control dir path setting. - env: - - name: ANSIBLE_SSH_CONTROL_PATH - ini: - - key: control_path - section: ssh_connection - control_path_dir: - default: ~/.ansible/cp - description: - - This sets the directory to use for ssh control path if the control path setting is null. - - Also, provides the `%(directory)s` variable for the control path setting. - env: - - name: ANSIBLE_SSH_CONTROL_PATH_DIR - ini: - - section: ssh_connection - key: control_path_dir - sftp_batch_mode: - default: True - description: 'TODO: write it' - env: [{name: ANSIBLE_SFTP_BATCH_MODE}] - ini: - - {key: sftp_batch_mode, section: ssh_connection} - type: boolean - scp_if_ssh: - default: smart - description: - - "Prefered method to use when transfering files over ssh" - - When set to smart, Ansible will try them until one succeeds or they all fail - - If set to True, it will force 'scp', if False it will use 'sftp' - env: [{name: ANSIBLE_SCP_IF_SSH}] - ini: - - {key: scp_if_ssh, section: ssh_connection} - use_tty: - version_added: '2.5' - default: True - description: add -tt to ssh commands to force tty allocation - env: [{name: ANSIBLE_SSH_USETTY}] - ini: - - {key: usetty, section: ssh_connection} - type: boolean - yaml: {key: connection.usetty} -''' - -class Connection(SSHConnection): - ''' ssh based connections for powershell via packer''' - - transport = 'packer' - has_pipelining = True - become_methods = [] - allow_executable = False - module_implementation_preferences = ('.ps1', '') - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) \ No newline at end of file diff --git a/provisioner/ansible/examples/connection-plugin/2.6.x/packer.py b/provisioner/ansible/examples/connection-plugin/2.6.x/packer.py deleted file mode 100644 index 8ef8c0548..000000000 --- a/provisioner/ansible/examples/connection-plugin/2.6.x/packer.py +++ /dev/null @@ -1,218 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.connection.ssh import Connection as SSHConnection - -DOCUMENTATION = ''' - connection: packer - short_description: ssh based connections for powershell via packer - description: - - This connection plugin allows ansible to communicate to the target packer machines via ssh based connections for powershell. - author: Packer Community - version_added: na - options: - host: - description: Hostname/ip to connect to. - default: inventory_hostname - vars: - - name: ansible_host - - name: ansible_ssh_host - host_key_checking: - description: Determines if ssh should check host keys - type: boolean - ini: - - section: defaults - key: 'host_key_checking' - - section: ssh_connection - key: 'host_key_checking' - version_added: '2.5' - env: - - name: ANSIBLE_HOST_KEY_CHECKING - - name: ANSIBLE_SSH_HOST_KEY_CHECKING - version_added: '2.5' - vars: - - name: ansible_host_key_checking - version_added: '2.5' - - name: ansible_ssh_host_key_checking - version_added: '2.5' - password: - description: Authentication password for the C(remote_user). Can be supplied as CLI option. - vars: - - name: ansible_password - - name: ansible_ssh_pass - ssh_args: - description: Arguments to pass to all ssh cli tools - default: '-C -o ControlMaster=auto -o ControlPersist=60s' - ini: - - section: 'ssh_connection' - key: 'ssh_args' - env: - - name: ANSIBLE_SSH_ARGS - ssh_common_args: - description: Common extra args for all ssh CLI tools - vars: - - name: ansible_ssh_common_args - ssh_executable: - default: ssh - description: - - This defines the location of the ssh binary. It defaults to ``ssh`` which will use the first ssh binary available in $PATH. - - This option is usually not required, it might be useful when access to system ssh is restricted, - or when using ssh wrappers to connect to remote hosts. - env: [{name: ANSIBLE_SSH_EXECUTABLE}] - ini: - - {key: ssh_executable, section: ssh_connection} - #const: ANSIBLE_SSH_EXECUTABLE - version_added: "2.2" - sftp_executable: - default: sftp - description: - - This defines the location of the sftp binary. It defaults to ``sftp`` which will use the first binary available in $PATH. - env: [{name: ANSIBLE_SFTP_EXECUTABLE}] - ini: - - {key: sftp_executable, section: ssh_connection} - version_added: "2.6" - scp_executable: - default: scp - description: - - This defines the location of the scp binary. It defaults to `scp` which will use the first binary available in $PATH. - env: [{name: ANSIBLE_SCP_EXECUTABLE}] - ini: - - {key: scp_executable, section: ssh_connection} - version_added: "2.6" - scp_extra_args: - description: Extra exclusive to the ``scp`` CLI - vars: - - name: ansible_scp_extra_args - sftp_extra_args: - description: Extra exclusive to the ``sftp`` CLI - vars: - - name: ansible_sftp_extra_args - ssh_extra_args: - description: Extra exclusive to the 'ssh' CLI - vars: - - name: ansible_ssh_extra_args - retries: - # constant: ANSIBLE_SSH_RETRIES - description: Number of attempts to connect. - default: 3 - type: integer - env: - - name: ANSIBLE_SSH_RETRIES - ini: - - section: connection - key: retries - - section: ssh_connection - key: retries - port: - description: Remote port to connect to. - type: int - default: 22 - ini: - - section: defaults - key: remote_port - env: - - name: ANSIBLE_REMOTE_PORT - vars: - - name: ansible_port - - name: ansible_ssh_port - remote_user: - description: - - User name with which to login to the remote server, normally set by the remote_user keyword. - - If no user is supplied, Ansible will let the ssh client binary choose the user as it normally - ini: - - section: defaults - key: remote_user - env: - - name: ANSIBLE_REMOTE_USER - vars: - - name: ansible_user - - name: ansible_ssh_user - pipelining: - default: ANSIBLE_PIPELINING - description: - - Pipelining reduces the number of SSH operations required to execute a module on the remote server, - by executing many Ansible modules without actual file transfer. - - This can result in a very significant performance improvement when enabled. - - However this conflicts with privilege escalation (become). - For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts, - which is why this feature is disabled by default. - env: - - name: ANSIBLE_PIPELINING - #- name: ANSIBLE_SSH_PIPELINING - ini: - - section: defaults - key: pipelining - #- section: ssh_connection - # key: pipelining - type: boolean - vars: - - name: ansible_pipelining - - name: ansible_ssh_pipelining - private_key_file: - description: - - Path to private key file to use for authentication - ini: - - section: defaults - key: private_key_file - env: - - name: ANSIBLE_PRIVATE_KEY_FILE - vars: - - name: ansible_private_key_file - - name: ansible_ssh_private_key_file - control_path: - description: - - This is the location to save ssh's ControlPath sockets, it uses ssh's variable substitution. - - Since 2.3, if null, ansible will generate a unique hash. Use `%(directory)s` to indicate where to use the control dir path setting. - env: - - name: ANSIBLE_SSH_CONTROL_PATH - ini: - - key: control_path - section: ssh_connection - control_path_dir: - default: ~/.ansible/cp - description: - - This sets the directory to use for ssh control path if the control path setting is null. - - Also, provides the `%(directory)s` variable for the control path setting. - env: - - name: ANSIBLE_SSH_CONTROL_PATH_DIR - ini: - - section: ssh_connection - key: control_path_dir - sftp_batch_mode: - default: 'yes' - description: 'TODO: write it' - env: [{name: ANSIBLE_SFTP_BATCH_MODE}] - ini: - - {key: sftp_batch_mode, section: ssh_connection} - type: bool - scp_if_ssh: - default: smart - description: - - "Prefered method to use when transfering files over ssh" - - When set to smart, Ansible will try them until one succeeds or they all fail - - If set to True, it will force 'scp', if False it will use 'sftp' - env: [{name: ANSIBLE_SCP_IF_SSH}] - ini: - - {key: scp_if_ssh, section: ssh_connection} - use_tty: - version_added: '2.5' - default: 'yes' - description: add -tt to ssh commands to force tty allocation - env: [{name: ANSIBLE_SSH_USETTY}] - ini: - - {key: usetty, section: ssh_connection} - type: bool - yaml: {key: connection.usetty} -''' - -class Connection(SSHConnection): - ''' ssh based connections for powershell via packer''' - - transport = 'packer' - has_pipelining = True - become_methods = [] - allow_executable = False - module_implementation_preferences = ('.ps1', '') - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) \ No newline at end of file diff --git a/provisioner/ansible/provisioner_test.go b/provisioner/ansible/provisioner_test.go deleted file mode 100644 index 12354f91f..000000000 --- a/provisioner/ansible/provisioner_test.go +++ /dev/null @@ -1,781 +0,0 @@ -// +build !windows - -package ansible - -import ( - "bytes" - "context" - "crypto/rand" - "fmt" - "io" - "io/ioutil" - "os" - "path" - "strings" - "testing" - - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - confighelper "github.com/hashicorp/packer-plugin-sdk/template/config" - "github.com/stretchr/testify/assert" -) - -// Be sure to remove the Ansible stub file in each test with: -// defer os.Remove(config["command"].(string)) -func testConfig(t *testing.T) map[string]interface{} { - m := make(map[string]interface{}) - wd, err := os.Getwd() - if err != nil { - t.Fatalf("err: %s", err) - } - ansible_stub := path.Join(wd, "packer-ansible-stub.sh") - - err = ioutil.WriteFile(ansible_stub, []byte("#!/usr/bin/env bash\necho ansible 1.6.0"), 0777) - if err != nil { - t.Fatalf("err: %s", err) - } - m["command"] = ansible_stub - - return m -} - -func TestProvisioner_Impl(t *testing.T) { - var raw interface{} - raw = &Provisioner{} - if _, ok := raw.(packersdk.Provisioner); !ok { - t.Fatalf("must be a Provisioner") - } -} - -func TestProvisionerPrepare_Defaults(t *testing.T) { - var p Provisioner - config := testConfig(t) - defer os.Remove(config["command"].(string)) - - err := p.Prepare(config) - if err == nil { - t.Fatalf("should have error") - } - - hostkey_file, err := ioutil.TempFile("", "hostkey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(hostkey_file.Name()) - - publickey_file, err := ioutil.TempFile("", "publickey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(publickey_file.Name()) - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["ssh_host_key_file"] = hostkey_file.Name() - config["ssh_authorized_key_file"] = publickey_file.Name() - config["playbook_file"] = playbook_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - err = os.Unsetenv("USER") - if err != nil { - t.Fatalf("err: %s", err) - } - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_PlaybookFile(t *testing.T) { - var p Provisioner - config := testConfig(t) - defer os.Remove(config["command"].(string)) - - hostkey_file, err := ioutil.TempFile("", "hostkey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(hostkey_file.Name()) - - publickey_file, err := ioutil.TempFile("", "publickey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(publickey_file.Name()) - - config["ssh_host_key_file"] = hostkey_file.Name() - config["ssh_authorized_key_file"] = publickey_file.Name() - - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["playbook_file"] = playbook_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_HostKeyFile(t *testing.T) { - var p Provisioner - config := testConfig(t) - defer os.Remove(config["command"].(string)) - - publickey_file, err := ioutil.TempFile("", "publickey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(publickey_file.Name()) - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - filename := make([]byte, 10) - n, err := io.ReadFull(rand.Reader, filename) - if n != len(filename) || err != nil { - t.Fatal("could not create random file name") - } - - config["ssh_host_key_file"] = fmt.Sprintf("%x", filename) - config["ssh_authorized_key_file"] = publickey_file.Name() - config["playbook_file"] = playbook_file.Name() - - err = p.Prepare(config) - if err == nil { - t.Fatal("should error if ssh_host_key_file does not exist") - } - - hostkey_file, err := ioutil.TempFile("", "hostkey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(hostkey_file.Name()) - - config["ssh_host_key_file"] = hostkey_file.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_AuthorizedKeyFile(t *testing.T) { - var p Provisioner - config := testConfig(t) - defer os.Remove(config["command"].(string)) - - hostkey_file, err := ioutil.TempFile("", "hostkey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(hostkey_file.Name()) - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - filename := make([]byte, 10) - n, err := io.ReadFull(rand.Reader, filename) - if n != len(filename) || err != nil { - t.Fatal("could not create random file name") - } - - config["ssh_host_key_file"] = hostkey_file.Name() - config["playbook_file"] = playbook_file.Name() - config["ssh_authorized_key_file"] = fmt.Sprintf("%x", filename) - - err = p.Prepare(config) - if err == nil { - t.Errorf("should error if ssh_authorized_key_file does not exist") - } - - publickey_file, err := ioutil.TempFile("", "publickey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(publickey_file.Name()) - - config["ssh_authorized_key_file"] = publickey_file.Name() - err = p.Prepare(config) - if err != nil { - t.Errorf("err: %s", err) - } -} - -func TestProvisionerPrepare_LocalPort(t *testing.T) { - var p Provisioner - config := testConfig(t) - defer os.Remove(config["command"].(string)) - - hostkey_file, err := ioutil.TempFile("", "hostkey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(hostkey_file.Name()) - - publickey_file, err := ioutil.TempFile("", "publickey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(publickey_file.Name()) - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["ssh_host_key_file"] = hostkey_file.Name() - config["ssh_authorized_key_file"] = publickey_file.Name() - config["playbook_file"] = playbook_file.Name() - - config["local_port"] = 65537 - err = p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["local_port"] = 22222 - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_InventoryDirectory(t *testing.T) { - var p Provisioner - config := testConfig(t) - defer os.Remove(config["command"].(string)) - - hostkey_file, err := ioutil.TempFile("", "hostkey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(hostkey_file.Name()) - - publickey_file, err := ioutil.TempFile("", "publickey") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(publickey_file.Name()) - - playbook_file, err := ioutil.TempFile("", "playbook") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(playbook_file.Name()) - - config["ssh_host_key_file"] = hostkey_file.Name() - config["ssh_authorized_key_file"] = publickey_file.Name() - config["playbook_file"] = playbook_file.Name() - - config["inventory_directory"] = "doesnotexist" - err = p.Prepare(config) - if err == nil { - t.Errorf("should error if inventory_directory does not exist") - } - - inventoryDirectory, err := ioutil.TempDir("", "some_inventory_dir") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.Remove(inventoryDirectory) - - config["inventory_directory"] = inventoryDirectory - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestAnsibleGetVersion(t *testing.T) { - if os.Getenv("PACKER_ACC") == "" { - t.Skip("This test is only run with PACKER_ACC=1 and it requires Ansible to be installed") - } - - var p Provisioner - p.config.Command = "ansible-playbook" - err := p.getVersion() - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestAnsibleGetVersionError(t *testing.T) { - var p Provisioner - p.config.Command = "./test-fixtures/exit1" - err := p.getVersion() - if err == nil { - t.Fatal("Should return error") - } - if !strings.Contains(err.Error(), "./test-fixtures/exit1 --version") { - t.Fatal("Error message should include command name") - } -} - -func TestAnsibleLongMessages(t *testing.T) { - if os.Getenv("PACKER_ACC") == "" { - t.Skip("This test is only run with PACKER_ACC=1 and it requires Ansible to be installed") - } - - var p Provisioner - p.config.Command = "ansible-playbook" - p.config.PlaybookFile = "./test-fixtures/long-debug-message.yml" - err := p.Prepare() - if err != nil { - t.Fatalf("err: %s", err) - } - - comm := &packersdk.MockCommunicator{} - ui := &packersdk.BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - } - - err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestCreateInventoryFile(t *testing.T) { - type inventoryFileTestCases struct { - AnsibleVersion uint - User string - Groups []string - EmptyGroups []string - UseProxy confighelper.Trilean - GeneratedData map[string]interface{} - Expected string - } - - TestCases := []inventoryFileTestCases{ - { - AnsibleVersion: 1, - User: "testuser", - UseProxy: confighelper.TriFalse, - GeneratedData: basicGenData(nil), - Expected: "default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234\n", - }, - { - AnsibleVersion: 2, - User: "testuser", - UseProxy: confighelper.TriFalse, - GeneratedData: basicGenData(nil), - Expected: "default ansible_host=123.45.67.89 ansible_user=testuser ansible_port=1234\n", - }, - { - AnsibleVersion: 1, - User: "testuser", - Groups: []string{"Group1", "Group2"}, - UseProxy: confighelper.TriFalse, - GeneratedData: basicGenData(nil), - Expected: `default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -[Group1] -default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -[Group2] -default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -`, - }, - { - AnsibleVersion: 1, - User: "testuser", - EmptyGroups: []string{"Group1", "Group2"}, - UseProxy: confighelper.TriFalse, - GeneratedData: basicGenData(nil), - Expected: `default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -[Group1] -[Group2] -`, - }, - { - AnsibleVersion: 1, - User: "testuser", - Groups: []string{"Group1", "Group2"}, - EmptyGroups: []string{"Group3"}, - UseProxy: confighelper.TriFalse, - GeneratedData: basicGenData(nil), - Expected: `default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -[Group1] -default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -[Group2] -default ansible_ssh_host=123.45.67.89 ansible_ssh_user=testuser ansible_ssh_port=1234 -[Group3] -`, - }, - { - AnsibleVersion: 2, - User: "testuser", - UseProxy: confighelper.TriFalse, - GeneratedData: basicGenData(map[string]interface{}{ - "ConnType": "winrm", - "Password": "12345", - }), - Expected: "default ansible_host=123.45.67.89 ansible_connection=winrm ansible_winrm_transport=basic ansible_shell_type=powershell ansible_user=testuser ansible_port=1234\n", - }, - } - - for _, tc := range TestCases { - var p Provisioner - p.Prepare(testConfig(t)) - defer os.Remove(p.config.Command) - p.ansibleMajVersion = tc.AnsibleVersion - p.config.User = tc.User - p.config.Groups = tc.Groups - p.config.EmptyGroups = tc.EmptyGroups - p.config.UseProxy = tc.UseProxy - p.generatedData = tc.GeneratedData - - err := p.createInventoryFile() - if err != nil { - t.Fatalf("error creating config using localhost and local port proxy") - } - if p.config.InventoryFile == "" { - t.Fatalf("No inventory file was created") - } - defer os.Remove(p.config.InventoryFile) - f, err := ioutil.ReadFile(p.config.InventoryFile) - if err != nil { - t.Fatalf("couldn't read created inventoryfile: %s", err) - } - - expected := tc.Expected - if fmt.Sprintf("%s", f) != expected { - t.Fatalf("File didn't match expected:\n\n expected: \n%s\n; recieved: \n%s\n", expected, f) - } - } -} - -func basicGenData(input map[string]interface{}) map[string]interface{} { - gd := map[string]interface{}{ - "Host": "123.45.67.89", - "Port": int64(1234), - "ConnType": "ssh", - "SSHPrivateKeyFile": "", - "SSHPrivateKey": "asdf", - "SSHAgentAuth": false, - "User": "PartyPacker", - "PackerHTTPAddr": commonsteps.HttpAddrNotImplemented, - "PackerHTTPIP": commonsteps.HttpIPNotImplemented, - "PackerHTTPPort": commonsteps.HttpPortNotImplemented, - } - if input == nil { - return gd - } - for k, v := range input { - gd[k] = v - } - return gd -} - -func TestCreateCmdArgs(t *testing.T) { - type testcase struct { - TestName string - PackerBuildName string - PackerBuilderType string - UseProxy confighelper.Trilean - generatedData map[string]interface{} - AnsibleSSHExtraArgs []string - ExtraArguments []string - AnsibleEnvVars []string - callArgs []string // httpAddr inventory playbook privKeyFile - ExpectedArgs []string - ExpectedEnvVars []string - } - TestCases := []testcase{ - { - // SSH with private key and an extra argument. - TestName: "SSH with private key and an extra argument", - PackerBuildName: "packerparty", - generatedData: basicGenData(nil), - ExtraArguments: []string{"-e", "hello-world"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", "/path/to/privkey.pem"}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "ansible_ssh_private_key_file=/path/to/privkey.pem", "--ssh-extra-args", "'-o IdentitiesOnly=yes'", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - // SSH with private key and an extra argument. - TestName: "SSH with private key and an extra argument and a ssh extra argument", - PackerBuildName: "packerparty", - generatedData: basicGenData(nil), - ExtraArguments: []string{"-e", "hello-world"}, - AnsibleSSHExtraArgs: []string{"-o IdentitiesOnly=no"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", "/path/to/privkey.pem"}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "--ssh-extra-args", "'-o IdentitiesOnly=no'", "-e", "ansible_ssh_private_key_file=/path/to/privkey.pem", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - TestName: "SSH with private key and an extra argument and UseProxy", - PackerBuildName: "packerparty", - UseProxy: confighelper.TriTrue, - generatedData: basicGenData(nil), - ExtraArguments: []string{"-e", "hello-world"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", "/path/to/privkey.pem"}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "ansible_ssh_private_key_file=/path/to/privkey.pem", "--ssh-extra-args", "'-o IdentitiesOnly=yes'", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{}, - }, - { - // Winrm, but no_proxy is unset so we don't do anything with ansible_password. - TestName: "Winrm, but no_proxy is unset so we don't do anything with ansible_password", - PackerBuildName: "packerparty", - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "winrm", - }), - ExtraArguments: []string{"-e", "hello-world"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - // HTTPAddr should be set. No env vars. - TestName: "HTTPAddr should be set. No env vars", - PackerBuildName: "packerparty", - ExtraArguments: []string{"-e", "hello-world"}, - generatedData: basicGenData(map[string]interface{}{ - "PackerHTTPAddr": "123.45.67.89", - }), - callArgs: []string{"123.45.67.89", "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "packer_http_addr=123.45.67.89", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{}, - }, - { - // Add ansible_password for proxyless winrm connection. - TestName: "Add ansible_password for proxyless winrm connection.", - UseProxy: confighelper.TriFalse, - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "winrm", - "Password": "ilovebananapancakes", - "PackerHTTPAddr": "123.45.67.89", - }), - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{"123.45.67.89", "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_builder_type=fakebuilder", "-e", "packer_http_addr=123.45.67.89", "-e", "ansible_password=ilovebananapancakes", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - // Neither special ssh stuff, nor special windows stuff. This is docker! - TestName: "Neither special ssh stuff, nor special windows stuff. This is docker!", - PackerBuildName: "packerparty", - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "docker", - }), - ExtraArguments: []string{"-e", "hello-world"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - // Windows, no proxy, with extra vars. - TestName: "Windows, no proxy, with extra vars.", - UseProxy: confighelper.TriFalse, - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "winrm", - "Password": "ilovebananapancakes", - "PackerHTTPAddr": "123.45.67.89", - }), - ExtraArguments: []string{"-e", "hello-world"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{"123.45.67.89", "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_builder_type=fakebuilder", "-e", "packer_http_addr=123.45.67.89", "-e", "ansible_password=ilovebananapancakes", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - // SSH, use Password. - TestName: "SSH, use ansible_password.", - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "ssh", - "Password": "ilovebananapancakes", - "PackerHTTPAddr": "123.45.67.89", - }), - ExtraArguments: []string{"-e", "hello-world", "-e", "ansible_password=ilovebananapancakes"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - callArgs: []string{"123.45.67.89", "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_builder_type=fakebuilder", "-e", "packer_http_addr=123.45.67.89", "-e", "hello-world", "-e", "ansible_password=ilovebananapancakes", "-e", "ansible_host_key_checking=False", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas"}, - }, - { - // SSH, use Password . - TestName: "SSH, already in ENV ansible_host_key_checking.", - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "ssh", - "Password": "ilovebananapancakes", - "PackerHTTPAddr": "123.45.67.89", - }), - ExtraArguments: []string{"-e", "hello-world", "-e", "ansible_password=ilovebananapancakes"}, - AnsibleEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas", "ANSIBLE_HOST_KEY_CHECKING=False"}, - callArgs: []string{"123.45.67.89", "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_builder_type=fakebuilder", "-e", "packer_http_addr=123.45.67.89", "-e", "hello-world", "-e", "ansible_password=ilovebananapancakes", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{"ENV_1=pancakes", "ENV_2=bananas", "ANSIBLE_HOST_KEY_CHECKING=False"}, - }, - { - TestName: "Use PrivateKey", - PackerBuildName: "packerparty", - UseProxy: confighelper.TriTrue, - generatedData: basicGenData(nil), - ExtraArguments: []string{"-e", "hello-world"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", "/path/to/privkey.pem"}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "ansible_ssh_private_key_file=/path/to/privkey.pem", "--ssh-extra-args", "'-o IdentitiesOnly=yes'", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{}, - }, - { - TestName: "Use PrivateKey and SSH Extra Arg", - PackerBuildName: "packerparty", - UseProxy: confighelper.TriTrue, - generatedData: basicGenData(nil), - AnsibleSSHExtraArgs: []string{"-o IdentitiesOnly=no"}, - ExtraArguments: []string{"-e", "hello-world"}, - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", "/path/to/privkey.pem"}, - ExpectedArgs: []string{"-e", "packer_build_name=\"packerparty\"", "-e", "packer_builder_type=fakebuilder", "-e", "ansible_ssh_private_key_file=/path/to/privkey.pem", "--ssh-extra-args", "'-o IdentitiesOnly=no'", "-e", "hello-world", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{}, - }, - { - TestName: "Use SSH Agent", - UseProxy: confighelper.TriTrue, - generatedData: basicGenData(nil), - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_builder_type=fakebuilder", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{}, - }, - { - // No builder name. This shouldn't cause an error, it just shouldn't be set. HCL, yo. - TestName: "No builder name. This shouldn't cause an error, it just shouldn't be set. HCL, yo.", - generatedData: basicGenData(nil), - callArgs: []string{commonsteps.HttpAddrNotImplemented, "/var/inventory", "test-playbook.yml", ""}, - ExpectedArgs: []string{"-e", "packer_builder_type=fakebuilder", "-i", "/var/inventory", "test-playbook.yml"}, - ExpectedEnvVars: []string{}, - }, - } - - for _, tc := range TestCases { - var p Provisioner - p.Prepare(testConfig(t)) - defer os.Remove(p.config.Command) - p.config.UseProxy = tc.UseProxy - p.config.PackerBuilderType = "fakebuilder" - p.config.PackerBuildName = tc.PackerBuildName - p.generatedData = tc.generatedData - p.config.AnsibleSSHExtraArgs = tc.AnsibleSSHExtraArgs - p.config.ExtraArguments = tc.ExtraArguments - p.config.AnsibleEnvVars = tc.AnsibleEnvVars - - args, envVars := p.createCmdArgs(tc.callArgs[0], tc.callArgs[1], tc.callArgs[2], tc.callArgs[3]) - assert.ElementsMatch(t, args, tc.ExpectedArgs, - "TestName: %s\nArgs didn't match expected:\nexpected: \n%s\n; recieved: \n%s\n", tc.TestName, tc.ExpectedArgs, args) - assert.ElementsMatch(t, envVars, tc.ExpectedEnvVars, - "TestName: %s\nArgs didn't match expected:\n\nEnvVars didn't match expected:\n\n expected: \n%s\n; recieved: \n%s\n", tc.TestName, tc.ExpectedEnvVars, envVars) - assert.EqualValues(t, tc.callArgs[2], args[len(args)-1], - "TestName: %s\nPlayBook File Not Returned as last element: \nexpected: %s\nrecieved: %s\n", tc.TestName, tc.callArgs[2], args[len(args)-1]) - } -} - -func TestUseProxy(t *testing.T) { - type testcase struct { - UseProxy confighelper.Trilean - generatedData map[string]interface{} - expectedSetupAdapterCalled bool - explanation string - } - - tcs := []testcase{ - { - explanation: "use_proxy is true; we should set up adapter", - UseProxy: confighelper.TriTrue, - generatedData: basicGenData(nil), - expectedSetupAdapterCalled: true, - }, - { - explanation: "use_proxy is false but no IP addr is available; we should set up adapter anyway.", - UseProxy: confighelper.TriFalse, - generatedData: basicGenData(map[string]interface{}{ - "Host": "", - "Port": nil, - }), - expectedSetupAdapterCalled: true, - }, - { - explanation: "use_proxy is false; we shouldn't set up adapter.", - UseProxy: confighelper.TriFalse, - generatedData: basicGenData(nil), - expectedSetupAdapterCalled: false, - }, - { - explanation: "use_proxy is false but connType isn't ssh or winrm.", - UseProxy: confighelper.TriFalse, - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "docker", - }), - expectedSetupAdapterCalled: true, - }, - { - explanation: "use_proxy is unset; we should default to setting up the adapter (for now).", - UseProxy: confighelper.TriUnset, - generatedData: basicGenData(nil), - expectedSetupAdapterCalled: true, - }, - { - explanation: "use_proxy is false and connType is winRM. we should not set up the adapter.", - UseProxy: confighelper.TriFalse, - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "winrm", - }), - expectedSetupAdapterCalled: false, - }, - { - explanation: "use_proxy is unset and connType is winRM. we should set up the adapter.", - UseProxy: confighelper.TriUnset, - generatedData: basicGenData(map[string]interface{}{ - "ConnType": "winrm", - }), - expectedSetupAdapterCalled: true, - }, - } - - for _, tc := range tcs { - var p Provisioner - p.Prepare(testConfig(t)) - p.config.UseProxy = tc.UseProxy - defer os.Remove(p.config.Command) - p.ansibleMajVersion = 1 - - var l provisionLogicTracker - l.setupAdapterCalled = false - p.setupAdapterFunc = l.setupAdapter - p.executeAnsibleFunc = l.executeAnsible - ctx := context.TODO() - comm := new(packersdk.MockCommunicator) - ui := &packersdk.BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - } - p.Provision(ctx, ui, comm, tc.generatedData) - - if l.setupAdapterCalled != tc.expectedSetupAdapterCalled { - t.Fatalf("%s", tc.explanation) - } - os.Remove(p.config.Command) - } -} diff --git a/provisioner/ansible/test-fixtures/exit1 b/provisioner/ansible/test-fixtures/exit1 deleted file mode 100755 index 2bb8d868b..000000000 --- a/provisioner/ansible/test-fixtures/exit1 +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exit 1 diff --git a/provisioner/ansible/test-fixtures/long-debug-message.yml b/provisioner/ansible/test-fixtures/long-debug-message.yml deleted file mode 100644 index e633061bd..000000000 --- a/provisioner/ansible/test-fixtures/long-debug-message.yml +++ /dev/null @@ -1,8 +0,0 @@ -- name: Stub for Packer testing long Ansible messages - hosts: localhost - connection: local - - tasks: - - name: Very long Ansible output (>65535 chars) (Issue https://github.com/hashicorp/packer/issues/3268) - debug: - msg: "{{ lipsum(n=300, html=false) }}" diff --git a/provisioner/ansible/version/version.go b/provisioner/ansible/version/version.go deleted file mode 100644 index 09e4c48ee..000000000 --- a/provisioner/ansible/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var AnsiblePluginVersion *version.PluginVersion - -func init() { - AnsiblePluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/test/fixtures/provisioner-ansible/all_options.json b/test/fixtures/provisioner-ansible/all_options.json deleted file mode 100644 index 561d8d275..000000000 --- a/test/fixtures/provisioner-ansible/all_options.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "shell-local", - "command": "echo 'TODO(bhcleek): write the public key to $HOME/.ssh/known_hosts and stop using ANSIBLE_HOST_KEY_CHECKING=False'" - }, { - "type": "ansible", - "playbook_file": "./playbook.yml", - "extra_arguments": [ - "--private-key", "ansible-test-id" - ], - "sftp_command": "/usr/lib/sftp-server -e -l INFO", - "use_sftp": true, - "ansible_env_vars": ["PACKER_ANSIBLE_TEST=1", "ANSIBLE_HOST_KEY_CHECKING=False"], - "groups": ["PACKER_TEST"], - "empty_groups": ["PACKER_EMPTY_GROUP"], - "host_alias": "packer-test", - "user": "packer", - "local_port": 2222, - "ssh_host_key_file": "ansible-server.key", - "ssh_authorized_key_file": "ansible-test-id.pub" - } - ], - "builders": [{ - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-alloptions-{{timestamp}}", - "source_image": "debian-8-jessie-v20161027", - "zone": "us-central1-a", - "ssh_username": "debian" - }] -} diff --git a/test/fixtures/provisioner-ansible/connection_plugins/packer.py b/test/fixtures/provisioner-ansible/connection_plugins/packer.py deleted file mode 100644 index f0bb10da8..000000000 --- a/test/fixtures/provisioner-ansible/connection_plugins/packer.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.connection.ssh import Connection as SSHConnection - -class Connection(SSHConnection): - ''' ssh based connections for powershell via packer''' - - transport = 'packer' - has_pipelining = True - become_methods = [] - allow_executable = False - module_implementation_preferences = ('.ps1', '') - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) diff --git a/test/fixtures/provisioner-ansible/dir/contents-only/file.txt b/test/fixtures/provisioner-ansible/dir/contents-only/file.txt deleted file mode 100644 index 426dfd53e..000000000 --- a/test/fixtures/provisioner-ansible/dir/contents-only/file.txt +++ /dev/null @@ -1 +0,0 @@ -this file's parent directory should not be transferred to the node. diff --git a/test/fixtures/provisioner-ansible/dir/file.txt b/test/fixtures/provisioner-ansible/dir/file.txt deleted file mode 100644 index 0637880d7..000000000 --- a/test/fixtures/provisioner-ansible/dir/file.txt +++ /dev/null @@ -1 +0,0 @@ -This is a file diff --git a/test/fixtures/provisioner-ansible/dir/subdir/file.txt b/test/fixtures/provisioner-ansible/dir/subdir/file.txt deleted file mode 100644 index faba4c25d..000000000 --- a/test/fixtures/provisioner-ansible/dir/subdir/file.txt +++ /dev/null @@ -1 +0,0 @@ -This file and its parent directory should be transferred to the node. diff --git a/test/fixtures/provisioner-ansible/docker.json b/test/fixtures/provisioner-ansible/docker.json deleted file mode 100644 index 9cc788b51..000000000 --- a/test/fixtures/provisioner-ansible/docker.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "shell", - "inline": [ - "apt-get update", - "apt-get -y install python" - ] - }, { - "type": "ansible", - "playbook_file": "./playbook.yml", - "extra_arguments": [ - ], - "sftp_command": "/usr/bin/false", - "use_sftp": false - } - ], - "builders": [ - { - "type": "docker", - "image": "debian:jessie", - "discard": true - } - ] -} diff --git a/test/fixtures/provisioner-ansible/galaxy-playbook.yml b/test/fixtures/provisioner-ansible/galaxy-playbook.yml deleted file mode 100644 index b91a3dab4..000000000 --- a/test/fixtures/provisioner-ansible/galaxy-playbook.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -- hosts: default:packer-test - gather_facts: no - collections: - - artis3n.github - tasks: - - name: touch - raw: touch /tmp/ansible-raw-test - - name: raw test - raw: date - - name: command test - command: echo "the command module" - - name: prepare remote directory - command: mkdir /tmp/remote-dir - args: - creates: /tmp/remote-dir - - name: transfer file.txt - copy: src=dir/file.txt dest=/tmp/remote-dir/file.txt - - name: fetch file.text - fetch: src=/tmp/remote-dir/file.txt dest=fetched-dir validate=yes fail_on_missing=yes - - name: copy contents of directory - copy: src=dir/contents-only/ dest=/tmp/remote-dir - - name: fetch contents of directory - fetch: src=/tmp/remote-dir/file.txt dest="fetched-dir/{{ inventory_hostname }}/tmp/remote-dir/contents-only/" flat=yes validate=yes fail_on_missing=yes - - name: copy directory recursively - copy: src=dir/subdir dest=/tmp/remote-dir - - name: fetch recursively copied directory - fetch: src=/tmp/remote-dir/subdir/file.txt dest=fetched-dir validate=yes fail_on_missing=yes - - copy: src=largish-file.txt dest=/tmp/largish-file.txt - - name: test collection - fetch latest repo version - set_fact: - # Ansible will fail if collection is not installed - packer_version: "{{ lookup('artis3n.github.latest_release', 'hashicorp/packer' }}" diff --git a/test/fixtures/provisioner-ansible/galaxy.json b/test/fixtures/provisioner-ansible/galaxy.json deleted file mode 100644 index 879c925f6..000000000 --- a/test/fixtures/provisioner-ansible/galaxy.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./galaxy-playbook.yml", - "galaxy_file": "./requirements.yml" - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-galaxy-{{timestamp}}", - "source_image": "debian-8-jessie-v20161027", - "zone": "us-central1-a", - "ssh_username": "debian" - } - ] -} diff --git a/test/fixtures/provisioner-ansible/largish-file.txt b/test/fixtures/provisioner-ansible/largish-file.txt deleted file mode 100644 index 56036f750..000000000 Binary files a/test/fixtures/provisioner-ansible/largish-file.txt and /dev/null differ diff --git a/test/fixtures/provisioner-ansible/minimal.json b/test/fixtures/provisioner-ansible/minimal.json deleted file mode 100644 index b2bec543b..000000000 --- a/test/fixtures/provisioner-ansible/minimal.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./playbook.yml" - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-minimal-{{timestamp}}", - "source_image": "debian-8-jessie-v20161027", - "zone": "us-central1-a", - "ssh_username": "debian" - } - ] -} diff --git a/test/fixtures/provisioner-ansible/playbook.yml b/test/fixtures/provisioner-ansible/playbook.yml deleted file mode 100644 index 484841a77..000000000 --- a/test/fixtures/provisioner-ansible/playbook.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- hosts: default:packer-test - gather_facts: no - tasks: - - name: touch - raw: touch /tmp/ansible-raw-test - - name: raw test - raw: date - - name: command test - command: echo "the command module" - - name: prepare remote directory - command: mkdir /tmp/remote-dir - args: - creates: /tmp/remote-dir - - name: transfer file.txt - copy: src=dir/file.txt dest=/tmp/remote-dir/file.txt - - name: fetch file.text - fetch: src=/tmp/remote-dir/file.txt dest=fetched-dir validate=yes fail_on_missing=yes - - name: copy contents of directory - copy: src=dir/contents-only/ dest=/tmp/remote-dir - - name: fetch contents of directory - fetch: src=/tmp/remote-dir/file.txt dest="fetched-dir/{{ inventory_hostname }}/tmp/remote-dir/contents-only/" flat=yes validate=yes fail_on_missing=yes - - name: copy directory recursively - copy: src=dir/subdir dest=/tmp/remote-dir - - name: fetch recursively copied directory - fetch: src=/tmp/remote-dir/subdir/file.txt dest=fetched-dir validate=yes fail_on_missing=yes - - copy: src=largish-file.txt dest=/tmp/largish-file.txt diff --git a/test/fixtures/provisioner-ansible/requirements.yml b/test/fixtures/provisioner-ansible/requirements.yml deleted file mode 100644 index 4658d9204..000000000 --- a/test/fixtures/provisioner-ansible/requirements.yml +++ /dev/null @@ -1,2 +0,0 @@ -collections: - - name: artis3n.github diff --git a/test/fixtures/provisioner-ansible/scp-to-sftp.json b/test/fixtures/provisioner-ansible/scp-to-sftp.json deleted file mode 100644 index 4d608ffc2..000000000 --- a/test/fixtures/provisioner-ansible/scp-to-sftp.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./playbook.yml", - "extra_arguments": [ - ], - "sftp_command": "/usr/bin/false", - "use_sftp": false - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-scp-to-sftp-{{timestamp}}", - "source_image": "debian-8-jessie-v20161027", - "zone": "us-central1-a", - "ssh_username": "debian", - "ssh_file_transfer_method": "sftp" - } - ] -} diff --git a/test/fixtures/provisioner-ansible/scp.json b/test/fixtures/provisioner-ansible/scp.json deleted file mode 100644 index b745d7370..000000000 --- a/test/fixtures/provisioner-ansible/scp.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./playbook.yml", - "extra_arguments": [ - ], - "sftp_command": "/usr/bin/false", - "use_sftp": false - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-scp-{{timestamp}}", - "source_image": "debian-8-jessie-v20161027", - "zone": "us-central1-a", - "ssh_username": "debian" - } - ] -} diff --git a/test/fixtures/provisioner-ansible/sftp.json b/test/fixtures/provisioner-ansible/sftp.json deleted file mode 100644 index 8c0f7034d..000000000 --- a/test/fixtures/provisioner-ansible/sftp.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./playbook.yml", - "sftp_command": "/usr/lib/sftp-server -e -l INFO", - "use_sftp": true - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-sftp-{{timestamp}}", - "source_image": "debian-8-jessie-v20161027", - "zone": "us-central1-a", - "ssh_username": "debian" - } - ] -} diff --git a/test/fixtures/provisioner-ansible/win-playbook.yml b/test/fixtures/provisioner-ansible/win-playbook.yml deleted file mode 100644 index 45b39b432..000000000 --- a/test/fixtures/provisioner-ansible/win-playbook.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- hosts: default:packer-test - gather_facts: no - tasks: - #- debug: msg="testing regular modules that function with Windows: raw, fetch, slurp, setup" - - name: raw test - raw: date /t - - debug: msg="testing windows modules" - #- win_file: path=tmp/remote-dir state=directory - #- name: win_shell test - #win_shell: date /t - - name: win_copy test - win_copy: src=dir/file.txt dest=file.txt - #- win_copy: src=dir/file.txt dest=/tmp/remote-dir/file.txt - #- fetch: src=/tmp/remote-dir/file.txt dest=fetched-dir validate=yes fail_on_missing=yes - #- win_copy: src=largish-file.txt dest=/tmp/largish-file.txt - - debug: msg="packer does not support downloading from windows" diff --git a/test/fixtures/provisioner-ansible/winrm.json b/test/fixtures/provisioner-ansible/winrm.json deleted file mode 100644 index 979b8b60e..000000000 --- a/test/fixtures/provisioner-ansible/winrm.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./win-playbook.yml", - "extra_arguments": [ - "--connection", "packer", - "--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None" - ] - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{user `account_file`}}", - "project_id": "{{user `project_id`}}", - "image_name": "packerbats-winrm-{{timestamp}}", - "source_image": "windows-server-2012-r2-dc-v20160916", - "communicator": "winrm", - "zone": "us-central1-a", - "disk_size": 50, - "winrm_username": "packer", - "winrm_use_ssl": true, - "winrm_insecure": true, - "metadata": { - "sysprep-specialize-script-cmd": "winrm set winrm/config/service/auth @{Basic=\"true\"}" - } - } - ] -} diff --git a/test/provisioner_ansible.bats b/test/provisioner_ansible.bats deleted file mode 100755 index 2cc45b522..000000000 --- a/test/provisioner_ansible.bats +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bats -# -# This tests the ansible provisioner on Google Cloud Provider (i.e. -# googlecompute). The teardown function will delete any images with the text -# "packerbats" within the name. - -load test_helper -fixtures provisioner-ansible - -# Required parameters -: ${GC_ACCOUNT_FILE:?} -: ${GC_PROJECT_ID:?} -command -v gcloud >/dev/null 2>&1 || { - echo "'gcloud' must be installed" >&2 - exit 1 -} - -USER_VARS="${USER_VARS} -var account_file=${GC_ACCOUNT_FILE}" -USER_VARS="${USER_VARS} -var project_id=${GC_PROJECT_ID}" - -# This tests if GCE has an image that contains the given parameter. -gc_has_image() { - gcloud compute --format='table[no-heading](name)' --project=${GC_PROJECT_ID} images list \ - | grep $1 | wc -l -} - -setup(){ - rm -f $FIXTURE_ROOT/ansible-test-id - rm -f $FIXTURE_ROOT/ansible-server.key - ssh-keygen -N "" -f $FIXTURE_ROOT/ansible-test-id - ssh-keygen -N "" -f $FIXTURE_ROOT/ansible-server.key -} - -teardown() { - gcloud compute --format='table[no-heading](name)' --project=${GC_PROJECT_ID} images list \ - | grep packerbats \ - | xargs -n1 gcloud compute --project=${GC_PROJECT_ID} images delete - - rm -f $FIXTURE_ROOT/ansible-test-id - rm -f $FIXTURE_ROOT/ansible-test-id.pub - rm -f $FIXTURE_ROOT/ansible-server.key - rm -f $FIXTURE_ROOT/ansible-server.key.pub - rm -rf $FIXTURE_ROOT/fetched-dir -} - -@test "ansible provisioner: build docker.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/docker.json - [ "$status" -eq 0 ] - diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} -@test "ansible provisioner: build minimal.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/minimal.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-minimal")" -eq 1 ] - diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} - -@test "ansible provisioner: build all_options.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/all_options.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-alloptions")" -eq 1 ] - diff -r dir fetched-dir/packer-test/tmp/remote-dir > /dev/null -} - -@test "ansible provisioner: build galaxy.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/galaxy.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-galaxy")" -eq 1 ] - diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} - -@test "ansible provisioner: build scp.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/scp.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-scp")" -eq 1 ] - diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} - -@test "ansible provisioner: build scp-to-sftp.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/scp-to-sftp.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-scp-to-sftp")" -eq 1 ] - diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} - -@test "ansible provisioner: build sftp.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/sftp.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-sftp")" -eq 1 ] - diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} - -@test "ansible provisioner: build winrm.json" { - cd $FIXTURE_ROOT - run packer build ${USER_VARS} $FIXTURE_ROOT/winrm.json - [ "$status" -eq 0 ] - [ "$(gc_has_image "packerbats-winrm")" -eq 1 ] - echo "packer does not support downloading files from download, skipping verification" - #diff -r dir fetched-dir/default/tmp/remote-dir > /dev/null -} diff --git a/vendor/github.com/hashicorp/packer-plugin-ansible/LICENSE b/vendor/github.com/hashicorp/packer-plugin-ansible/LICENSE new file mode 100644 index 000000000..a612ad981 --- /dev/null +++ b/vendor/github.com/hashicorp/packer-plugin-ansible/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/provisioner/ansible-local/communicator_mock.go b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/communicator_mock.go similarity index 98% rename from provisioner/ansible-local/communicator_mock.go rename to vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/communicator_mock.go index 4cec79020..d13625b2b 100644 --- a/provisioner/ansible-local/communicator_mock.go +++ b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/communicator_mock.go @@ -36,5 +36,6 @@ func (c *communicatorMock) DownloadDir(src, dst string, exclude []string) error return nil } +//nolint:unused func (c *communicatorMock) verify() { } diff --git a/provisioner/ansible-local/provisioner.go b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/provisioner.go similarity index 100% rename from provisioner/ansible-local/provisioner.go rename to vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/provisioner.go diff --git a/provisioner/ansible-local/provisioner.hcl2spec.go b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/provisioner.hcl2spec.go similarity index 100% rename from provisioner/ansible-local/provisioner.hcl2spec.go rename to vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/provisioner.hcl2spec.go diff --git a/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/test-fixtures/docker_playbookdir_template.pkr.hcl b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/test-fixtures/docker_playbookdir_template.pkr.hcl new file mode 100644 index 000000000..c8aa349b1 --- /dev/null +++ b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/test-fixtures/docker_playbookdir_template.pkr.hcl @@ -0,0 +1,31 @@ +packer { + required_version = ">1.7.0" + + required_plugins { + docker = { + source = "github.com/hashicorp/docker" + version = ">=0.0.7" + } + } +} + +source "docker" "autogenerated_1" { + discard = true + image = "williamyeh/ansible:centos7" +} + +build { + sources = ["source.docker.autogenerated_1"] + + provisioner "ansible-local" { + playbook_dir = "test-fixtures" + playbook_files = ["test-fixtures/hello.yml", "test-fixtures/world.yml"] + } + + provisioner "file" { + destination = "hello_world" + direction = "download" + source = "/tmp/hello_world" + } + +} diff --git a/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/test-fixtures/docker_playbookfiles_template.pkr.hcl b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/test-fixtures/docker_playbookfiles_template.pkr.hcl new file mode 100644 index 000000000..7e7f51a42 --- /dev/null +++ b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local/test-fixtures/docker_playbookfiles_template.pkr.hcl @@ -0,0 +1,30 @@ +packer { + required_version = ">1.7.0" + + required_plugins { + docker = { + source = "github.com/hashicorp/docker" + version = ">=0.0.7" + } + } +} + +source "docker" "autogenerated_1" { + discard = true + image = "williamyeh/ansible:centos7" +} + +build { + sources = ["source.docker.autogenerated_1"] + + provisioner "ansible-local" { + playbook_files = ["test-fixtures/hello.yml", "test-fixtures/world.yml"] + } + + provisioner "file" { + destination = "hello_world" + direction = "download" + source = "/tmp/hello_world" + } + +} diff --git a/provisioner/ansible/mock_ansible.go b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/mock_ansible.go similarity index 100% rename from provisioner/ansible/mock_ansible.go rename to vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/mock_ansible.go diff --git a/provisioner/ansible/provisioner.go b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/provisioner.go similarity index 99% rename from provisioner/ansible/provisioner.go rename to vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/provisioner.go index e6a67071c..79b82a0a2 100644 --- a/provisioner/ansible/provisioner.go +++ b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/provisioner.go @@ -485,7 +485,9 @@ func (p *Provisioner) createInventoryFile() error { } w := bufio.NewWriter(tf) - w.WriteString(host) + if _, err := w.WriteString(host); err != nil { + log.Printf("[TRACE] error writing the generated inventory file: %s", err) + } for _, group := range p.config.Groups { fmt.Fprintf(w, "[%s]\n%s", group, host) @@ -681,7 +683,7 @@ func (p *Provisioner) executeGalaxy(ui packersdk.Ui, comm packersdk.Communicator // Intended to be invoked from p.executeGalaxy depending on the Ansible Galaxy parameters passed to Packer func (p *Provisioner) invokeGalaxyCommand(args []string, ui packersdk.Ui, comm packersdk.Communicator) error { - ui.Message(fmt.Sprintf("Executing Ansible Galaxy")) + ui.Message("Executing Ansible Galaxy") cmd := exec.Command(p.config.GalaxyCommand, args...) stdout, err := cmd.StdoutPipe() diff --git a/provisioner/ansible/provisioner.hcl2spec.go b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/provisioner.hcl2spec.go similarity index 100% rename from provisioner/ansible/provisioner.hcl2spec.go rename to vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/provisioner.hcl2spec.go diff --git a/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/test-fixtures/docker_playbookfile_template.pkr.hcl b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/test-fixtures/docker_playbookfile_template.pkr.hcl new file mode 100644 index 000000000..a07d0f1e8 --- /dev/null +++ b/vendor/github.com/hashicorp/packer-plugin-ansible/provisioner/ansible/test-fixtures/docker_playbookfile_template.pkr.hcl @@ -0,0 +1,23 @@ +packer { + required_version = ">1.7.0" + + required_plugins { + docker = { + source = "github.com/hashicorp/docker" + version = ">=0.0.7" + } + } +} + +source "docker" "autogenerated_1" { + discard = true + image = "williamyeh/ansible:centos7" +} + +build { + sources = ["source.docker.autogenerated_1"] + + provisioner "ansible" { + playbook_file = "test-fixtures/long-debug-message.yml" + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 89835e8a3..1002ef874 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -509,6 +509,10 @@ github.com/hashicorp/packer-plugin-amazon/builder/instance github.com/hashicorp/packer-plugin-amazon/datasource/ami github.com/hashicorp/packer-plugin-amazon/datasource/secretsmanager github.com/hashicorp/packer-plugin-amazon/post-processor/import +# github.com/hashicorp/packer-plugin-ansible v0.0.2 +## explicit +github.com/hashicorp/packer-plugin-ansible/provisioner/ansible +github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local # github.com/hashicorp/packer-plugin-docker v0.0.7 ## explicit github.com/hashicorp/packer-plugin-docker/builder/docker diff --git a/website/content/docs/provisioners/ansible-local.mdx b/website/content/docs/provisioners/ansible-local.mdx deleted file mode 100644 index bfeeb1bee..000000000 --- a/website/content/docs/provisioners/ansible-local.mdx +++ /dev/null @@ -1,136 +0,0 @@ ---- -description: > - The ansible-local Packer provisioner will run ansible in ansible's "local" - mode on the remote/guest VM using Playbook and Role files that exist on the - guest VM. This means Ansible must be installed on the remote/guest VM. - Playbooks and Roles can be uploaded from your build machine (the one running - Packer) to the vm. -page_title: Ansible Local - Provisioners ---- - -# Ansible Local Provisioner - -Type: `ansible-local` - -The `ansible-local` Packer provisioner will execute `ansible` in Ansible's "local" -mode on the remote/guest VM using Playbook and Role files that exist on the -guest VM. This means Ansible must be installed on the remote/guest VM. -Playbooks and Roles can be uploaded from your build machine (the one running -Packer) to the vm. Ansible is then run on the guest machine in [local -mode](https://docs.ansible.com/ansible/latest/playbooks_delegation.html#local-playbooks) -via the `ansible-playbook` command. - --> **Note:** Ansible will _not_ be installed automatically by this -provisioner. This provisioner expects that Ansible is already installed on the -guest/remote machine. It is common practice to use the [shell -provisioner](/docs/provisioners/shell) before the Ansible provisioner to -do this. - -## Basic Example - -The example below is fully functional. - - - - -```json -{ - "builders": [ - { - "type": "docker", - "image": "williamyeh/ansible:ubuntu14.04", - "export_path": "packer_example", - "run_command": ["-d", "-i", "-t", "--entrypoint=/bin/bash", "{{.Image}}"] - } - ], - "variables": { - "topping": "mushroom" - }, - "provisioners": [ - { - "type": "ansible-local", - "playbook_file": "./playbook.yml", - "extra_arguments": [ - "--extra-vars", - "\"pizza_toppings={{ user `topping`}}\"" - ] - } - ] -} -``` - - - - -```hcl -variable "topping" { - type = string - default = "mushroom" -} - -source "docker" "example" { - image = "williamyeh/ansible:ubuntu14.04" - export_path = "packer_example" - run_command = ["-d", "-i", "-t", "--entrypoint=/bin/bash", "{{.Image}}"] -} - -build { - sources = [ - "source.docker.example" - ] - - provisioner "ansible-local" { - playbook_file = "./playbook.yml" - extra_arguments = ["--extra-vars", "\"pizza_toppings=${var.topping}\""] - } -} -``` - - - - -where ./playbook.yml contains - -``` ---- -- name: hello world - hosts: 127.0.0.1 - connection: local - - tasks: - - command: echo {{ pizza_toppings }} - - debug: msg="{{ pizza_toppings }}" - -``` - -## Configuration Reference - -The reference of available configuration options is listed below. - -Note that one of `playbook_file` or `playbook_files` is required. - -@include '/provisioner/ansible/Config-not-required.mdx' - -@include 'provisioners/common-config.mdx' - -## Default Extra Variables - -In addition to being able to specify extra arguments using the -`extra_arguments` configuration, the provisioner automatically defines certain -commonly useful Ansible variables: - -- `packer_build_name` is set to the name of the build that Packer is running. - This is most useful when Packer is making multiple builds and you want to - distinguish them slightly when using a common playbook. - -- `packer_builder_type` is the type of the builder that was used to create - the machine that the script is running on. This is useful if you want to - run only certain parts of the playbook on systems built with certain - builders. - -- `packer_http_addr` If using a builder that provides an HTTP server for file - transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this - will be set to the address. You can use this address in your provisioner to - download large files over HTTP. This may be useful if you're experiencing - slower speeds using the default file provisioner. A file provisioner using - the `winrm` communicator may experience these types of difficulties. diff --git a/website/content/docs/provisioners/ansible.mdx b/website/content/docs/provisioners/ansible.mdx deleted file mode 100644 index 86228cd32..000000000 --- a/website/content/docs/provisioners/ansible.mdx +++ /dev/null @@ -1,805 +0,0 @@ ---- -description: | - The ansible Packer provisioner allows Ansible playbooks to be run to provision - the machine. -page_title: Ansible - Provisioners ---- - -# Ansible Provisioner - -Type: `ansible` - -The `ansible` Packer provisioner runs Ansible playbooks. It dynamically creates -an Ansible inventory file configured to use SSH, runs an SSH server, executes -`ansible-playbook`, and marshals Ansible plays through the SSH server to the -machine being provisioned by Packer. - --> **Note:** Any `remote_user` defined in tasks will be ignored. Packer -will always connect with the user given in the json config for this -provisioner. - --> **Note:** Options below that use the Packer template engine won't be able to -accept jinja2 `{{ function }}` macro syntax in a way that can be preserved to -the Ansible run. If you need to set variables using Ansible macros, you need to -do so inside your playbooks or inventory files. - -Please see the [Debugging](#debugging), [Limitations](#limitations), or [Troubleshooting](#troubleshooting) if you are having trouble -getting started. - -## Basic Example - -This is a fully functional template that will provision an image on -DigitalOcean. Replace the mock `api_token` value with your own. - -Example Packer template: - - - - -```hcl -source "digitalocean" "example"{ - api_token = "6a561151587389c7cf8faa2d83e94150a4202da0e2bad34dd2bf236018ffaeeb" - image = "ubuntu-20-04-x64" - region = "sfo1" -} - -build { - sources = [ - "source.digitalocean.example" - ] - - provisioner "ansible" { - playbook_file = "./playbook.yml" - } -} -``` - - - - -```json -{ - "builders": [ - { - "type": "digitalocean", - "api_token": "6a561151587389c7cf8faa2d83e94150a4202da0e2bad34dd2bf236018ffaeeb", - "image": "ubuntu-20-04-x64", - "region": "sfo1" - } - ], - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./playbook.yml" - } - ] -} -``` - - - - -Example playbook: - -```yaml ---- -# playbook.yml -- name: 'Provision Image' - hosts: default - become: true - - tasks: - - name: install Apache - package: - name: 'httpd' - state: present -``` - -## Configuration Reference - -Required Parameters: - -@include 'provisioner/ansible/Config-required.mdx' - -Optional Parameters: - -@include '/provisioner/ansible/Config-not-required.mdx' - -@include 'provisioners/common-config.mdx' - -## Default Extra Variables - -In addition to being able to specify extra arguments using the -`extra_arguments` configuration, the provisioner automatically defines certain -commonly useful Ansible variables: - -- `packer_build_name` is set to the name of the build that Packer is running. - This is most useful when Packer is making multiple builds and you want to - distinguish them slightly when using a common playbook. - -- `packer_builder_type` is the type of the builder that was used to create - the machine that the script is running on. This is useful if you want to - run only certain parts of the playbook on systems built with certain - builders. - -- `packer_http_addr` If using a builder that provides an HTTP server for file - transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this - will be set to the address. You can use this address in your provisioner to - download large files over HTTP. This may be useful if you're experiencing - slower speeds using the default file provisioner. A file provisioner using - the `winrm` communicator may experience these types of difficulties. - -## Debugging - -To debug underlying issues with Ansible, add `"-vvvv"` to `"extra_arguments"` -to enable verbose logging. - - - - -```hcl - extra_arguments = [ "-vvvv" ] -``` - - - - -```json - "extra_arguments": [ "-vvvv" ] -``` - - - - -## Limitations - -### Redhat / CentOS - -Redhat / CentOS builds have been known to fail with the following error due to -`sftp_command`, which should be set to `/usr/libexec/openssh/sftp-server -e`: - -```text -==> virtualbox-ovf: starting sftp subsystem - virtualbox-ovf: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh", "unreachable": true} -``` - -### chroot communicator - -Building within a chroot (e.g. `amazon-chroot`) requires changing the Ansible -connection to chroot and running Ansible as root/sudo. - - - - -```hcl -source "amazon-chroot" "example" { - mount_path = "/mnt/packer-amazon-chroot" - region = "us-east-1" - source_ami = "ami-123456" -} - -build { - sources = [ - "source.amazon-chroot.example" - ] - - provisioner "ansible" { - extra_arguments = [ - "--connection=chroot", - "--inventory-file=/mnt/packer-amazon-chroot" - ] - - playbook_file = "main.yml" - } -} -``` - - - - -```json -{ - "builders": [ - { - "type": "amazon-chroot", - "mount_path": "/mnt/packer-amazon-chroot", - "region": "us-east-1", - "source_ami": "ami-123456" - } - ], - "provisioners": [ - { - "type": "ansible", - "extra_arguments": [ - "--connection=chroot", - "--inventory-file=/mnt/packer-amazon-chroot" - ], - "playbook_file": "main.yml" - } - ] -} -``` - - - - -### WinRM Communicator - -There are two possible methods for using Ansible with the WinRM communicator. - -Please note that if you're having trouble getting Ansible to connect, you may -want to take a look at the script that the Ansible project provides to help -configure remoting for Ansible: -https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 - -#### Method 1 (recommended) - -The recommended way to use the WinRM communicator is to set `"use_proxy": false` -and let the Ansible provisioner handle the rest for you. If you -are using WinRM with HTTPS, and you are using a self-signed certificate you -will also have to set `ansible_winrm_server_cert_validation=ignore` in your -extra_arguments. - -Below is a fully functioning Ansible example using WinRM: - - - - -```hcl -data "amazon-ami" "ubuntu" { - access_key = var.aws_access_key - - filters = { - name = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*" - root-device-type = "ebs" - virtualization-type = "hvm" - } - - most_recent = true - owners = ["099720109477"] - region = var.aws_region - secret_key = var.aws_secret_key -} - -source "amazon-ebs" "example" { - region = "us-east-1" - instance_type = "t2.micro" - - source_ami = data.amazon-ami.ubuntu.id - - ami_name = "test-ansible-packer" - user_data_file = "windows_bootstrap.txt" - communicator = "winrm" - force_deregister = true - winrm_username = "Administrator" - winrm_insecure = true - winrm_use_ssl = true -} - -build { - sources = [ - "source.amazon-ebs.example", - ] - - provisioner "ansible" { - playbook_file = "./playbooks/playbook-windows.yml" - user = "Administrator" - use_proxy = false - extra_arguments = [ - "-e", - "ansible_winrm_server_cert_validation=ignore" - ] - } -} -``` - - - - -```json -{ - "builders": [ - { - "type": "amazon-ebs", - "region": "us-east-1", - "instance_type": "t2.micro", - "source_ami_filter": { - "filters": { - "virtualization-type": "hvm", - "name": "*Windows_Server-2012*English-64Bit-Base*", - "root-device-type": "ebs" - }, - "most_recent": true, - "owners": "amazon" - }, - "ami_name": "test-ansible-packer", - "user_data_file": "windows_bootstrap.txt", - "communicator": "winrm", - "force_deregister": true, - "winrm_insecure": true, - "winrm_username": "Administrator", - "winrm_use_ssl": true - } - ], - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./playbook.yml", - "user": "Administrator", - "use_proxy": false, - "extra_arguments": ["-e", "ansible_winrm_server_cert_validation=ignore"] - } - ] -} -``` - - - - -Note that you do have to set the "Administrator" user, because otherwise Ansible -will default to using the user that is calling Packer, rather than the user -configured inside of the Packer communicator. For the contents of -windows_bootstrap.txt, see the WinRM docs for the amazon-ebs communicator. - -When running from OSX, you may see an error like: - -```text - amazon-ebs: objc[9752]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. - amazon-ebs: objc[9752]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug. - amazon-ebs: ERROR! A worker was found in a dead state -``` - -If you see this, you may be able to work around the issue by telling Ansible to -explicitly not use any proxying; you can do this by setting the template option - - - - -```hcl -ansible_env_vars = ["no_proxy=\"*\""] -``` - - - - -```json -"ansible_env_vars": ["no_proxy=\"*\""], -``` - - - - -in the above Ansible template. - -#### Method 2 (Not recommended) - -If you want to use the Packer SSH proxy, then you need a custom Ansible -connection plugin and a particular configuration. You need a directory named -`connection_plugins` next to the playbook which contains a file named -packer.py` which implements the connection plugin. On versions of Ansible -before 2.4.x, the following works as the connection plugin: - -```python -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.connection.ssh import Connection as SSHConnection - -class Connection(SSHConnection): - ''' ssh based connections for powershell via packer''' - - transport = 'packer' - has_pipelining = True - become_methods = [] - allow_executable = False - module_implementation_preferences = ('.ps1', '') - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) -``` - -Newer versions of Ansible require all plugins to have a documentation string. -You can see if there is a plugin available for the version of Ansible you are -using -[here](https://github.com/hashicorp/packer/tree/master/provisioner/ansible/examples/connection-plugin). - -To create the plugin yourself, you will need to copy all of the `options` from -the `DOCUMENTATION` string from the [ssh.py Ansible connection -plugin](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py) -of the Ansible version you are using and add it to a packer.py file similar to -as follows - -```python -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.plugins.connection.ssh import Connection as SSHConnection - -DOCUMENTATION = ''' - connection: packer - short_description: ssh based connections for powershell via packer - description: - - This connection plugin allows ansible to communicate to the target packer machines via ssh based connections for powershell. - author: Packer - version_added: na - options: - **** Copy ALL the options from - https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py - for the version of Ansible you are using **** -''' - -class Connection(SSHConnection): - ''' ssh based connections for powershell via packer''' - - transport = 'packer' - has_pipelining = True - become_methods = [] - allow_executable = False - module_implementation_preferences = ('.ps1', '') - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) -``` - -This template should build a Windows Server 2012 image on Google Cloud -Platform: - -```json -{ - "variables": {}, - "provisioners": [ - { - "type": "ansible", - "playbook_file": "./win-playbook.yml", - "extra_arguments": [ - "--connection", - "packer", - "--extra-vars", - "\"ansible_shell_type=powershell ansible_shell_executable=None\"" - ] - } - ], - "builders": [ - { - "type": "googlecompute", - "account_file": "{{ user `account_file`}}", - "project_id": "{{user `project_id`}}", - "source_image": "windows-server-2012-r2-dc-v20160916", - "communicator": "winrm", - "zone": "us-central1-a", - "disk_size": 50, - "winrm_username": "packer", - "winrm_use_ssl": true, - "winrm_insecure": true, - "metadata": { - "sysprep-specialize-script-cmd": "winrm set winrm/config/service/auth @{Basic=\"true\"}" - } - } - ] -} -``` - --> **Warning:** Please note that if you're setting up WinRM for provisioning, you'll probably want to turn it off or restrict its permissions as part of a shutdown script at the end of Packer's provisioning process. For more details on the why/how, check out this useful blog post and the associated code: -https://cloudywindows.io/post/winrm-for-provisioning-close-the-door-on-the-way-out-eh/ - -### Post i/o timeout errors - -If you see -`unknown error: Post http://:/wsman:dial tcp :: i/o timeout` -errors while provisioning a Windows machine, try setting Ansible to copy files -over [ssh instead of -sftp](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#envvar-ANSIBLE_SCP_IF_SSH). - -### Too many SSH keys - -SSH servers only allow you to attempt to authenticate a certain number of -times. All of your loaded keys will be tried before the dynamically generated -key. If you have too many SSH keys loaded in your `ssh-agent`, the Ansible -provisioner may fail authentication with a message similar to this: - -```text - googlecompute: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '[127.0.0.1]:62684' (RSA) to the list of known hosts.\r\nReceived disconnect from 127.0.0.1 port 62684:2: too many authentication failures\r\nAuthentication failed.\r\n", "unreachable": true} -``` - -To unload all keys from your `ssh-agent`, run: - -```shell-session -$ ssh-add -D -``` - -### Become: yes - -We recommend against running Packer as root; if you do then you won't be able -to successfully run your Ansible playbook as root; `become: yes` will fail. - -### Using a wrapping script for your Ansible call - -Sometimes, you may have extra setup that needs to be called as part of your -ansible run. The easiest way to do this is by writing a small bash script and -using that bash script in your "command" in place of the default -"ansible-playbook". For example, you may need to launch a Python virtualenv -before calling Ansible. To do this, you'd want to create a bash script like - -```shell -#!/bin/bash -source /tmp/venv/bin/activate && ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 /tmp/venv/bin/ansible-playbook "$@" -``` - -The Ansible provisioner template remains very simple. For example: - - - - -```hcl -provisioner "ansible" { - command = "/Path/To/call_ansible.sh" - playbook_file = "./playbook.yml" -} -``` - - - - -```json -{ - "type": "ansible", - "command": "/Path/To/call_ansible.sh", - "playbook_file": "./playbook.yml" -} -``` - - - - -Note that we're calling ansible-playbook at the end of this command and passing -all command line arguments through into this call; this is necessary for -making sure that --extra-vars and other important Ansible arguments get set. -Note the quoting around the bash array, too; if you don't use quotes, any -arguments with spaces will not be read properly. - -### Docker - -When trying to use Ansible with Docker, it should "just work" but if it doesn't -you may need to tweak a few options. - -- Change the ansible_connection from "ssh" to "docker" -- Set a Docker container name via the --name option. - -On a CI server you probably want to overwrite ansible_host with a random name. - -Example Packer template: - - - - -```hcl -variable "ansible_host" { - default = "default" -} - -variable "ansible_connection" { - default = "docker" -} - -source "docker" "example" { - image = "centos:7" - commit = true - run_command = [ "-d", "-i", "-t", "--name", var.ansible_host, "{{.Image}}", "/bin/bash" ] -} - -build { - sources = [ - "source.docker.example" - ] - - provisioner "ansible" { - groups = [ "webserver" ] - playbook_file = "./webserver.yml" - extra_arguments = [ - "--extra-vars", - "ansible_host=${var.ansible_host} ansible_connection=${var.ansible_connection}" - ] - } -} -``` - - - - -```json -{ - "variables": { - "ansible_host": "default", - "ansible_connection": "docker" - }, - "builders": [ - { - "type": "docker", - "image": "centos:7", - "commit": true, - "run_command": [ - "-d", - "-i", - "-t", - "--name", - "{{user `ansible_host`}}", - "{{.Image}}", - "/bin/bash" - ] - } - ], - "provisioners": [ - { - "type": "ansible", - "groups": ["webserver"], - "playbook_file": "./webserver.yml", - "extra_arguments": [ - "--extra-vars", - "ansible_host={{user `ansible_host`}} ansible_connection={{user `ansible_connection`}}" - ] - } - ] -} -``` - - - - -Example playbook: - -```yaml -- name: configure webserver - hosts: webserver - tasks: - - name: install Apache - yum: - name: httpd -``` - -### Amazon Session Manager - -When trying to use Ansible with Amazon's Session Manager, you may run into an error where Ansible -is unable to connect to the remote Amazon instance if the local proxy adapter for Ansible [use_proxy](#use_proxy) is false. - -The error may look something like the following: - -``` -amazon-ebs: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 127.0.0.1 port 8362: Connection timed out", "unreachable": true} -``` - -The error is caused by a limitation on using Amazon's SSM default Port Forwarding session which only allows for one -remote connection on the forwarded port. Since Ansible's SSH communication is not using the local proxy adapter -it will try to make a new SSH connection to the same forwarded localhost port and fail. - -In order to workaround this issue Ansible can be configured via a custom inventory file to use the AWS session-manager-plugin -directly to create a new session, separate from the one created by Packer, at runtime to connect and remotely provision the instance. - --> **Warning:** Please note that the default region configured for the `aws` cli must match the build region where the instance is being -provisioned otherwise you may run into a TargetNotConnected error. Users can use `AWS_DEFAULT_REGION` to temporarily override -their configured region. - - - - -```hcl - provisioner "ansible" { - use_proxy = false - playbook_file = "./playbooks/playbook_remote.yml" - ansible_env_vars = ["PACKER_BUILD_NAME={{ build_name }}"] - inventory_file_template = "{{ .HostAlias }} ansible_host={{ .ID }} ansible_user={{ .User }} ansible_ssh_common_args='-o StrictHostKeyChecking=no -o ProxyCommand=\"sh -c \\\"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p\\\"\"'\n" - } -``` - - - - -```json - "provisioners": [ - { - "type": "ansible", - "use_proxy": false, - "ansible_env_vars": ["PACKER_BUILD_NAME={{ build_name }}"], - "playbook_file": "./playbooks/playbook_remote.yml", - "inventory_file_template": "{{ .HostAlias }} ansible_host={{ .ID }} ansible_user={{ .User }} ansible_ssh_common_args='-o StrictHostKeyChecking=no -o ProxyCommand=\"sh -c \\\"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p\\\"\"'\n" - } - ] -``` - - - - -Full Packer template example: - - - - -```hcl - -variables { - instance_role = "SSMInstanceProfile" -} - -source "amazon-ebs" "ansible-example" { - region = "us-east-1" - ami_name = "packer-ami-ansible" - instance_type = "t2.micro" - - source_ami_filter { - filters = { - name = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*" - virtualization-type = "hvm" - root-device-type = "ebs" - } - owners = [ "099720109477" ] - most_recent = true - } - communicator = "ssh" - ssh_username = "ubuntu" - ssh_interface = "session_manager" - iam_instance_profile = var.instance_role -} - -build { - sources = ["source.amazon-ebs.ansible-example"] - - provisioner "ansible" { - use_proxy = false - playbook_file = "./playbooks/playbook_remote.yml" - ansible_env_vars = ["PACKER_BUILD_NAME={{ build_name }}"] - inventory_file_template = "{{ .HostAlias }} ansible_host={{ .ID }} ansible_user={{ .User }} ansible_ssh_common_args='-o StrictHostKeyChecking=no -o ProxyCommand=\"sh -c \\\"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p\\\"\"'\n" - } -} -``` - - - - -```json -{ - "variables": { - "instance_role": "SSMInstanceProfile" - }, - - "builders": [ - { - "type": "amazon-ebs", - "region": "us-east-1", - "ami_name": "packer-ami-ansible", - "instance_type": "t2.micro", - "source_ami_filter": { - "filters": { - "virtualization-type": "hvm", - "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*", - "root-device-type": "ebs" - }, - "owners": ["099720109477"], - "most_recent": true - }, - "communicator": "ssh", - "ssh_username": "ubuntu", - "ssh_interface": "session_manager", - "iam_instance_profile": "{{user `instance_role`}}" - } - ], - "provisioners": [ - { - "type": "ansible", - "use_proxy": false, - "ansible_env_vars": ["PACKER_BUILD_NAME={{ build_name }}"], - "playbook_file": "./playbooks/playbook_remote.yml", - "inventory_file_template": "{{ .HostAlias }} ansible_host={{ .ID }} ansible_user={{ .User }} ansible_ssh_common_args='-o StrictHostKeyChecking=no -o ProxyCommand=\"sh -c \\\"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p\\\"\"'\n" - } - ] -} -``` - - - - -### Troubleshooting - -If you are using an Ansible version >= 2.8 and Packer hangs in the -"Gathering Facts" stage, this could be the result of a pipelineing issue with -the proxy adapter that Packer uses. Setting `use_proxy: false,` in your -Packer config should resolve the issue. In the future we will default to setting -this, so you won't have to but for now it is a manual change you must make. diff --git a/website/content/partials/provisioner/ansible-local/Config-not-required.mdx b/website/content/partials/provisioner/ansible-local/Config-not-required.mdx deleted file mode 100644 index 379d30798..000000000 --- a/website/content/partials/provisioner/ansible-local/Config-not-required.mdx +++ /dev/null @@ -1,124 +0,0 @@ - - -- `command` (string) - The command to invoke ansible. Defaults to - `ansible-playbook`. If you would like to provide a more complex command, - for example, something that sets up a virtual environment before calling - ansible, take a look at the ansible wrapper guide below for inspiration. - Please note that Packer expects Command to be a path to an executable. - Arbitrary bash scripting will not work and needs to go inside an - executable script. - -- `extra_arguments` ([]string) - Extra arguments to pass to Ansible. - These arguments _will not_ be passed through a shell and arguments should - not be quoted. Usage example: - - ```json - "extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ] - ``` - In certain scenarios where you want to pass ansible command line arguments - that include parameter and value (for example `--vault-password-file pwfile`), - from ansible documentation this is correct format but that is NOT accepted here. - Instead you need to do it like `--vault-password-file=pwfile`. - - If you are running a Windows build on AWS, Azure, Google Compute, or OpenStack - and would like to access the auto-generated password that Packer uses to - connect to a Windows instance via WinRM, you can use the template variable - `{{.WinRMPassword}}` in this option. For example: - - ```json - "extra_arguments": [ - "--extra-vars", "winrm_password={{ .WinRMPassword }}" - ] - ``` - -- `group_vars` (string) - A path to the directory containing ansible group - variables on your local system to be copied to the remote machine. By - default, this is empty. - -- `host_vars` (string) - A path to the directory containing ansible host variables on your local - system to be copied to the remote machine. By default, this is empty. - -- `playbook_dir` (string) - A path to the complete ansible directory structure on your local system - to be copied to the remote machine as the `staging_directory` before all - other files and directories. - -- `playbook_file` (string) - The playbook file to be executed by ansible. This file must exist on your - local system and will be uploaded to the remote machine. This option is - exclusive with `playbook_files`. - -- `playbook_files` ([]string) - The playbook files to be executed by ansible. These files must exist on - your local system. If the files don't exist in the `playbook_dir` or you - don't set `playbook_dir` they will be uploaded to the remote machine. This - option is exclusive with `playbook_file`. - -- `playbook_paths` ([]string) - An array of directories of playbook files on your local system. These - will be uploaded to the remote machine under `staging_directory`/playbooks. - By default, this is empty. - -- `role_paths` ([]string) - An array of paths to role directories on your local system. These will be - uploaded to the remote machine under `staging_directory`/roles. By default, - this is empty. - -- `staging_directory` (string) - The directory where all the configuration of Ansible by Packer will be placed. - By default this is `/tmp/packer-provisioner-ansible-local/`, where - `` is replaced with a unique ID so that this provisioner can be run more - than once. If you'd like to know the location of the staging directory in - advance, you should set this to a known location. This directory doesn't need - to exist but must have proper permissions so that the SSH user that Packer uses - is able to create directories and write into this folder. If the permissions - are not correct, use a shell provisioner prior to this to configure it - properly. - -- `clean_staging_directory` (bool) - If set to `true`, the content of the `staging_directory` will be removed after - executing ansible. By default this is set to `false`. - -- `inventory_file` (string) - The inventory file to be used by ansible. This - file must exist on your local system and will be uploaded to the remote - machine. - - When using an inventory file, it's also required to `--limit` the hosts to the - specified host you're building. The `--limit` argument can be provided in the - `extra_arguments` option. - - An example inventory file may look like: - - ```text - [chi-dbservers] - db-01 ansible_connection=local - db-02 ansible_connection=local - - [chi-appservers] - app-01 ansible_connection=local - app-02 ansible_connection=local - - [chi:children] - chi-dbservers - chi-appservers - - [dbservers:children] - chi-dbservers - - [appservers:children] - chi-appservers - ``` - -- `inventory_groups` ([]string) - `inventory_groups` (string) - A comma-separated list of groups to which - packer will assign the host `127.0.0.1`. A value of `my_group_1,my_group_2` - will generate an Ansible inventory like: - - ```text - [my_group_1] - 127.0.0.1 - [my_group_2] - 127.0.0.1 - ``` - -- `galaxy_file` (string) - A requirements file which provides a way to - install roles or collections with the [ansible-galaxy - cli](https://docs.ansible.com/ansible/latest/galaxy/user_guide.html#the-ansible-galaxy-command-line-tool) - on the local machine before executing `ansible-playbook`. By default, this is empty. - -- `galaxy_command` (string) - The command to invoke ansible-galaxy. By default, this is - `ansible-galaxy`. - - diff --git a/website/content/partials/provisioner/ansible/Config-not-required.mdx b/website/content/partials/provisioner/ansible/Config-not-required.mdx deleted file mode 100644 index 76c7e2dad..000000000 --- a/website/content/partials/provisioner/ansible/Config-not-required.mdx +++ /dev/null @@ -1,167 +0,0 @@ - - -- `command` (string) - The command to invoke ansible. Defaults to - `ansible-playbook`. If you would like to provide a more complex command, - for example, something that sets up a virtual environment before calling - ansible, take a look at the ansible wrapper guide below for inspiration. - Please note that Packer expects Command to be a path to an executable. - Arbitrary bash scripting will not work and needs to go inside an - executable script. - -- `extra_arguments` ([]string) - Extra arguments to pass to Ansible. - These arguments _will not_ be passed through a shell and arguments should - not be quoted. Usage example: - - ```json - "extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ] - ``` - In certain scenarios where you want to pass ansible command line arguments - that include parameter and value (for example `--vault-password-file pwfile`), - from ansible documentation this is correct format but that is NOT accepted here. - Instead you need to do it like `--vault-password-file=pwfile`. - - If you are running a Windows build on AWS, Azure, Google Compute, or OpenStack - and would like to access the auto-generated password that Packer uses to - connect to a Windows instance via WinRM, you can use the template variable - `{{.WinRMPassword}}` in this option. For example: - - ```json - "extra_arguments": [ - "--extra-vars", "winrm_password={{ .WinRMPassword }}" - ] - ``` - -- `ansible_env_vars` ([]string) - Environment variables to set before - running Ansible. Usage example: - - ```json - "ansible_env_vars": [ "ANSIBLE_HOST_KEY_CHECKING=False", "ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s'", "ANSIBLE_NOCOLOR=True" ] - ``` - - This is a [template engine](/docs/templates/legacy_json_templates/engine). Therefore, you - may use user variables and template functions in this field. - - For example, if you are running a Windows build on AWS, Azure, - Google Compute, or OpenStack and would like to access the auto-generated - password that Packer uses to connect to a Windows instance via WinRM, you - can use the template variable `{{.WinRMPassword}}` in this option. Example: - - ```json - "ansible_env_vars": [ "WINRM_PASSWORD={{.WinRMPassword}}" ], - ``` - -- `ansible_ssh_extra_args` ([]string) - Specifies --ssh-extra-args on command line defaults to -o IdentitiesOnly=yes - -- `groups` ([]string) - The groups into which the Ansible host should - be placed. When unspecified, the host is not associated with any groups. - -- `empty_groups` ([]string) - The groups which should be present in - inventory file but remain empty. - -- `host_alias` (string) - The alias by which the Ansible host should be - known. Defaults to `default`. This setting is ignored when using a custom - inventory file. - -- `user` (string) - The `ansible_user` to use. Defaults to the user running - packer, NOT the user set for your communicator. If you want to use the same - user as the communicator, you will need to manually set it again in this - field. - -- `local_port` (int) - The port on which to attempt to listen for SSH - connections. This value is a starting point. The provisioner will attempt - listen for SSH connections on the first available of ten ports, starting at - `local_port`. A system-chosen port is used when `local_port` is missing or - empty. - -- `ssh_host_key_file` (string) - The SSH key that will be used to run the SSH - server on the host machine to forward commands to the target machine. - Ansible connects to this server and will validate the identity of the - server using the system known_hosts. The default behavior is to generate - and use a onetime key. Host key checking is disabled via the - `ANSIBLE_HOST_KEY_CHECKING` environment variable if the key is generated. - -- `ssh_authorized_key_file` (string) - The SSH public key of the Ansible - `ssh_user`. The default behavior is to generate and use a onetime key. If - this key is generated, the corresponding private key is passed to - `ansible-playbook` with the `-e ansible_ssh_private_key_file` option. - -- `sftp_command` (string) - The command to run on the machine being - provisioned by Packer to handle the SFTP protocol that Ansible will use to - transfer files. The command should read and write on stdin and stdout, - respectively. Defaults to `/usr/lib/sftp-server -e`. - -- `skip_version_check` (bool) - Check if ansible is installed prior to - running. Set this to `true`, for example, if you're going to install - ansible during the packer run. - -- `use_sftp` (bool) - Use SFTP - -- `inventory_directory` (string) - The directory in which to place the - temporary generated Ansible inventory file. By default, this is the - system-specific temporary file location. The fully-qualified name of this - temporary file will be passed to the `-i` argument of the `ansible` command - when this provisioner runs ansible. Specify this if you have an existing - inventory directory with `host_vars` `group_vars` that you would like to - use in the playbook that this provisioner will run. - -- `inventory_file_template` (string) - This template represents the format for the lines added to the temporary - inventory file that Packer will create to run Ansible against your image. - The default for recent versions of Ansible is: - "{{ .HostAlias }} ansible_host={{ .Host }} ansible_user={{ .User }} ansible_port={{ .Port }}\n" - Available template engines are: This option is a template engine; - variables available to you include the examples in the default (Host, - HostAlias, User, Port) as well as any variables available to you via the - "build" template engine. - -- `inventory_file` (string) - The inventory file to use during provisioning. - When unspecified, Packer will create a temporary inventory file and will - use the `host_alias`. - -- `keep_inventory_file` (bool) - If `true`, the Ansible provisioner will - not delete the temporary inventory file it creates in order to connect to - the instance. This is useful if you are trying to debug your ansible run - and using "--on-error=ask" in order to leave your instance running while you - test your playbook. this option is not used if you set an `inventory_file`. - -- `galaxy_file` (string) - A requirements file which provides a way to - install roles or collections with the [ansible-galaxy - cli](https://docs.ansible.com/ansible/latest/galaxy/user_guide.html#the-ansible-galaxy-command-line-tool) - on the local machine before executing `ansible-playbook`. By default, this is empty. - -- `galaxy_command` (string) - The command to invoke ansible-galaxy. By default, this is - `ansible-galaxy`. - -- `galaxy_force_install` (bool) - Force overwriting an existing role. - Adds `--force` option to `ansible-galaxy` command. By default, this is - `false`. - -- `roles_path` (string) - The path to the directory on your local system in which to - install the roles. Adds `--roles-path /path/to/your/roles` to - `ansible-galaxy` command. By default, this is empty, and thus `--roles-path` - option is not added to the command. - -- `collections_path` (string) - The path to the directory on your local system in which to - install the collections. Adds `--collections-path /path/to/your/collections` to - `ansible-galaxy` command. By default, this is empty, and thus `--collections-path` - option is not added to the command. - -- `use_proxy` (boolean) - When `true`, set up a localhost proxy adapter - so that Ansible has an IP address to connect to, even if your guest does not - have an IP address. For example, the adapter is necessary for Docker builds - to use the Ansible provisioner. If you set this option to `false`, but - Packer cannot find an IP address to connect Ansible to, it will - automatically set up the adapter anyway. - - In order for Ansible to connect properly even when use_proxy is false, you - need to make sure that you are either providing a valid username and ssh key - to the ansible provisioner directly, or that the username and ssh key - being used by the ssh communicator will work for your needs. If you do not - provide a user to ansible, it will use the user associated with your - builder, not the user running Packer. - use_proxy=false is currently only supported for SSH and WinRM. - - Currently, this defaults to `true` for all connection types. In the future, - this option will be changed to default to `false` for SSH and WinRM - connections where the provisioner has access to a host IP. - - diff --git a/website/content/partials/provisioner/ansible/Config-required.mdx b/website/content/partials/provisioner/ansible/Config-required.mdx deleted file mode 100644 index dc067fd87..000000000 --- a/website/content/partials/provisioner/ansible/Config-required.mdx +++ /dev/null @@ -1,5 +0,0 @@ - - -- `playbook_file` (string) - The playbook to be run by Ansible. - - diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 1198fe8f2..c9b8ca2a2 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -945,14 +945,6 @@ "title": "Overview", "path": "provisioners" }, - { - "title": "Ansible Local", - "path": "provisioners/ansible-local" - }, - { - "title": "Ansible (Remote)", - "path": "provisioners/ansible" - }, { "title": "Breakpoint", "path": "provisioners/breakpoint" diff --git a/website/data/docs-remote-plugins.json b/website/data/docs-remote-plugins.json index 16cfd8daa..c7f9ea5d2 100644 --- a/website/data/docs-remote-plugins.json +++ b/website/data/docs-remote-plugins.json @@ -16,5 +16,11 @@ "path": "vsphere", "repo": "hashicorp/packer-plugin-vsphere", "version": "latest" + }, + { + "title": "Ansible", + "path": "ansible", + "repo": "hashicorp/packer-plugin-ansible", + "version": "latest" } ]