def test_upload_app(self):
        app_id = 'guestbook'
        source_path = '{}.tar.gz'.format(app_id)
        extracted_dir = '/tmp/{}'.format(app_id)
        head_node = '192.168.33.10'
        secret = 'secret-key'
        operation_id = 'operation-1'
        port = 8080
        version_url = 'http://{}:{}'.format(head_node, port)

        argv = ['--keyname', self.keyname, '--file', source_path, '--test']
        options = ParseArgs(argv, self.function).args

        version = Version('python27', 'app.yaml')
        version.project_id = app_id

        flexmock(LocalState).should_receive('extract_tgz_app_to_dir').\
          and_return('/tmp/{}'.format(app_id))
        flexmock(Version).should_receive('from_tar_gz').and_return(version)
        flexmock(AppEngineHelper).should_receive('validate_app_id')
        flexmock(LocalState).should_receive('get_host_with_role').\
          and_return(head_node)
        flexmock(LocalState).should_receive('get_secret_key').and_return(
            secret)
        flexmock(RemoteHelper).should_receive('copy_app_to_host').\
          with_args(extracted_dir, app_id, self.keyname, {}, None).\
          and_return(source_path)
        flexmock(AdminClient).should_receive('create_version').\
          and_return(operation_id)
        flexmock(AdminClient).should_receive('get_operation').\
          and_return({'done': True, 'response': {'versionUrl': version_url}})
        flexmock(shutil).should_receive('rmtree').with_args(extracted_dir)
        flexmock(AppEngineHelper).should_receive('warn_if_version_defined')

        given_host, given_port = AppScaleTools.upload_app(options)
        self.assertEquals(given_host, head_node)
        self.assertEquals(given_port, port)

        # If provided user is not app admin, deployment should fail.
        flexmock(AdminClient).should_receive('create_version').\
          and_raise(AdminError)
        self.assertRaises(AdminError, AppScaleTools.upload_app, options)

        # An application with the PHP runtime should be deployed successfully.
        version = Version('php', 'app.yaml')
        version.project_id = app_id
        flexmock(Version).should_receive('from_tar_gz').and_return(version)
        flexmock(AdminClient).should_receive('create_version').\
          and_return(operation_id)
        given_host, given_port = AppScaleTools.upload_app(options)
        self.assertEquals(given_host, head_node)
        self.assertEquals(given_port, port)
  def test_upload_app(self):
    app_id = 'guestbook'
    source_path = '{}.tar.gz'.format(app_id)
    extracted_dir = '/tmp/{}'.format(app_id)
    head_node = '192.168.33.10'
    secret = 'secret-key'
    operation_id = 'operation-1'
    port = 8080
    version_url = 'http://{}:{}'.format(head_node, port)

    argv = ['--keyname', self.keyname, '--file', source_path, '--test']
    options = ParseArgs(argv, self.function).args

    version = Version('python27', 'app.yaml')
    version.project_id = app_id

    flexmock(LocalState).should_receive('extract_tgz_app_to_dir').\
      and_return('/tmp/{}'.format(app_id))
    flexmock(Version).should_receive('from_tar_gz').and_return(version)
    flexmock(AppEngineHelper).should_receive('validate_app_id')
    flexmock(LocalState).should_receive('get_host_with_role').\
      and_return(head_node)
    flexmock(LocalState).should_receive('get_secret_key').and_return(secret)
    flexmock(RemoteHelper).should_receive('copy_app_to_host').\
      with_args(extracted_dir, app_id, self.keyname, False, {}, None).\
      and_return(source_path)
    flexmock(AdminClient).should_receive('create_version').\
      and_return(operation_id)
    flexmock(AdminClient).should_receive('get_operation').\
      and_return({'done': True, 'response': {'versionUrl': version_url}})
    flexmock(shutil).should_receive('rmtree').with_args(extracted_dir)
    flexmock(AppEngineHelper).should_receive('warn_if_version_defined')

    given_host, given_port = AppScaleTools.upload_app(options)
    self.assertEquals(given_host, head_node)
    self.assertEquals(given_port, port)

    # If provided user is not app admin, deployment should fail.
    flexmock(AdminClient).should_receive('create_version').\
      and_raise(AdminError)
    self.assertRaises(AdminError, AppScaleTools.upload_app, options)

    # An application with the PHP runtime should be deployed successfully.
    version = Version('php', 'app.yaml')
    version.project_id = app_id
    flexmock(Version).should_receive('from_tar_gz').and_return(version)
    flexmock(AdminClient).should_receive('create_version').\
      and_return(operation_id)
    given_host, given_port = AppScaleTools.upload_app(options)
    self.assertEquals(given_host, head_node)
    self.assertEquals(given_port, port)
