mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-01 14:51:27 -07:00
add support for opening shell on remote Windows host (#43919)
* add support for opening shell on remote Windows host * added arg completion and fix sanity check * remove uneeded arg
This commit is contained in:
parent
aef16ee195
commit
6ca4ea0c1f
3 changed files with 79 additions and 20 deletions
|
@ -33,6 +33,7 @@ from lib.core_ci import (
|
||||||
|
|
||||||
from lib.manage_ci import (
|
from lib.manage_ci import (
|
||||||
ManagePosixCI,
|
ManagePosixCI,
|
||||||
|
ManageWindowsCI,
|
||||||
)
|
)
|
||||||
|
|
||||||
from lib.util import (
|
from lib.util import (
|
||||||
|
@ -321,30 +322,35 @@ def delegate_remote(args, exclude, require, integration_targets):
|
||||||
|
|
||||||
core_ci.wait()
|
core_ci.wait()
|
||||||
|
|
||||||
options = {
|
if platform == 'windows':
|
||||||
'--remote': 1,
|
# Windows doesn't need the ansible-test fluff, just run the SSH command
|
||||||
}
|
manage = ManageWindowsCI(core_ci)
|
||||||
|
cmd = ['powershell.exe']
|
||||||
|
else:
|
||||||
|
options = {
|
||||||
|
'--remote': 1,
|
||||||
|
}
|
||||||
|
|
||||||
cmd = generate_command(args, 'ansible/test/runner/test.py', options, exclude, require)
|
cmd = generate_command(args, 'ansible/test/runner/test.py', options, exclude, require)
|
||||||
|
|
||||||
if httptester_id:
|
if httptester_id:
|
||||||
cmd += ['--inject-httptester']
|
cmd += ['--inject-httptester']
|
||||||
|
|
||||||
if isinstance(args, TestConfig):
|
if isinstance(args, TestConfig):
|
||||||
if args.coverage and not args.coverage_label:
|
if args.coverage and not args.coverage_label:
|
||||||
cmd += ['--coverage-label', 'remote-%s-%s' % (platform, version)]
|
cmd += ['--coverage-label', 'remote-%s-%s' % (platform, version)]
|
||||||
|
|
||||||
if isinstance(args, IntegrationConfig):
|
if isinstance(args, IntegrationConfig):
|
||||||
if not args.allow_destructive:
|
if not args.allow_destructive:
|
||||||
cmd.append('--allow-destructive')
|
cmd.append('--allow-destructive')
|
||||||
|
|
||||||
# remote instances are only expected to have a single python version available
|
# remote instances are only expected to have a single python version available
|
||||||
if isinstance(args, UnitsConfig) and not args.python:
|
if isinstance(args, UnitsConfig) and not args.python:
|
||||||
cmd += ['--python', 'default']
|
cmd += ['--python', 'default']
|
||||||
|
|
||||||
|
manage = ManagePosixCI(core_ci)
|
||||||
|
|
||||||
manage = ManagePosixCI(core_ci)
|
|
||||||
manage.setup()
|
manage.setup()
|
||||||
|
|
||||||
if isinstance(args, IntegrationConfig):
|
if isinstance(args, IntegrationConfig):
|
||||||
cloud_platforms = get_cloud_providers(args)
|
cloud_platforms = get_cloud_providers(args)
|
||||||
|
|
||||||
|
@ -355,8 +361,9 @@ def delegate_remote(args, exclude, require, integration_targets):
|
||||||
manage.ssh(cmd, ssh_options)
|
manage.ssh(cmd, ssh_options)
|
||||||
success = True
|
success = True
|
||||||
finally:
|
finally:
|
||||||
manage.ssh('rm -rf /tmp/results && cp -a ansible/test/results /tmp/results && chmod -R a+r /tmp/results')
|
if platform != 'windows':
|
||||||
manage.download('/tmp/results', 'test')
|
manage.ssh('rm -rf /tmp/results && cp -a ansible/test/results /tmp/results && chmod -R a+r /tmp/results')
|
||||||
|
manage.download('/tmp/results', 'test')
|
||||||
finally:
|
finally:
|
||||||
if args.remote_terminate == 'always' or (args.remote_terminate == 'success' and success):
|
if args.remote_terminate == 'always' or (args.remote_terminate == 'success' and success):
|
||||||
core_ci.stop()
|
core_ci.stop()
|
||||||
|
|
|
@ -32,6 +32,22 @@ class ManageWindowsCI(object):
|
||||||
:type core_ci: AnsibleCoreCI
|
:type core_ci: AnsibleCoreCI
|
||||||
"""
|
"""
|
||||||
self.core_ci = core_ci
|
self.core_ci = core_ci
|
||||||
|
self.ssh_args = ['-i', self.core_ci.ssh_key.key]
|
||||||
|
|
||||||
|
ssh_options = dict(
|
||||||
|
BatchMode='yes',
|
||||||
|
StrictHostKeyChecking='no',
|
||||||
|
UserKnownHostsFile='/dev/null',
|
||||||
|
ServerAliveInterval=15,
|
||||||
|
ServerAliveCountMax=4,
|
||||||
|
)
|
||||||
|
|
||||||
|
for ssh_option in sorted(ssh_options):
|
||||||
|
self.ssh_args += ['-o', '%s=%s' % (ssh_option, ssh_options[ssh_option])]
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
"""Used in delegate_remote to setup the host, no action is required for Windows."""
|
||||||
|
pass
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
"""Wait for instance to respond to ansible ping."""
|
"""Wait for instance to respond to ansible ping."""
|
||||||
|
@ -59,6 +75,24 @@ class ManageWindowsCI(object):
|
||||||
raise ApplicationError('Timeout waiting for %s/%s instance %s.' %
|
raise ApplicationError('Timeout waiting for %s/%s instance %s.' %
|
||||||
(self.core_ci.platform, self.core_ci.version, self.core_ci.instance_id))
|
(self.core_ci.platform, self.core_ci.version, self.core_ci.instance_id))
|
||||||
|
|
||||||
|
def ssh(self, command, options=None):
|
||||||
|
"""
|
||||||
|
:type command: str | list[str]
|
||||||
|
:type options: list[str] | None
|
||||||
|
"""
|
||||||
|
if not options:
|
||||||
|
options = []
|
||||||
|
|
||||||
|
if isinstance(command, list):
|
||||||
|
command = ' '.join(pipes.quote(c) for c in command)
|
||||||
|
|
||||||
|
run_command(self.core_ci.args,
|
||||||
|
['ssh', '-tt', '-q'] + self.ssh_args +
|
||||||
|
options +
|
||||||
|
['-p', '22',
|
||||||
|
'%s@%s' % (self.core_ci.connection.username, self.core_ci.connection.hostname)] +
|
||||||
|
[command])
|
||||||
|
|
||||||
|
|
||||||
class ManageNetworkCI(object):
|
class ManageNetworkCI(object):
|
||||||
"""Manage access to a network instance provided by Ansible Core CI."""
|
"""Manage access to a network instance provided by Ansible Core CI."""
|
||||||
|
|
|
@ -564,7 +564,7 @@ def add_environments(parser, tox_version=False, tox_only=False):
|
||||||
environments.add_argument('--remote',
|
environments.add_argument('--remote',
|
||||||
metavar='PLATFORM',
|
metavar='PLATFORM',
|
||||||
default=None,
|
default=None,
|
||||||
help='run from a remote instance').completer = complete_remote
|
help='run from a remote instance').completer = complete_remote_shell if parser.prog.endswith(' shell') else complete_remote
|
||||||
|
|
||||||
remote = parser.add_argument_group(title='remote arguments')
|
remote = parser.add_argument_group(title='remote arguments')
|
||||||
|
|
||||||
|
@ -685,6 +685,24 @@ def complete_remote(prefix, parsed_args, **_):
|
||||||
return [i for i in images if i.startswith(prefix)]
|
return [i for i in images if i.startswith(prefix)]
|
||||||
|
|
||||||
|
|
||||||
|
def complete_remote_shell(prefix, parsed_args, **_):
|
||||||
|
"""
|
||||||
|
:type prefix: unicode
|
||||||
|
:type parsed_args: any
|
||||||
|
:rtype: list[str]
|
||||||
|
"""
|
||||||
|
del parsed_args
|
||||||
|
|
||||||
|
with open('test/runner/completion/remote.txt', 'r') as completion_fd:
|
||||||
|
images = completion_fd.read().splitlines()
|
||||||
|
|
||||||
|
# 2008 doesn't support SSH so we do not add to the list of valid images
|
||||||
|
with open('test/runner/completion/windows.txt', 'r') as completion_fd:
|
||||||
|
images.extend(["windows/%s" % i for i in completion_fd.read().splitlines() if i != '2008'])
|
||||||
|
|
||||||
|
return [i for i in images if i.startswith(prefix)]
|
||||||
|
|
||||||
|
|
||||||
def complete_docker(prefix, parsed_args, **_):
|
def complete_docker(prefix, parsed_args, **_):
|
||||||
"""
|
"""
|
||||||
:type prefix: unicode
|
:type prefix: unicode
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue