def testWithAlternatePort(self): self.make_requests.side_effect = iter([ [INSTANCE_WITH_EXTERNAL_ADDRESS], [self.project_resource], ]) self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE self.Run(""" compute connect-to-serial-port instance-1 --zone zone-1 --port 3 """) self.CheckRequests( [(self.GetCompute().instances, 'Get', self.GetMessages().ComputeInstancesGetRequest( instance='instance-1', project='my-project', zone='zone-1'))], [(self.GetCompute().projects, 'Get', self.GetMessages().ComputeProjectsGetRequest( project='my-project'))], ) # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), ssh.Remote(self.gateway, user='******'), identity_file=self.private_key_file, options=self.options, port='9600') self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.env, force_connect=True)
def testWithAlternateUser(self): project_resource = self.messages.Project(name='my-project', ) self.make_requests.side_effect = iter([ [self.instance], [project_resource], [], ]) self.Run("""\ compute scp hapoo@instance-1:~/remote-file ~/local-dir --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], [(self.compute.projects, 'SetCommonInstanceMetadata', self.messages.ComputeProjectsSetCommonInstanceMetadataRequest( metadata=self.messages.Metadata(items=[ self.messages.Metadata.ItemsValueListEntry( key='ssh-keys', value='hapoo:' + self.public_key_material), ]), project='my-project'))], ) remote = ssh.Remote(self.remote.host, user='******') remote_file = ssh.FileReference('~/remote-file', remote=remote) # Polling self.poller_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHPoller), remote=remote, identity_file=self.private_key_file, max_wait_ms=ssh_utils.SSH_KEY_PROPAGATION_TIMEOUT_MS, options=dict(self.options, HostKeyAlias='compute.11111'), extra_flags=None, iap_tunnel_args=None) self.poller_poll.assert_called_once() # SCP Command self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [remote_file], self.local_dir, identity_file=self.private_key_file, extra_flags=[], port=None, recursive=False, compress=False, options=dict(self.options, HostKeyAlias='compute.11111'), iap_tunnel_args=None) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True)
def testWithAbsoluteExpiration(self): self.make_requests.side_effect = iter([ [INSTANCE_WITH_EXTERNAL_ADDRESS], [self.project_resource_without_metadata], [], ]) self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE self.Run(""" compute connect-to-serial-port instance-1 --zone zone-1 --ssh-key-expiration 2015-01-23T12:34:56+0000 """) self.CheckRequests( [(self.GetCompute().instances, 'Get', self.GetMessages().ComputeInstancesGetRequest( instance='instance-1', project='my-project', zone='zone-1'))], [(self.GetCompute().projects, 'Get', self.GetMessages().ComputeProjectsGetRequest( project='my-project'))], [(self.GetCompute().projects, 'SetCommonInstanceMetadata', self.GetMessages().ComputeProjectsSetCommonInstanceMetadataRequest( metadata=self.GetMessages().Metadata( items=[ self.GetMessages().Metadata.ItemsValueListEntry( key='ssh-keys', value=('me:{0} google-ssh {{"userName":"******",' '"expireOn":' '"2015-01-23T12:34:56+0000"}}').format( self.pubkey.ToEntry())), ]), project='my-project'))], ) # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), ssh.Remote(self.gateway, user='******'), identity_file=self.private_key_file, options=self.options, port='9600') self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.env, force_connect=True) # Known Hosts self.known_hosts_add.assert_called_once_with( mock_matchers.TypeMatcher(ssh.KnownHosts), '[ssh-serialport.googleapis.com]:9600', PUBLIC_KEY, overwrite=True) self.known_hosts_write.assert_called_once() self.AssertErrContains('Updating project ssh metadata')
def testSimpleCase(self, test_instance_key, explicit_flag): test_instance = self.instances[test_instance_key] self.make_requests.side_effect = iter([ [test_instance], [self.project_resource], ]) self.Run( 'compute scp {}:~/remote-file ~/local-dir --zone zone-1{}'.format( test_instance.name, ' --tunnel-through-iap' if explicit_flag else '')) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest( instance=test_instance.name, project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() expected_tunnel_args = iap_tunnel.SshTunnelArgs() expected_tunnel_args.track = self.track.prefix expected_tunnel_args.project = 'my-project' expected_tunnel_args.zone = 'zone-1' expected_tunnel_args.instance = test_instance.name # SCP Command remote_file = ssh.FileReference( '~/remote-file', remote=ssh.Remote.FromArg('me@compute.%s' % test_instance.id)) local_dir = ssh.FileReference('~/local-dir') self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [remote_file], local_dir, identity_file=self.private_key_file, extra_flags=[], port=None, recursive=False, compress=False, options=dict(self.options, HostKeyAlias='compute.%s' % test_instance.id), iap_tunnel_args=expected_tunnel_args) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True)
def testOsloginEnabledOnProjectButDisabledOnInstance(self, oslogin_mock): # Should fall through to alternate authentication. properties.VALUES.core.account.Set('*****@*****.**') self.remote = ssh.Remote('23.251.133.75', user='******') oslogin_mock.return_value = test_resources.MakeOsloginClient('v1') self.make_requests.side_effect = iter([ [INSTANCE_WITH_OSLOGIN_DISABLED], [self.project_resource_with_oslogin_enabled], [], ]) self.Run(""" compute ssh instance-1 --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], [(self.compute.projects, 'SetCommonInstanceMetadata', self.messages.ComputeProjectsSetCommonInstanceMetadataRequest( metadata=self.messages.Metadata(items=[ self.messages.Metadata.ItemsValueListEntry( key='enable-oslogin', value='true'), self.messages.Metadata.ItemsValueListEntry( key='ssh-keys', value='me:' + self.public_key_material), ]), project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, HostKeyAlias='compute.55555'), remote_command=None, iap_tunnel_args=None, remainder=[]) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True)
def testOverrideUsername(self, oslogin_mock): properties.VALUES.core.account.Set('*****@*****.**') self.remote = ssh.Remote.FromArg('[email protected]') self.remote_file = ssh.FileReference('~/remote-file', remote=self.remote) self.local_dir = ssh.FileReference('~/local-dir') oslogin_mock.return_value = test_resources.MakeOsloginClient('v1beta') self.make_requests.side_effect = iter([ [self.instance_with_oslogin_enabled], [self.project_resource], ]) self.Run("""\ compute scp someotheruser@instance-1:~/remote-file ~/local-dir --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SCP Command self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [self.remote_file], self.local_dir, identity_file=self.private_key_file, extra_flags=[], port=None, recursive=False, compress=False, options=dict(self.options, HostKeyAlias='compute.44444'), iap_tunnel_args=None) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True) self.AssertErrContains('Using OS Login user [user_google_com] instead ' 'of requested user [someotheruser]')
def testInvalidHostKeyType(self): # No valid keys are returned, so nothing is written to known hosts and # StrictHostKeyChecking stays set to the default value. self.make_requests.side_effect = iter([ [INSTANCE_WITH_GUEST_ATTRIBUTES_ENABLED], [self.project_resource], [GUEST_ATTRIBUTES_CONTENTS_INVALID_KEY_TYPE], ]) self.Run(""" compute ssh instance-6 --zone zone-1 """) self.CheckRequests( [(self.compute_v1.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-6', project='my-project', zone='zone-1'))], [(self.compute_v1.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], [(self.compute.instances, 'GetGuestAttributes', self.messages.ComputeInstancesGetGuestAttributesRequest( instance='instance-6', project='my-project', queryPath='hostkeys/', zone='zone-1'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # No host keys to add since it is an invalid type self.known_hosts_addmultiple.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, HostKeyAlias='compute.66666'), remote_command=None, iap_tunnel_args=None, remainder=[]) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True)
def testEnabledAtProjectLevel(self): self.make_requests.side_effect = iter([ [INSTANCE_WITH_EXTERNAL_ADDRESS], [self.project_resource_with_guest_attr_enabled], [GUEST_ATTRIBUTES_CONTENTS], ]) self.Run(""" compute ssh instance-1 --zone zone-1 """) self.CheckRequests( [(self.compute_v1.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute_v1.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], [(self.compute.instances, 'GetGuestAttributes', self.messages.ComputeInstancesGetGuestAttributesRequest( instance='instance-1', project='my-project', queryPath='hostkeys/', zone='zone-1'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, StrictHostKeyChecking='yes', HostKeyAlias='compute.11111'), remote_command=None, iap_tunnel_args=None, remainder=[]) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True)
def testSimpleCase(self): """Base case that makes sure SCPCommand is constructed. Note that the only difference against `compute scp` is that this command adds the `-r` recursive flag by default. """ self.make_requests.side_effect = iter([ [self.instance], [self.project_resource], ]) self.Run("""\ compute copy-files instance-1:~/remote-file ~/local-dir --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SCP Command self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [self.remote_file], self.local_dir, identity_file=self.private_key_file, extra_flags=None, port=None, recursive=True, compress=False, options=dict(self.options, HostKeyAlias='compute.11111'), iap_tunnel_args=None) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True) self.AssertErrContains('deprecated')
def testInstanceWithOsloginEnabled(self, oslogin_mock): properties.VALUES.core.account.Set('*****@*****.**') oslogin_mock.return_value = test_resources.MakeOsloginClient('v1') self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE self.make_requests.side_effect = iter([ [INSTANCE_WITH_OSLOGIN_ENABLED], [self.project_resource], ]) self.Run(""" compute connect-to-serial-port instance-4 --zone zone-1 """) self.CheckRequests( [(self.GetCompute().instances, 'Get', self.GetMessages().ComputeInstancesGetRequest( instance='instance-4', project='my-project', zone='zone-1'))], [(self.GetCompute().projects, 'Get', self.GetMessages().ComputeProjectsGetRequest( project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with( self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), ssh.Remote(self.gateway, user='******'), identity_file=self.private_key_file, options=self.options, port='9600') self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.env, force_connect=True) # Known Hosts self.known_hosts_add.assert_called_once_with( mock_matchers.TypeMatcher(ssh.KnownHosts), '[ssh-serialport.googleapis.com]:9600', PUBLIC_KEY, overwrite=True) self.known_hosts_write.assert_called_once() self.make_requests.assert_not_called()
def testRequestNonOsloginUser(self, oslogin_mock): properties.VALUES.core.account.Set('*****@*****.**') self.remote = ssh.Remote('23.251.133.75', user='******') oslogin_mock.return_value = test_resources.MakeOsloginClient('v1') self.make_requests.side_effect = iter([ [INSTANCE_WITH_OSLOGIN_ENABLED], [self.project_resource], ]) self.Run(""" compute ssh someotheruser@instance-1 --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, HostKeyAlias='compute.44444'), remote_command=None, iap_tunnel_args=None, remainder=[]) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True) self.AssertErrContains('Using OS Login user [user_google_com] instead ' 'of requested user [someotheruser]')
def testWithInternalIPAddress(self, track, api_version): self._SetUpForTrack(track, api_version) self.make_requests.side_effect = iter([ [self.instance_with_internal_ip_address], [self.project_resource], ]) self.Run(""" compute scp ~/local-file-1 instance-3:~/remote-dir --zone zone-1 --internal-ip """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-3', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) self.remote = ssh.Remote.FromArg('[email protected]') self.remote_dir = ssh.FileReference('~/remote-dir', self.remote) self.local_file = ssh.FileReference('~/local-file-1') self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [self.local_file], self.remote_dir, identity_file=self.private_key_file, extra_flags=[], port=None, recursive=False, compress=False, options=dict(self.options, HostKeyAlias='compute.33333'), iap_tunnel_args=None) self.ssh_init.assert_has_calls([ mock.call( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, options=dict(self.options, HostKeyAlias='compute.33333'), remote_command=[ '[ `curl "http://metadata.google.internal/' 'computeMetadata/v1/instance/id" -H "Metadata-Flavor: ' 'Google" -q` = 33333 ] || exit 23' ]), ], any_order=True)
def testInstanceWithNoExternalIp(self): self.make_requests.side_effect = iter([ [INSTANCE_WITH_NO_EXTERNAL_ADDRESS], [self.project_resource], ]) self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE self.Run(""" compute connect-to-serial-port instance-2 --zone zone-1 """) self.CheckRequests( [(self.GetCompute().instances, 'Get', self.GetMessages().ComputeInstancesGetRequest( instance='instance-2', project='my-project', zone='zone-1'))], [(self.GetCompute().projects, 'Get', self.GetMessages().ComputeProjectsGetRequest( project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with( self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), ssh.Remote(self.gateway, user='******'), identity_file=self.private_key_file, options=self.options, port='9600') self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.env, force_connect=True) # Known Hosts self.known_hosts_add.assert_called_once_with( mock_matchers.TypeMatcher(ssh.KnownHosts), '[ssh-serialport.googleapis.com]:9600', PUBLIC_KEY, overwrite=True) self.known_hosts_write.assert_called_once() self.make_requests.assert_not_called()
def testSSHWithCommand(self): """Execute a remote command.""" self.Run( 'app instances ssh --service default --version v1 i2 -- echo hi') self._AssertPopulateCalled() self.ssh_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.remote, identity_file=self.key_file, tty=None, options=self.options, remote_command='echo hi'.split()) self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.ssh_env)
def testEnabledAtProjectDisabledAtInstance(self): # Instance value overrides project value, so Guest Attributes won't # be retrieved and StrictHostKeyChecking should be set to 'no'. self.make_requests.side_effect = iter([ [INSTANCE_WITH_GUEST_ATTRIBUTES_DISABLED], [self.project_resource_with_guest_attr_enabled], ]) self.Run(""" compute ssh instance-7 --zone zone-1 """) self.CheckRequests( [(self.compute_v1.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-7', project='my-project', zone='zone-1'))], [(self.compute_v1.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, StrictHostKeyChecking='no', HostKeyAlias='compute.77777'), remote_command=None, iap_tunnel_args=None, remainder=[]) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True)
def testZonePrompting(self): self.StartPatch('googlecloudsdk.core.console.console_io.CanPrompt', return_value=True) self.make_requests.side_effect = iter([ [ self.messages.Instance(name='instance-1', zone='zone-1'), ], [self.instance], [self.project_resource], ]) self.Run("""\ compute scp instance-1:~/remote-file ~/local-dir """) self.CheckRequests( self.FilteredInstanceAggregateListRequest('instance-1'), [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) self.AssertErrContains( 'No zone specified. Using zone [zone-1] for instance: [instance-1].' ) # SCP Command self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [self.remote_file], self.local_dir, identity_file=self.private_key_file, extra_flags=[], port=None, recursive=False, compress=False, options=dict(self.options, HostKeyAlias='compute.11111'), iap_tunnel_args=None) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True)
def testWithManyRemoteFilesToLocalDestination(self): self.make_requests.side_effect = iter([ [self.instance], [self.project_resource], ]) self.Run(r""" compute scp instance-1:~/remote-file-1 instance-1:~/remote-file-2 instance-1:~/remote-file-3 ~/local-dir --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) remote = ssh.Remote('23.251.133.1', user='******') # SCP Command self.scp_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), [ ssh.FileReference('~/remote-file-1', remote=remote), ssh.FileReference('~/remote-file-2', remote=remote), ssh.FileReference('~/remote-file-3', remote=remote), ], self.local_dir, identity_file=self.private_key_file, extra_flags=[], port=None, recursive=False, compress=False, options=dict(self.options, HostKeyAlias='compute.11111'), iap_tunnel_args=None) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True)
def testUnknownOsloginApiVarsion(self, oslogin_mock): # Should fall through to alternate authentication. properties.VALUES.core.account.Set('*****@*****.**') self.remote = ssh.Remote('23.251.133.75', user='******') oslogin_mock.side_effect = apis_util.UnknownVersionError( 'oslogin', 'v1') self.make_requests.side_effect = iter([ [INSTANCE_WITH_OSLOGIN_ENABLED], [self.project_resource], ]) self.Run(""" compute ssh instance-1 --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, HostKeyAlias='compute.44444'), remote_command=None, iap_tunnel_args=None, remainder=[]) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True)
def testSSHWithContainer(self): """Go straight to the app container.""" self.Run( 'app instances ssh --service default --version v1 i2 --container ' 'gaeapp') self._AssertPopulateCalled() self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.remote, identity_file=self.key_file, tty=True, options=self.options, remote_command='sudo docker exec -it gaeapp /bin/sh'.split()) self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.ssh_env)
def testSSH(self): """Base case of unlocked instance.""" self.Run('app instances ssh --service default --version v1 i2') self.ensure_keys_exist.assert_called_once_with( mock_matchers.TypeMatcher(ssh.Keys), overwrite=False) self._AssertPopulateCalled() self.ssh_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.remote, identity_file=self.key_file, tty=None, options=self.options, remote_command=None) self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.ssh_env)
def testWithURI(self): """SSH using URI instead of specifying service and version.""" self.Run('app instances ssh https://appengine.googleapis.com/v1/apps/' 'fakeproject/services/default/versions/v1/instances/i2') self.ensure_keys_exist.assert_called_once_with( mock_matchers.TypeMatcher(ssh.Keys), overwrite=False) self._AssertPopulateCalled() self.ssh_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.remote, identity_file=self.key_file, tty=None, options=self.options, remote_command=None) self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.ssh_env)
def testFlags(self): """Remote to local, but with all flags here.""" self._RunScp('--recurse --compress i2:rem_1 local_1') self.require_ssh.assert_called_once() self.ensure_keys_exist.assert_called_once_with( mock_matchers.TypeMatcher(ssh.Keys), overwrite=False) self._AssertPopulateCalled() self.scp_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), [self.remote_file_1], self.local_file_1, identity_file=self.key_file, recursive=True, compress=True, options=self.options) self.scp_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), self.ssh_env)
def testMultiRemoteToLocal(self): """Multiple remote files (same instance) to local.""" self._RunScp('i2:rem_1 i2:rem_2 local_1') self.require_ssh.assert_called_once() self.ensure_keys_exist.assert_called_once_with( mock_matchers.TypeMatcher(ssh.Keys), overwrite=False) self._AssertPopulateCalled() self.scp_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), [self.remote_file_1, self.remote_file_2], self.local_file_1, identity_file=self.key_file, recursive=False, compress=False, options=self.options) self.scp_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), self.ssh_env)
def testSingleLocalToRemote(self): """Simple case with remote to local.""" self._RunScp('local_1 i2:rem_1') self.require_ssh.assert_called_once() self.ensure_keys_exist.assert_called_once_with( mock_matchers.TypeMatcher(ssh.Keys), overwrite=False) self._AssertPopulateCalled() self.scp_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), [self.local_file_1], self.remote_file_1, identity_file=self.key_file, recursive=False, compress=False, options=self.options) self.scp_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SCPCommand), self.ssh_env)
def _assertSSHCalled(self): self.ensure_keys.assert_called_once_with(mock_matchers.TypeMatcher( ssh.Keys), None, allow_passphrase=True) self.poller_poll.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHPoller), mock_matchers.TypeMatcher(ssh.Environment), force_connect=True) # SSH Command self.ssh_init.assert_called_once() self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), mock_matchers.TypeMatcher(ssh.Environment), force_connect=True)
def testSSHShortFlagsInBeta(self): """Test that short flags work in the beta version.""" self.track = calliope_base.ReleaseTrack.BETA self.Run('app instances ssh -s default -v v1 i2') self.ensure_keys_exist.assert_called_once_with( mock_matchers.TypeMatcher(ssh.Keys), overwrite=False) self._AssertPopulateCalled() self.ssh_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.remote, identity_file=self.key_file, tty=None, options=self.options, remote_command=None) self.ssh_run.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), self.ssh_env) self.AssertErrContains('the short flags `-s` and `-v` are deprecated')
def testPlain(self): self.make_requests.side_effect = iter([ [self.instance], [self.project_resource], ]) self.Run("""\ compute scp --plain instance-1:~/remote-file ~/local-dir --zone zone-1 """) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Don't require SSH keys self.ensure_keys.assert_not_called() # No polling self.poller_poll.assert_not_called() # SCP Command without options and identity_file self.scp_init.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), [self.remote_file], self.local_dir, identity_file=None, extra_flags=[], port=None, recursive=False, compress=False, options=None, iap_tunnel_args=None) self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SCPCommand), self.env, force_connect=True)
def testWithCommandAndImplementationArgs(self): self.make_requests.side_effect = iter([ [INSTANCE_WITH_EXTERNAL_ADDRESS], [self.project_resource], ]) self.Run([ 'compute', 'ssh', 'instance-1', '--zone', 'zone-1', '--command', '"/bin/sh"', '--', '-v', '1 2 3', 'a | b', 'b\'y' ]) self.CheckRequests( [(self.compute_v1.instances, 'Get', self.messages.ComputeInstancesGetRequest(instance='instance-1', project='my-project', zone='zone-1'))], [(self.compute_v1.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], ) # Require SSH keys self.ensure_keys.assert_called_once_with(self.keys, None, allow_passphrase=True) # No polling self.poller_poll.assert_not_called() # SSH Command self.ssh_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHCommand), remote=self.remote, identity_file=self.private_key_file, extra_flags=[], tty=None, options=dict(self.options, HostKeyAlias='compute.11111'), remote_command=['"/bin/sh"'], iap_tunnel_args=None, remainder=['-v', '1 2 3', 'a | b', 'b\'y']) self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher( ssh.SSHCommand), self.env, force_connect=True)
def testWithPollingTimeout(self, test_instance_key): self.poller_poll.side_effect = retry.WaitException( 'msg', 'result', 'state') project_resource = self.messages.Project(name='my-project', ) test_instance = self.instances[test_instance_key] self.make_requests.side_effect = iter([ [test_instance], [project_resource], [], ]) with self.AssertRaisesExceptionMatches( ssh_utils.NetworkError, 'Could not SSH into the instance'): self.Run('compute scp hapoo@{}:~/remote-file ~/local-dir ' '--zone zone-1 --tunnel-through-iap'.format( test_instance.name)) self.CheckRequests( [(self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest( instance=test_instance.name, project='my-project', zone='zone-1'))], [(self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest(project='my-project'))], [(self.compute.projects, 'SetCommonInstanceMetadata', self.messages.ComputeProjectsSetCommonInstanceMetadataRequest( metadata=self.messages.Metadata(items=[ self.messages.Metadata.ItemsValueListEntry( key='ssh-keys', value='hapoo:' + self.public_key_material), ]), project='my-project'))], ) expected_tunnel_args = iap_tunnel.SshTunnelArgs() expected_tunnel_args.track = self.track.prefix expected_tunnel_args.project = 'my-project' expected_tunnel_args.zone = 'zone-1' expected_tunnel_args.instance = test_instance.name # Polling remote = ssh.Remote.FromArg('hapoo@compute.%s' % test_instance.id) self.poller_init.assert_called_once_with( mock_matchers.TypeMatcher(ssh.SSHPoller), remote=remote, identity_file=self.private_key_file, max_wait_ms=ssh_utils.SSH_KEY_PROPAGATION_TIMEOUT_MS, options=dict(self.options, HostKeyAlias='compute.%s' % test_instance.id), extra_flags=None, iap_tunnel_args=expected_tunnel_args) self.poller_poll.assert_called_once() self.scp_run.assert_not_called()
def testTimeout(self): disk_ref = self._GetDiskRef('disk-1') snapshot_ref = self._GetSnapshotRef('random-name-0') operation_ref = self._GetOperationRef('operation-1') self.api_mock.batch_responder.ExpectBatch([ (self._GetCreateSnapshotRequest(disk_ref, snapshot_ref), self._GetOperationMessage(operation_ref, self.status_enum.PENDING)), ]) waiter_mock = self.StartPatch( 'googlecloudsdk.api_lib.util.waiter.WaitFor', autospec=True) self.Run('compute disks snapshot disk-1 --zone central2-a') waiter_mock.assert_called_once_with( mock_matchers.TypeMatcher(poller.BatchPoller), mock_matchers.TypeMatcher(poller.OperationBatch), 'Creating snapshot(s) random-name-0', max_wait_ms=None)