コード例 #1
0
    def upgrade(self):
        """ Allows users to upgrade to the latest version of AppScale."""
        contents_as_yaml = yaml.safe_load(self.read_appscalefile())

        # Construct the appscale-upgrade command from argv and the contents of
        # the AppScalefile.
        command = []

        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml['keyname'])

        if 'verbose' in contents_as_yaml and contents_as_yaml[
                'verbose'] == True:
            command.append("--verbose")

        if 'ips_layout' in contents_as_yaml:
            command.append('--ips_layout')
            command.append(
                base64.b64encode(yaml.dump(contents_as_yaml['ips_layout'])))

        if 'login' in contents_as_yaml:
            command.extend(['--login', contents_as_yaml['login']])

        if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
            command.append('--test')

        options = ParseArgs(command, 'appscale-upgrade').args
        options.ips = yaml.safe_load(base64.b64decode(options.ips_layout))
        AppScaleTools.upgrade(options)
コード例 #2
0
    def test_infrastructure_flags(self):
        # Specifying infastructure as EC2 or Eucalyptus is acceptable.
        argv_1 = self.cloud_argv[:] + [
            '--infrastructure', 'ec2', '--machine', 'ami-ABCDEFG'
        ]
        actual_1 = ParseArgs(argv_1, self.function)
        self.assertEquals('ec2', actual_1.args.infrastructure)

        argv_2 = self.cloud_argv[:] + [
            '--infrastructure', 'euca', '--machine', 'emi-ABCDEFG'
        ]
        actual_2 = ParseArgs(argv_2, self.function)
        self.assertEquals('euca', actual_2.args.infrastructure)

        # Specifying something else as the infrastructure is not acceptable.
        argv_3 = self.cloud_argv[:] + [
            '--infrastructure', 'boocloud', '--machine', 'boo'
        ]
        self.assertRaises(SystemExit, ParseArgs, argv_3, self.function)

        # Specifying --machine when we're not running in a cloud is not acceptable.
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args("ips.yaml").and_return(True)

        argv_4 = self.cluster_argv[:] + ['--machine', 'boo']
        self.assertRaises(BadConfigurationException, ParseArgs, argv_4,
                          self.function)
コード例 #3
0
    def test_table_flags(self):
        # throw in a mock that says our ips.yaml file exists
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args('ips.yaml').and_return(True)

        # Specifying a table that isn't accepted should abort
        argv_1 = self.cluster_argv[:] + ['--table', 'non-existent-database']
        self.assertRaises(SystemExit, ParseArgs, argv_1, self.function)

        # Specifying a table that is accepted should return that in the result
        argv_2 = self.cluster_argv[:] + ['--table', 'cassandra']
        actual_2 = ParseArgs(argv_2, self.function)
        self.assertEquals('cassandra', actual_2.args.table)

        # Failing to specify a table should default to a predefined table
        args_3 = self.cluster_argv[:]
        actual_3 = ParseArgs(args_3, self.function)
        self.assertEquals(ParseArgs.DEFAULT_DATASTORE, actual_3.args.table)

        # Specifying a non-positive integer for n should abort
        argv_4 = self.cloud_argv[:] + ['--table', 'cassandra', '-n', '0']
        self.assertRaises(BadConfigurationException, ParseArgs, argv_4,
                          self.function)

        # Specifying a positive integer for n should be ok
        argv_5 = self.cloud_argv[:] + ['--table', 'cassandra', '-n', '2']
        actual_5 = ParseArgs(argv_5, self.function)
        self.assertEquals(2, actual_5.args.replication)
コード例 #4
0
ファイル: appscale.py プロジェクト: menivaitsi/appscale-tools
  def upgrade(self):
    """ Allows users to upgrade to the latest version of AppScale."""
    contents_as_yaml = yaml.safe_load(self.read_appscalefile())

    # Construct the appscale-upgrade command from argv and the contents of
    # the AppScalefile.
    command = []

    if 'keyname' in contents_as_yaml:
      command.append("--keyname")
      command.append(contents_as_yaml['keyname'])

    if 'verbose' in contents_as_yaml and contents_as_yaml['verbose'] == True:
      command.append("--verbose")

    if 'ips_layout' in contents_as_yaml:
      command.append('--ips_layout')
      command.append(
        base64.b64encode(yaml.dump(contents_as_yaml['ips_layout'])))

    if 'login' in contents_as_yaml:
      command.extend(['--login', contents_as_yaml['login']])

    if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
      command.append('--test')

    options = ParseArgs(command, 'appscale-upgrade').args
    options.ips = yaml.safe_load(base64.b64decode(options.ips_layout))
    AppScaleTools.upgrade(options)