예제 #3
0
    def deploy(self, app, project_id=None):
        """ 'deploy' is a more accessible way to tell an AppScale deployment to run a
    Google App Engine application than 'appscale-upload-app'. It calls that
    command with the configuration options found in the AppScalefile in the
    current working directory.

    Args:
      app: The path (absolute or relative) to the Google App Engine application
        that should be uploaded.
      project_id: Which project ID to use to deploy the application.
    Returns:
      A tuple containing the host and port where the application is serving
        traffic from.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
        contents = self.read_appscalefile()

        # Construct an upload-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 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
            command.append("--test")

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

        command.append("--file")
        command.append(app)

        if project_id is not None:
            command.append("--project")
            command.append(project_id)

        # Finally, exec the command. Don't worry about validating it -
        # appscale-upload-app will do that for us.
        options = ParseArgs(command, "appscale-upload-app").args
        login_host, http_port = AppScaleTools.upload_app(options)
        AppScaleTools.update_indexes(options.file, options.keyname,
                                     options.project)
        AppScaleTools.update_cron(options.file, options.keyname,
                                  options.project)
        AppScaleTools.update_queues(options.file, options.keyname,
                                    options.project)
        try:
            AppScaleTools.update_dispatch(options.file, options.keyname,
                                          options.project)
        except (AdminError, AppScaleException) as e:
            AppScaleLogger.warn(
                'Request to update dispatch failed, if your '
                'dispatch references undeployed services, ignore '
                'this exception: {}'.format(e))
        return login_host, http_port
예제 #4
0
  def deploy(self, app, project_id=None):
    """ 'deploy' is a more accessible way to tell an AppScale deployment to run a
    Google App Engine application than 'appscale-upload-app'. It calls that
    command with the configuration options found in the AppScalefile in the
    current working directory.

    Args:
      app: The path (absolute or relative) to the Google App Engine application
        that should be uploaded.
      project_id: Which project ID to use to deploy the application.
    Returns:
      A tuple containing the host and port where the application is serving
        traffic from.
    Raises:
      AppScalefileException: If there is no AppScalefile in the current working
      directory.
    """
    contents = self.read_appscalefile()

    # Construct an upload-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 'test' in contents_as_yaml and contents_as_yaml['test'] == True:
      command.append("--test")

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

    command.append("--file")
    command.append(app)

    if project_id is not None:
      command.append("--project")
      command.append(project_id)

    # Finally, exec the command. Don't worry about validating it -
    # appscale-upload-app will do that for us.
    options = ParseArgs(command, "appscale-upload-app").args
    login_host, http_port = AppScaleTools.upload_app(options)
    AppScaleTools.update_cron(options.file, options.keyname)
    AppScaleTools.update_queues(options.file, options.keyname)
    return login_host, http_port
  def test_upload_php_app_successfully(self):
    app_dir = '/tmp/appscale-app-1234'

    # add in mocks so that the gzip'ed file gets extracted to /tmp
    # as well as for removing it later
    flexmock(os)
    os.should_receive('mkdir').with_args(app_dir) \
      .and_return(True)
    flexmock(shutil)
    shutil.should_receive('rmtree').with_args(app_dir).and_return()

    local_state = flexmock(LocalState)
    local_state.should_receive('shell')\
      .with_args(re.compile('tar zxvf'),False)\
      .and_return()

    # 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(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' : 'php'
    }))
    builtins.should_receive('open').with_args(app_yaml_location, 'r') \
      .and_return(fake_app_yaml)

    # Mock out service host and port
    app_data = {'owner' : '*****@*****.**',
      'hosts' : {'192.168.1.1' : { 'http' : 8080, 'https' : 4380 }}}
    app_stats_data = {'apps': {'baz': {'http': 8080, 'language': 'python27',
      'total_reqs': 'no_change', 'appservers': 1, 'https': 4380, 'reqs_enqueued': None}}}

    # 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('done_uploading').with_args('baz',
      '/opt/appscale/apps/baz.tar.gz', 'the secret').and_return()
    fake_appcontroller.should_receive('update').with_args(['baz'],
      'the secret').and_return()
    fake_appcontroller.should_receive('is_app_running').with_args('baz',
      'the secret').and_return(False).and_return(True)
    fake_appcontroller.should_receive('does_user_exist').with_args(
      '*****@*****.**', 'the secret').and_return('true')
    fake_appcontroller.should_receive('does_user_exist').with_args(
      'a@public1', 'the secret').and_return('true')
    fake_appcontroller.should_receive('does_app_exist').with_args(
      'baz', 'the secret').and_return(json.dumps(app_data))
    fake_appcontroller.should_receive('get_app_data').with_args(
      'baz', 'the secret').and_return(json.dumps(app_data))
    fake_appcontroller.should_receive('get_all_stats').with_args(
      'the secret').and_return(json.dumps(app_stats_data))
    flexmock(SOAPpy)
    SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@a.com")
    flexmock(getpass)
    getpass.should_receive('getpass').and_return('aaaaaa')

    # mock out making the remote app directory
    local_state.should_receive('shell') \
      .with_args(re.compile('^ssh'), False, 5, stdin=re.compile('^mkdir -p')) \
      .and_return()

    # and mock out tarring and copying the app
    local_state.should_receive('shell') \
      .with_args(re.compile('tar -czf'), False) \
      .and_return()

    local_state.should_receive('shell') \
      .with_args(re.compile('/tmp/appscale-app-baz.tar.gz'), False, 5) \
      .and_return()

    # as well as removing the tar'ed app once we're done copying it
    flexmock(os)
    os.should_receive('remove').with_args('/tmp/appscale-app-baz-1234.tar.gz') \
      .and_return()

    os.should_receive('listdir').and_return(['app.yaml','index.py'])

    # and slap in a mock that says the app comes up after waiting for it
    # three times
    fake_socket = flexmock(name='fake_socket')
    fake_socket.should_receive('connect').with_args(('public1',
      8080)).and_raise(Exception).and_raise(Exception) \
      .and_return(None)
    flexmock(socket)
    socket.should_receive('socket').and_return(fake_socket)

    argv = [
      "--keyname", self.keyname,
      "--file", self.app_dir + ".tar.gz"
    ]
    options = ParseArgs(argv, self.function).args
    (host, port) = AppScaleTools.upload_app(options)
    self.assertEquals('public1', host)
    self.assertEquals(8080, port) 
예제 #6
0
    def test_upload_php_app_successfully(self):
        app_dir = '/tmp/appscale-app-1234'

        # add in mocks so that the gzip'ed file gets extracted to /tmp
        # as well as for removing it later
        flexmock(os)
        os.should_receive('mkdir').with_args(app_dir) \
          .and_return(True)
        flexmock(shutil)
        shutil.should_receive('rmtree').with_args(app_dir).and_return()

        local_state = flexmock(LocalState)
        local_state.should_receive('shell')\
          .with_args(re.compile('tar zxvf'),False)\
          .and_return()

        # 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(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': 'php'
            }))
        builtins.should_receive('open').with_args(app_yaml_location, 'r') \
          .and_return(fake_app_yaml)

        # Mock out service host and port
        app_data = {
            'owner': '*****@*****.**',
            'hosts': {
                '192.168.1.1': {
                    'http': 8080,
                    'https': 4380
                }
            }
        }
        app_stats_data = {
            'apps': {
                'baz': {
                    'http': 8080,
                    'language': 'python27',
                    'total_reqs': 'no_change',
                    'appservers': 1,
                    'https': 4380,
                    'reqs_enqueued': None
                }
            }
        }

        remote_tarball = '/opt/appscale/apps/baz.tar.gz'

        # 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('done_uploading').with_args(
            'baz', remote_tarball, 'the secret').and_return()
        fake_appcontroller.should_receive('update').with_args(
            ['baz'], 'the secret').and_return()
        fake_appcontroller.should_receive('does_user_exist').with_args(
            '*****@*****.**', 'the secret').and_return('true')
        fake_appcontroller.should_receive('does_user_exist').with_args(
            'a@public1', 'the secret').and_return('true')
        fake_appcontroller.should_receive('does_app_exist').with_args(
            'baz', 'the secret').and_return(json.dumps(app_data))
        fake_appcontroller.should_receive('get_app_data').with_args(
            'baz', 'the secret').and_return(json.dumps(app_data))
        fake_appcontroller.should_receive('get_all_stats').with_args(
            'the secret').and_return(json.dumps(app_stats_data))
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@a.com")
        flexmock(getpass)
        getpass.should_receive('getpass').and_return('aaaaaa')

        # mock out making the remote app directory
        local_state.should_receive('shell') \
          .with_args(re.compile('^ssh'), False, 5, stdin=re.compile('^mkdir -p')) \
          .and_return()

        # and mock out tarring and copying the app
        local_state.should_receive('shell') \
          .with_args(re.compile('tar -czf'), False) \
          .and_return()

        local_state.should_receive('shell') \
          .with_args(re.compile('/tmp/appscale-app-baz.tar.gz'), False, 5) \
          .and_return()

        # as well as removing the tar'ed app once we're done copying it
        flexmock(os)
        os.should_receive('remove').with_args('/tmp/appscale-app-baz-1234.tar.gz') \
          .and_return()

        os.should_receive('listdir').and_return(['app.yaml', 'index.py'])

        # and slap in a mock that says the app comes up after waiting for it
        # three times
        fake_socket = flexmock(name='fake_socket')
        fake_socket.should_receive('connect').with_args(('public1',
          8080)).and_raise(Exception).and_raise(Exception) \
          .and_return(None)
        flexmock(socket)
        socket.should_receive('socket').and_return(fake_socket)

        flexmock(RemoteHelper).should_receive('copy_app_to_host').\
          and_return(remote_tarball)

        argv = ["--keyname", self.keyname, "--file", self.app_dir + ".tar.gz"]
        options = ParseArgs(argv, self.function).args
        (host, port) = AppScaleTools.upload_app(options)
        self.assertEquals('public1', host)
        self.assertEquals(8080, port)
예제 #7
0
    def test_upload_app_when_app_exists_on_virt_cluster(self):
        # we do let you upload an app if it's already running

        # add in mocks so that there is an app.yaml with an 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': 'python27'
            }))
        builtins.should_receive('open').with_args(app_yaml_location, 'r') \
          .and_return(fake_app_yaml)

        # Mock out service host and port
        app_data = {
            'owner': '*****@*****.**',
            'hosts': {
                '192.168.1.1': {
                    'http': 8080,
                    'https': 4380
                }
            }
        }
        app_stats_data = {
            'apps': {
                'baz': {
                    'http': 8080,
                    'language': 'python27',
                    'total_reqs': 'no_change',
                    'appservers': 1,
                    'https': 4380,
                    'reqs_enqueued': None
                }
            }
        }

        # 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('done_uploading').with_args(
            'baz', '/opt/appscale/apps/baz.tar.gz',
            'the secret').and_return('OK')
        fake_appcontroller.should_receive('update').with_args(
            ['baz'], 'the secret').and_return('OK')
        fake_appcontroller.should_receive('does_user_exist').with_args(
            '*****@*****.**', 'the secret').and_return('true')
        fake_appcontroller.should_receive('does_user_exist').with_args(
            'a@public1', 'the secret').and_return('true')
        fake_appcontroller.should_receive('does_app_exist').with_args(
            'baz', 'the secret').and_return(json.dumps(app_data))
        fake_appcontroller.should_receive('get_app_data').with_args(
            'baz', 'the secret').and_return(json.dumps(app_data))
        fake_appcontroller.should_receive('get_all_stats').with_args(
            'the secret').and_return(json.dumps(app_stats_data))
        flexmock(SOAPpy)
        SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@a.com")
        flexmock(getpass)
        getpass.should_receive('getpass').and_return('aaaaaa')

        # mock out making the remote app directory
        flexmock(subprocess)
        subprocess.should_receive('Popen').with_args(re.compile('mkdir -p'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        # and mock out tarring and copying the app
        subprocess.should_receive('Popen').with_args(re.compile('tar -czhf'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        subprocess.should_receive('Popen').with_args(re.compile(
          '/tmp/appscale-app-baz.tar.gz'),
          shell=True, stdout=self.fake_temp_file, stderr=subprocess.STDOUT) \
          .and_return(self.success)

        # as well as removing the tar'ed app once we're done copying it
        flexmock(os)
        os.should_receive('remove').with_args('/tmp/appscale-app-baz-1234.tar.gz') \
          .and_return()

        # and slap in a mock that says the app comes up after waiting for it
        # three times
        fake_socket = flexmock(name='fake_socket')
        fake_socket.should_receive('connect').with_args(('public1',
          8080)).and_raise(Exception).and_raise(Exception) \
          .and_return(None)
        flexmock(socket)
        socket.should_receive('socket').and_return(fake_socket)

        argv = ["--keyname", self.keyname, "--file", self.app_dir]
        options = ParseArgs(argv, self.function).args
        (host, port) = AppScaleTools.upload_app(options)
        self.assertEquals('public1', host)
        self.assertEquals(8080, port)