Skip to content

Commit d02b153

Browse files
committed
Fix: Force SCP mode for file transfer with bastion
Force SCP mode for Ansible file transfers with bastion. Add ANSIBLE_SCP_IF_SSH=True environment variable when local_build=true to force Ansible to use SCP instead of SFTP for file transfers. Root cause: Ansible defaults to SFTP for file transfers, which causes failures when connecting through bastion/jump hosts that don't have sftp-server installed. The existing --scp-extra-args '-O' flag was being ignored because Ansible was using SFTP, not SCP. Error without this fix: failed to transfer file to /home/ubuntu/.ansible/tmp/... bash: line 1: /usr/lib/sftp-server: No such file or directory scp: Connection closed Solution: Set ANSIBLE_SCP_IF_SSH=True to force Ansible to use SCP mode when local_build=true (builds through bastion). Once SCP is being used, the --scp-extra-args '-O' flag applies, forcing legacy SCP protocol which works correctly through the bastion. Changes: - Added local.ansible_env_vars conditional in all templates - When local_build=true: includes ANSIBLE_SCP_IF_SSH=True - When local_build=false: standard Ansible environment (Jenkins builds) - Updated provisioner blocks to use local.ansible_env_vars Templates updated: - builder.pkr.hcl - docker.pkr.hcl - devstack.pkr.hcl - devstack-pre-pip-yoga.pkr.hcl - windows-builder.pkr.hcl Backward compatibility: Existing Jenkins builds continue to work unchanged since local_build defaults to false. Only affects builds with local_build=true (packer-build-action through bastion). Change-Id: Iae0d6f2284fb2cdefa827c951bd11b51a5a56e19 Signed-off-by: Anil Belur <[email protected]>
1 parent de07429 commit d02b153

File tree

6 files changed

+150
-45
lines changed

6 files changed

+150
-45
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
fixes:
3+
- |
4+
Fix Ansible file transfer failures when building through bastion/jump hosts.
5+
6+
**Problem**: Packer builds with ``local_build=true`` (bastion/jump host mode)
7+
were failing during Ansible provisioning with SFTP errors:
8+
9+
.. code-block:: text
10+
11+
failed to transfer file to /home/ubuntu/.ansible/tmp/...
12+
bash: line 1: /usr/lib/sftp-server: No such file or directory
13+
scp: Connection closed
14+
15+
**Root Cause**: Ansible defaults to SFTP for file transfers, not SCP.
16+
The existing ``--scp-extra-args '-O'`` flag was being ignored because
17+
Ansible was using SFTP, not SCP. Many cloud instances and bastion hosts
18+
don't have ``sftp-server`` installed, causing transfer failures.
19+
20+
**Resolution**: Added ``ANSIBLE_SCP_IF_SSH=True`` environment variable
21+
when ``local_build=true`` to force Ansible to use SCP mode instead of
22+
SFTP. This makes the ``--scp-extra-args '-O'`` flag take effect, which
23+
forces the legacy SCP protocol that works through bastion hosts.
24+
25+
**Implementation**: Created conditional ``ansible_env_vars`` in the
26+
locals block of all templates:
27+
28+
- When ``local_build=true``: Sets ``ANSIBLE_SCP_IF_SSH=True``
29+
- When ``local_build=false``: Standard Ansible environment (no change)
30+
31+
**Backward Compatibility**: This change only affects builds with
32+
``local_build=true`` (packer-build-action through bastion). Existing
33+
Jenkins builds continue to work unchanged since ``local_build``
34+
defaults to false.
35+
36+
Templates updated:
37+
38+
- templates/builder.pkr.hcl
39+
- templates/docker.pkr.hcl
40+
- templates/devstack.pkr.hcl
41+
- templates/devstack-pre-pip-yoga.pkr.hcl
42+
- templates/windows-builder.pkr.hcl
43+
44+
**Usage**: When building through a bastion/jump host, set:
45+
46+
.. code-block:: bash
47+
48+
packer build -var local_build=true ...
49+
50+
Reference: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/ssh_connection.html

templates/builder.pkr.hcl

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,32 @@ variable "vm_volume_size" {
158158
}
159159

160160
locals {
161-
# SSH arguments for local builds only
161+
# SSH arguments - SCP compatibility for local builds
162162
ssh_extra_args = var.local_build ? [
163163
"--scp-extra-args", "'-O'",
164164
"--ssh-extra-args",
165165
"-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa"
166166
] : [
167167
"--ssh-extra-args", "-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa"
168168
]
169+
170+
# Ansible environment variables - force SCP for local builds to work with bastion
171+
ansible_env_vars = var.local_build ? [
172+
"ANSIBLE_NOCOWS=1",
173+
"ANSIBLE_PIPELINING=False",
174+
"ANSIBLE_HOST_KEY_CHECKING=False",
175+
"ANSIBLE_SCP_IF_SSH=True",
176+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
177+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
178+
"ANSIBLE_STDOUT_CALLBACK=debug"
179+
] : [
180+
"ANSIBLE_NOCOWS=1",
181+
"ANSIBLE_PIPELINING=False",
182+
"ANSIBLE_HOST_KEY_CHECKING=False",
183+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
184+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
185+
"ANSIBLE_STDOUT_CALLBACK=debug"
186+
]
169187
}
170188