コード例 #5
0
    def test_ec2_creds_in_term_instances(self):
        function = "appscale-terminate-instances"

        # specifying EC2_ACCESS_KEY but not EC2_SECRET_KEY should fail
        argv = ["--EC2_ACCESS_KEY", "access_key"]
        self.assertRaises(BadConfigurationException, ParseArgs, argv, function)

        # specifying EC2_SECRET_KEY but not EC2_ACCESS_KEY should fail
        argv = ["--EC2_SECRET_KEY", "secret_key"]
        self.assertRaises(BadConfigurationException, ParseArgs, argv, function)

        # specifying both should result in them being set in the environment
        argv = ["--EC2_ACCESS_KEY", "baz", "--EC2_SECRET_KEY", "baz"]
        ParseArgs(argv, function)
        self.assertEquals("baz", os.environ['EC2_ACCESS_KEY'])
        self.assertEquals("baz", os.environ['EC2_SECRET_KEY'])

        # specifying a EC2_URL should result in it being set in the environment
        argv = [
            "--EC2_ACCESS_KEY", "baz", "--EC2_SECRET_KEY", "baz", "--EC2_URL",
            "http://boo.baz"
        ]
        ParseArgs(argv, function)
        self.assertEquals("baz", os.environ['EC2_ACCESS_KEY'])
        self.assertEquals("baz", os.environ['EC2_SECRET_KEY'])
        self.assertEquals("http://boo.baz", os.environ['EC2_URL'])
コード例 #6
0
    def test_developer_flags(self):
        # Specifying force or test should have that carried over
        # to in the resulting hash
        argv_1 = self.cloud_argv[:] + ['--force']
        actual_1 = ParseArgs(argv_1, self.function)
        self.assertEquals(True, actual_1.args.force)

        argv_2 = self.cloud_argv[:] + ['--test']
        actual_2 = ParseArgs(argv_2, self.function)
        self.assertEquals(True, actual_2.args.test)
コード例 #7
0
    def up(self):
        """Starts an AppScale deployment with the configuration options from the
    AppScalefile in the current directory.

    Raises:
      AppScalefileException: If there is no AppScalefile in the current
      directory.
    """
        contents = self.read_appscalefile()

        # If running in a cluster environment, we first need to set up SSH keys
        contents_as_yaml = yaml.safe_load(contents)
        if "ips_layout" in contents_as_yaml:
            ips_layout = base64.b64encode(
                yaml.dump(contents_as_yaml["ips_layout"]))

        if not "infrastructure" in contents_as_yaml:
            # Only run add-keypair if there is no ssh key present,
            # or if it doesn't log into all the machines specified.
            if not self.valid_ssh_key(contents_as_yaml):
                add_keypair_command = []
                if "keyname" in contents_as_yaml:
                    add_keypair_command.append("--keyname")
                    add_keypair_command.append(str(
                        contents_as_yaml["keyname"]))

                add_keypair_command.append("--ips_layout")
                add_keypair_command.append(ips_layout)
                options = ParseArgs(add_keypair_command,
                                    "appscale-add-keypair").args
                AppScaleTools.add_keypair(options)

        # Construct a run-instances command from the file's contents
        command = []
        for key, value in contents_as_yaml.items():
            if key in ["EC2_ACCESS_KEY", "EC2_SECRET_KEY", "EC2_URL"]:
                os.environ[key] = value
                continue

            if value is True:
                command.append(str("--%s" % key))
            elif value is False:
                pass
            else:
                if key == "ips_layout":
                    command.append("--ips_layout")
                    command.append(ips_layout)
                else:
                    command.append(str("--%s" % key))
                    command.append(str("%s" % value))

        # Finally, call AppScaleTools.run_instances
        options = ParseArgs(command, "appscale-run-instances").args
        AppScaleTools.run_instances(options)
コード例 #8
0
  def test_add_master_nodes_in_virt_deployment(self):
    # don't use a 192.168.X.Y IP here, since sometimes we set our virtual
    # machines to boot with those addresses (and that can mess up our tests).
    ips_yaml = """
master: 1.2.3.4
database: 1.2.3.4
zookeeper: 1.2.3.4
appengine: 1.2.3.4
    """

    # mock out reading the yaml file, and slip in our own
    fake_yaml_file = flexmock(name='fake_yaml')
    fake_yaml_file.should_receive('read').and_return(ips_yaml)

    builtins = flexmock(sys.modules['__builtin__'])
    builtins.should_call('open')  # set the fall-through
    builtins.should_receive('open').with_args('/tmp/boo.yaml', 'r') \
      .and_return(fake_yaml_file)

    argv = [
      "--ips", "/tmp/boo.yaml",
      "--keyname", self.keyname
    ]
    options = ParseArgs(argv, self.function).args
    self.assertRaises(BadConfigurationException, AppScaleTools.add_instances,
      options)
コード例 #9
0
    def test_all_ok(self):
        # If the user wants to relocate their app to port X, and nothing else
        # runs on that port, this should succeed.

        # Assume that the AppController is running, so is our app, and that other
        # apps are not running on port 80.
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_app_info_map').with_args(
            'the secret').and_return(
                json.dumps({
                    self.appid: {
                        'nginx': 8080
                    },
                    'a-different-app': {
                        'nginx': 81
                    }
                }))
        fake_appcontroller.should_receive('relocate_app').with_args(
            self.appid, 80, 443, 'the secret').and_return("OK")
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        argv = [
            '--keyname', self.keyname, '--appname', self.appid, '--http_port',
            '80', '--https_port', '443'
        ]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.relocate_app(options)
コード例 #10
0
    def test_upload_app_with_non_alpha_appid(self):
        # add in mocks so that there is an app.yaml, but with no appid set
        flexmock(os.path)
        os.path.should_call('exists')
        app_yaml_location = AppEngineHelper.get_app_yaml_location(self.app_dir)
        os.path.should_receive('exists').with_args(app_yaml_location) \
          .and_return(True)

        # mock out reading the app.yaml file
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')  # set the fall-through

        fake_app_yaml = flexmock(name="fake_app_yaml")
        fake_app_yaml.should_receive('read').and_return(
            yaml.dump({
                'application': 'baz*',
                'runtime': 'python'
            }))
        builtins.should_receive('open').with_args(app_yaml_location, 'r') \
          .and_return(fake_app_yaml)

        argv = ["--keyname", self.keyname, "--file", self.app_dir]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(AppEngineConfigException, AppScaleTools.upload_app,
                          options)
コード例 #11
0
    def test_appscale_with_ips_layout_flag_but_no_copy_id(self):
        # assume that we have ssh-keygen but not ssh-copy-id
        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('hash ssh-keygen'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('hash ssh-copy-id'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.failed)

        # don't use a 192.168.X.Y IP here, since sometimes we set our virtual
        # machines to boot with those addresses (and that can mess up our tests).
        ips_layout = yaml.safe_load("""
master : public1
database: public1
zookeeper: public2
appengine:  public3
    """)

        argv = [
            "--ips_layout",
            base64.b64encode(yaml.dump(ips_layout)), "--keyname", self.keyname
        ]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(BadConfigurationException, AppScaleTools.add_keypair,
                          options)
コード例 #12
0
    def logs(self, location):
        """ 'logs' provides a cleaner experience for users than the
    appscale-gather-logs command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      location: The path on the local filesystem where logs should be copied to.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # construct the appscale-gather-logs command
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--location")
        command.append(location)

        # and exec it
        options = ParseArgs(command, "appscale-gather-logs").args
        AppScaleTools.gather_logs(options)
コード例 #13
0
    def test_upload_java_app_with_no_appid(self):
        # add in mocks so that there is an appengine-web.xml, but with no appid set
        flexmock(os.path)
        os.path.should_call('exists')
        os.path.should_receive('exists').with_args(
            AppEngineHelper.get_app_yaml_location(
                self.app_dir)).and_return(False)
        appengine_web_xml_location = AppEngineHelper.get_appengine_web_xml_location(
            self.app_dir)
        os.path.should_receive('exists').with_args(
            AppEngineHelper.get_appengine_web_xml_location(
                self.app_dir)).and_return(True)
        flexmock(AppEngineHelper).should_receive(
            'get_app_id_from_app_config').and_return('app_id')
        flexmock(AppEngineHelper).should_receive(
            'get_app_runtime_from_app_config').and_return('runtime')
        flexmock(LocalState).should_receive('get_secret_key').and_return()

        # mock out reading the app.yaml file
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')  # set the fall-through

        fake_appengine_web_xml = flexmock(name="fake_appengine_web_xml")
        fake_appengine_web_xml.should_receive('read').and_return(
            "<baz></baz>\n" + "<application></application>")
        builtins.should_receive('open').with_args(appengine_web_xml_location, 'r') \
          .and_return(fake_appengine_web_xml)

        argv = ["--keyname", self.keyname, "--file", self.app_dir]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(AppEngineConfigException, AppScaleTools.upload_app,
                          options)
コード例 #14
0
    def test_appscale_in_two_node_virt_deployment(self):
        # pretend that the place we're going to put logs into doesn't exist
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args('/tmp/foobaz').and_return(
            False)

        # and mock out the mkdir operation
        flexmock(os)
        os.should_receive('mkdir').with_args('/tmp/foobaz').and_return()

        # next, mock out finding the login ip address
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_nodes_json")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([{
                "public_ip": "public1",
                "private_ip": "private1",
                "jobs": ["shadow", "login"]
            }]))
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)

        # mock out writing the secret key to ~/.appscale, as well as reading it
        # later
        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # and slip in a fake appcontroller to report on the two IP addrs
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_all_public_ips').with_args(
            'the secret').and_return(json.dumps(['public1', 'public2']))
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        # fake the creation of the log directories locally
        os.should_receive('mkdir').with_args(
            '/tmp/foobaz/public1').and_return()
        os.should_receive('mkdir').with_args(
            '/tmp/foobaz/public2').and_return()

        # finally, fake the copying of the log files
        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('/var/log/appscale'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        argv = ["--keyname", self.keyname, "--location", "/tmp/foobaz"]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.gather_logs(options)
コード例 #15
0
    def test_fails_if_app_isnt_running(self):
        # If the user wants to relocate their app to port X, but their app isn't
        # even running, this should fail.

        # Assume that the AppController is running but our app isn't.
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_app_info_map').with_args(
            'the secret').and_return(json.dumps({}))
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        argv = [
            '--keyname', self.keyname, '--appname', self.appid, '--http_port',
            '80', '--https_port', '443'
        ]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(AppScaleException, AppScaleTools.relocate_app,
                          options)
コード例 #16
0
    def test_disks_flag(self):
        # specifying a EBS mount or PD mount is only valid for EC2/Euca/GCE, so
        # fail on a cluster deployment.
        argv = self.cluster_argv[:] + ["--disks", "ABCDFEG"]
        self.assertRaises(BadConfigurationException, ParseArgs, argv,
                          self.function)

        # if we get a --disk flag, fail if it's not a dict (after base64, yaml load)
        bad_disks_layout = yaml.load("""
    public1,
    """)
        base64ed_bad_disks = base64.b64encode(yaml.dump(bad_disks_layout))
        cloud_argv1 = self.cloud_argv[:] + ["--disks", base64ed_bad_disks]
        self.assertRaises(BadConfigurationException, ParseArgs, cloud_argv1,
                          self.function)

        # passing in a dict should be fine, and result in us seeing the same value
        # for --disks that we passed in.
        disks = {'public1': 'vol-ABCDEFG'}
        good_disks_layout = yaml.load("""
public1 : vol-ABCDEFG
    """)
        base64ed_good_disks = base64.b64encode(yaml.dump(good_disks_layout))
        cloud_argv2 = self.cloud_argv[:] + ["--disks", base64ed_good_disks]
        actual = ParseArgs(cloud_argv2, self.function).args
        self.assertEquals(disks, actual.disks)
コード例 #17
0
    def undeploy(self, appid):
        """ 'undeploy' is a more accessible way to tell an AppScale deployment to
    stop hosting a Google App Engine application than 'appscale-remove-app'. It
    calls that command with the configuration options found in the AppScalefile
    in the current working directory.

    Args:
      appid: The name of the application that we should remove.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()

        # Construct an remove-app command from the file's contents
        command = []
        contents_as_yaml = yaml.safe_load(contents)
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml['keyname'])

        if 'verbose' in contents_as_yaml and contents_as_yaml[
                'verbose'] == True:
            command.append("--verbose")

        if 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
            command.append('--confirm')

        command.append("--appname")
        command.append(appid)

        # Finally, exec the command. Don't worry about validating it -
        # appscale-upload-app will do that for us.
        options = ParseArgs(command, "appscale-remove-app").args
        AppScaleTools.remove_app(options)
コード例 #18
0
    def test_max_spot_instance_price_flag(self):
        # if the user wants to use spot instances, that only works on ec2, so
        # abort if they're running on euca
        euca_argv = [
            '--min', '1', '--max', '1', '--group', 'blargscale',
            '--infrastructure', 'euca', '--machine', 'emi-ABCDEFG',
            '--max_spot_price', '20'
        ]
        self.assertRaises(BadConfigurationException, ParseArgs, euca_argv,
                          self.function)

        # also abort if they're running on a virtualized cluster
        cluster_argv = self.cluster_argv[:] + ['--max_spot_price', '20']
        self.assertRaises(BadConfigurationException, ParseArgs, cluster_argv,
                          self.function)

        # fail if running on EC2 and they didn't say that we should use spot
        # instances
        ec2_bad_argv = self.cloud_argv[:] + ['--max_spot_price', '20']
        self.assertRaises(BadConfigurationException, ParseArgs, ec2_bad_argv,
                          self.function)

        # succeed if they did say it
        ec2_argv = self.cloud_argv[:] + [
            '--use_spot_instances', '--max_spot_price', '20.0'
        ]
        actual = ParseArgs(ec2_argv, self.function).args
        self.assertEquals(True, actual.use_spot_instances)
        self.assertEquals(20.0, actual.max_spot_price)
コード例 #19
0
    def get(self, property_regex):
        """ 'get' provides a cleaner experience for users than the
    appscale-get-property command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      property_regex: A regular expression indicating which AppController
        properties should be retrieved.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # construct the appscale-get-property command
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--property")
        command.append(property_regex)

        # and exec it
        options = ParseArgs(command, "appscale-get-property").args
        return AppScaleTools.get_property(options)
コード例 #20
0
    def set(self, property_name, property_value):
        """ 'set' provides a cleaner experience for users than the
    appscale-set-property command, by using the configuration options present in
    the AppScalefile found in the current working directory.

    Args:
      property_name: A str naming the AppController instance variable that
        should be overwritten.
      property_value: The new value that should be used for the named property.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()
        contents_as_yaml = yaml.safe_load(contents)

        # construct the appscale-set-property command
        command = []
        if 'keyname' in contents_as_yaml:
            command.append("--keyname")
            command.append(contents_as_yaml["keyname"])

        command.append("--property_name")
        command.append(property_name)

        command.append("--property_value")
        command.append(property_value)

        # and exec it
        options = ParseArgs(command, "appscale-set-property").args
        AppScaleTools.set_property(options)
コード例 #21
0
    def test_remove_app_but_user_cancels_it(self):
        # mock out reading from stdin, and assume the user says 'no'
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_receive('raw_input').and_return('no')

        argv = ["--appname", "blargapp"]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(AppScaleException, AppScaleTools.remove_app, options)
コード例 #22
0
    def test_scp_flag(self):
        # first, make sure --scp fails if no arg is provided
        argv_1 = self.cloud_argv[:] + ['--scp']
        self.assertRaises(SystemExit, ParseArgs, argv_1, self.function)

        argv_2 = self.cloud_argv[:] + ['--scp', '/tmp/booscale']
        actual = ParseArgs(argv_2, self.function).args
        self.assertEquals('/tmp/booscale', actual.scp)