171189
source "docker" "builder" {
@@ -216,14 +234,7 @@ build {
216234
}
217235

218236
provisioner "ansible" {
219-
ansible_env_vars = [
220-
"ANSIBLE_NOCOWS=1",
221-
"ANSIBLE_PIPELINING=False",
222-
"ANSIBLE_HOST_KEY_CHECKING=False",
223-
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
224-
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
225-
"ANSIBLE_STDOUT_CALLBACK=debug"
226-
]
237+
ansible_env_vars = local.ansible_env_vars
227238
command = "./common-packer/ansible-playbook.sh"
228239
extra_arguments = local.ssh_extra_args
229240
playbook_file = "provision/local-builder.yaml"

templates/devstack-pre-pip-yoga.pkr.hcl

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ variable "vm_volume_size" {
161161
}
162162

163163
locals {
164-
# SSH arguments for local builds only
164+
# SSH arguments - SCP compatibility for local builds
165165
ssh_extra_args = var.local_build ? [
166166
"--extra-vars", "os_branch=stable/yoga rdo_branch=yoga",
167167
"--scp-extra-args", "'-O'",
@@ -171,6 +171,24 @@ locals {
171171
"--extra-vars", "os_branch=stable/yoga rdo_branch=yoga",
172172
"--ssh-extra-args", "-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa"
173173
]
174+
175+
# Ansible environment variables - force SCP for local builds to work with bastion
176+
ansible_env_vars = var.local_build ? [
177+
"ANSIBLE_NOCOWS=1",
178+
"ANSIBLE_PIPELINING=False",
179+
"ANSIBLE_HOST_KEY_CHECKING=False",
180+
"ANSIBLE_SCP_IF_SSH=True",
181+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
182+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
183+
"ANSIBLE_STDOUT_CALLBACK=debug"
184+
] : [
185+
"ANSIBLE_NOCOWS=1",
186+
"ANSIBLE_PIPELINING=False",
187+
"ANSIBLE_HOST_KEY_CHECKING=False",
188+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
189+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
190+
"ANSIBLE_STDOUT_CALLBACK=debug"
191+
]
174192
}
175193

176194
source "docker" "devstack-pre-pip-yoga" {
@@ -221,14 +239,7 @@ build {
221239
}
222240

223241
provisioner "ansible" {
224-
ansible_env_vars = [
225-
"ANSIBLE_NOCOWS=1",
226-
"ANSIBLE_PIPELINING=False",
227-
"ANSIBLE_HOST_KEY_CHECKING=False",
228-
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
229-
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
230-
"ANSIBLE_STDOUT_CALLBACK=debug"
231-
]
242+
ansible_env_vars = local.ansible_env_vars
232243
command = "./common-packer/ansible-playbook.sh"
233244
extra_arguments = local.ssh_extra_args
234245
playbook_file = "provision/devstack-pre-pip-centos.yaml"

templates/devstack.pkr.hcl

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ variable "vm_volume_size" {
163163
}
164164

165165
locals {
166-
# SSH arguments for local builds only
166+
# SSH arguments - SCP compatibility for local builds
167167
ssh_extra_args = var.local_build ? [
168168
"--extra-vars", "os_branch=stable/yoga rdo_branch=yoga",
169169
"--scp-extra-args", "'-O'",
@@ -173,6 +173,24 @@ locals {
173173
"--extra-vars", "os_branch=stable/yoga rdo_branch=yoga",
174174
"--ssh-extra-args", "-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa"
175175
]
176+
177+
# Ansible environment variables - force SCP for local builds to work with bastion
178+
ansible_env_vars = var.local_build ? [
179+
"ANSIBLE_NOCOWS=1",
180+
"ANSIBLE_PIPELINING=False",
181+
"ANSIBLE_HOST_KEY_CHECKING=False",
182+
"ANSIBLE_SCP_IF_SSH=True",
183+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
184+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
185+
"ANSIBLE_STDOUT_CALLBACK=debug"
186+
] : [
187+
"ANSIBLE_NOCOWS=1",
188+
"ANSIBLE_PIPELINING=False",
189+
"ANSIBLE_HOST_KEY_CHECKING=False",
190+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
191+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
192+
"ANSIBLE_STDOUT_CALLBACK=debug"
193+
]
176194
}
177195

178196
source "docker" "devstack" {
@@ -223,14 +241,7 @@ build {
223241
}
224242

225243
provisioner "ansible" {
226-
ansible_env_vars = [
227-
"ANSIBLE_NOCOWS=1",
228-
"ANSIBLE_PIPELINING=False",
229-
"ANSIBLE_HOST_KEY_CHECKING=False",
230-
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
231-
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
232-
"ANSIBLE_STDOUT_CALLBACK=debug"
233-
]
244+
ansible_env_vars = local.ansible_env_vars
234245
command = "./common-packer/ansible-playbook.sh"
235246
extra_arguments = local.ssh_extra_args
236247
playbook_file = "provision/devstack-centos.yaml"

templates/docker.pkr.hcl

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,32 @@ variable "vm_volume_size" {
164164
}
165165

166166
locals {
167-
# SSH arguments for local builds only
167+
# SSH arguments - SCP compatibility for local builds
168168
ssh_extra_args = var.local_build ? [
169169
"--scp-extra-args", "'-O'",
170170
"--ssh-extra-args",
171171
"-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa"
172172
] : [
173173
"--ssh-extra-args", "-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa"
174174
]
175+
176+
# Ansible environment variables - force SCP for local builds to work with bastion
177+
ansible_env_vars = var.local_build ? [
178+
"ANSIBLE_NOCOWS=1",
179+
"ANSIBLE_PIPELINING=False",
180+
"ANSIBLE_HOST_KEY_CHECKING=False",
181+
"ANSIBLE_SCP_IF_SSH=True",
182+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
183+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
184+
"ANSIBLE_STDOUT_CALLBACK=debug"
185+
] : [
186+
"ANSIBLE_NOCOWS=1",
187+
"ANSIBLE_PIPELINING=False",
188+
"ANSIBLE_HOST_KEY_CHECKING=False",
189+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
190+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
191+
"ANSIBLE_STDOUT_CALLBACK=debug"
192+
]
175193
}
176194

177195
source "docker" "docker" {
@@ -222,14 +240,7 @@ build {
222240
}
223241

224242
provisioner "ansible" {
225-
ansible_env_vars = [
226-
"ANSIBLE_NOCOWS=1",
227-
"ANSIBLE_PIPELINING=False",
228-
"ANSIBLE_HOST_KEY_CHECKING=False",
229-
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
230-
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
231-
"ANSIBLE_STDOUT_CALLBACK=debug"
232-
]
243+
ansible_env_vars = local.ansible_env_vars
233244
command = "./common-packer/ansible-playbook.sh"
234245
extra_arguments = local.ssh_extra_args
235246
playbook_file = "provision/local-docker.yaml"

templates/windows-builder.pkr.hcl

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ variable "vm_volume_size" {
160160
}
161161

162162
locals {
163-
# SSH arguments for local builds only
163+
# SSH arguments - SCP compatibility for local builds
164164
ssh_extra_args = var.local_build ? [
165165
"--extra-vars", "ansible_shell_type=powershell",
166166
"--extra-vars", "ansible_shell_executable=None",
@@ -172,6 +172,24 @@ locals {
172172
"--extra-vars", "ansible_shell_executable=None",
173173
"--ssh-extra-args", "-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa"
174174
]
175+
176+
# Ansible environment variables - force SCP for local builds to work with bastion
177+
ansible_env_vars = var.local_build ? [
178+
"ANSIBLE_NOCOWS=1",
179+
"ANSIBLE_PIPELINING=False",
180+
"ANSIBLE_HOST_KEY_CHECKING=False",
181+
"ANSIBLE_SCP_IF_SSH=True",
182+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
183+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
184+
"ANSIBLE_STDOUT_CALLBACK=debug"
185+
] : [
186+
"ANSIBLE_NOCOWS=1",
187+
"ANSIBLE_PIPELINING=False",
188+
"ANSIBLE_HOST_KEY_CHECKING=False",
189+
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
190+
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
191+
"ANSIBLE_STDOUT_CALLBACK=debug"
192+
]
175193
}
176194

177195
source "openstack" "windows-builder" {
@@ -209,14 +227,7 @@ build {
209227
}
210228

211229
provisioner "ansible" {
212-
ansible_env_vars = [
213-
"ANSIBLE_NOCOWS=1",
214-
"ANSIBLE_PIPELINING=False",
215-
"ANSIBLE_HOST_KEY_CHECKING=False",
216-
"ANSIBLE_ROLES_PATH=${var.ansible_roles_path}",
217-
"ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
218-
"ANSIBLE_STDOUT_CALLBACK=debug"
219-
]
230+
ansible_env_vars = local.ansible_env_vars
220231
command = "./common-packer/ansible-playbook.sh"
221232
extra_arguments = local.ssh_extra_args
222233
playbook_file = "provision/local-windows-builder.yaml"

0 commit comments

Comments
 (0)