コード例 #23
0
    def test_describe_instances_with_two_nodes(self):
        # mock out writing the secret key to ~/.appscale, as well as reading it
        # later
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')  # set the fall-through

        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        fake_secret.should_receive('write').and_return()
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # mock out the SOAP call to the AppController and assume it succeeded
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('get_all_public_ips').with_args('the secret') \
          .and_return(json.dumps(['public1', 'public2']))
        fake_appcontroller.should_receive('status').with_args('the secret') \
          .and_return('nothing interesting here') \
          .and_return('Database is at not-up-yet') \
          .and_return('Database is at 1.2.3.4')
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public2:17443') \
          .and_return(fake_appcontroller)

        # mock out reading the locations.json file, and slip in our own json
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_nodes_json")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([
                {
                    "public_ip": "public1",
                    "private_ip": "private1",
                    "jobs": ["shadow", "login"]
                },
                {
                    "public_ip": "public2",
                    "private_ip": "private2",
                    "jobs": ["appengine"]
                },
            ]))
        fake_nodes_json.should_receive('write').and_return()
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)
        # assume that there are two machines running in our deployment

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.describe_instances(options)
コード例 #24
0
    def test_reset_password_for_user_that_doesnt_exist(self):
        # put in a mock for reading the secret file
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_call('open')  # set the fall-through

        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # mock out reading the username and new password from the user
        builtins.should_receive('raw_input').and_return('*****@*****.**')
        flexmock(getpass)
        getpass.should_receive('getpass').and_return('the password')

        # mock out finding the login node's IP address from the json file
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_secret")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([{
                'public_ip': 'public1',
                'private_ip': 'private1',
                'jobs': ['login', 'db_master']
            }]))
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)

        # mock out grabbing the userappserver ip from an appcontroller
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('status').with_args('the secret') \
          .and_return('nothing interesting here') \
          .and_return('Database is at not-up-yet') \
          .and_return('Database is at public1')

        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@foo.goo', str,
            'the secret').and_return('Error: user does not exist')
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:4343') \
          .and_return(fake_userappserver)

        argv = ["--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(SystemExit, AppScaleTools.reset_password, options)
コード例 #25
0
    def test_remove_app_and_app_is_running(self):
        # mock out reading from stdin, and assume the user says 'YES'
        builtins = flexmock(sys.modules['__builtin__'])
        builtins.should_receive('raw_input').and_return('YES')

        # mock out reading the secret key
        builtins.should_call('open')  # set the fall-through

        secret_key_location = LocalState.get_secret_key_location(self.keyname)
        fake_secret = flexmock(name="fake_secret")
        fake_secret.should_receive('read').and_return('the secret')
        builtins.should_receive('open').with_args(secret_key_location, 'r') \
          .and_return(fake_secret)

        # mock out the SOAP call to the AppController and assume it succeeded
        fake_appcontroller = flexmock(name='fake_appcontroller')
        fake_appcontroller.should_receive('status').with_args('the secret') \
          .and_return('Database is at public1')
        fake_appcontroller.should_receive('stop_app').with_args(
            'blargapp', 'the secret').and_return('OK')
        fake_appcontroller.should_receive('is_app_running').with_args(
            'blargapp',
            'the secret').and_return(True).and_return(True).and_return(False)
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \
          .and_return(fake_appcontroller)

        # mock out reading the locations.json file, and slip in our own json
        flexmock(os.path)
        os.path.should_call('exists')  # set the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_locations_json_location(
                self.keyname)).and_return(True)

        fake_nodes_json = flexmock(name="fake_nodes_json")
        fake_nodes_json.should_receive('read').and_return(
            json.dumps([{
                "public_ip": "public1",
                "private_ip": "private1",
                "jobs": ["shadow", "login"]
            }]))
        fake_nodes_json.should_receive('write').and_return()
        builtins.should_receive('open').with_args(
          LocalState.get_locations_json_location(self.keyname), 'r') \
          .and_return(fake_nodes_json)

        # mock out calls to the UserAppServer and presume that the app does exist
        fake_userappserver = flexmock(name='fake_uaserver')
        fake_userappserver.should_receive('get_app_data').with_args(
            'blargapp', 'the secret').and_return('\nnum_ports:2\n')
        SOAPpy.should_receive('SOAPProxy').with_args('https://public1:4343') \
          .and_return(fake_userappserver)

        argv = ["--appname", "blargapp", "--keyname", self.keyname]
        options = ParseArgs(argv, self.function).args
        AppScaleTools.remove_app(options)
コード例 #26
0
    def test_scaling_flags(self):
        # Specifying a value for add_to_existing should fail
        argv_1 = ["--add_to_existing", "boo"]
        self.assertRaises(SystemExit, ParseArgs, argv_1,
                          "appscale-add-keypair")

        # not specifying a value should set it to true
        argv_2 = ["--add_to_existing"]
        actual = ParseArgs(argv_2, "appscale-add-keypair")
        self.assertEquals(True, actual.args.add_to_existing)
コード例 #27
0
    def test_login_flag(self):
        # if the user wants to override the URL where we log in at, make sure it
        # fails if they don't give us a URL to log in to
        argv_1 = self.cloud_argv[:] + ['--login_host']
        self.assertRaises(SystemExit, ParseArgs, argv_1, self.function)

        # and it should succeed if they do give us the URL
        argv_2 = self.cloud_argv[:] + ['--login_host', 'www.booscale.com']
        actual = ParseArgs(argv_2, self.function).args
        self.assertEquals('www.booscale.com', actual.login_host)
コード例 #28
0
    def test_terminate_when_not_running(self):
        # let's say that there's no locations.yaml file, which means appscale isn't
        # running, so we should throw up and die
        flexmock(os.path)
        os.path.should_call('exists')  # set up the fall-through
        os.path.should_receive('exists').with_args(
            LocalState.get_secret_key_location(self.keyname)).and_return(False)

        argv = ["--keyname", self.keyname, "--test"]
        options = ParseArgs(argv, self.function).args
        self.assertRaises(AppScaleException, AppScaleTools.terminate_instances,
                          options)
コード例 #29
0
    def test_ips_layout_flag(self):
        # first, make sure that the flag works
        ips_layout = yaml.load("""
    'controller' : public1,
    'servers' : public2'
    """)
        base64ed_ips = base64.b64encode(yaml.dump(ips_layout))
        argv = ['--ips_layout', base64ed_ips]
        actual = ParseArgs(argv, self.function).args
        self.assertEquals(base64ed_ips, actual.ips_layout)

        # next, make sure that it got assigned to ips
        self.assertEquals(ips_layout, actual.ips)
コード例 #30
0
    def test_instance_types(self):
        # Not specifying an instance type should default to a predetermined
        # value.
        argv_1 = self.cloud_argv[:]
        actual = ParseArgs(argv_1, self.function)
        self.assertEquals(ParseArgs.DEFAULT_EC2_INSTANCE_TYPE, \
          actual.args.instance_type)

        # Specifying m1.large as the instance type is acceptable.
        argv_2 = self.cloud_argv[:] + [
            '--infrastructure', 'ec2', '--machine', 'ami-ABCDEFG',
            '--instance_type', 'm1.large'
        ]
        actual = ParseArgs(argv_2, self.function)
        self.assertEquals("m1.large", actual.args.instance_type)

        # Specifying blarg1.humongous as the instance type is not
        # acceptable.
        argv_3 = self.cloud_argv[:] + [
            '--infrastructure', 'ec2', '--machine', 'ami-ABCDEFG',
            '--instance_type', 'blarg1.humongous'
        ]
        self.assertRaises(SystemExit, ParseArgs, argv_3, self.function)
コード例 #31
0
    def test_flags_that_cause_program_abort(self):
        # using a flag that isn't acceptable should raise
        # an exception
        argv_1 = ['--boo!']
        self.assertRaises(SystemExit, ParseArgs, argv_1, self.function)

        # the version flag should quit and print the current
        # version of the tools
        argv_2 = ['--version']
        try:
            ParseArgs(argv_2, self.function)
            raise
        except SystemExit:
            pass