def testDeployWithCloudAppScalefile(self): # calling 'appscale deploy app' with an AppScalefile in the local # directory should collect any parameters needed for the # 'appscale-upload-app' command and then exec it appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-run-instances call fake_port = 8080 fake_host = 'fake_host' flexmock(AppScaleTools) AppScaleTools.should_receive('upload_app').and_return( (fake_host, fake_port)) app = '/bar/app' (host, port) = appscale.deploy(app) self.assertEquals(fake_host, host) self.assertEquals(fake_port, port)
def testDestroyWithEC2EnvironmentVariables(self): # if the user wants us to use their EC2 credentials when running AppScale, # we should make sure they get set appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1, 'EC2_ACCESS_KEY' : 'access key', 'EC2_SECRET_KEY' : 'secret key' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-terminate-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('terminate_instances') appscale.destroy() self.assertEquals('access key', os.environ['EC2_ACCESS_KEY']) self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
def testDeployWithCloudAppScalefileAndTestFlag(self): # same as before, but with the 'test' flag in our AppScalefile appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1, 'test' : True } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-run-instances call fake_port = 8080 fake_host = 'fake_host' flexmock(AppScaleTools) AppScaleTools.should_receive('upload_app').and_return( (fake_host, fake_port)) app = '/bar/app' (host, port) = appscale.deploy(app) self.assertEquals(fake_host, host) self.assertEquals(fake_port, port)
def testUpWithCloudAppScalefile(self): # calling 'appscale up' if there is an AppScalefile present # should call appscale-run-instances with the given config # params. here, we assume that the file is intended for use # on EC2 appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # throw in some mocks for the argument parsing for credential in EC2Agent.REQUIRED_CREDENTIALS: os.environ[credential] = "baz" # finally, pretend that our ec2 image to use exists fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \ .and_return() flexmock(boto) boto.should_receive('connect_ec2').with_args('baz', 'baz').and_return(fake_ec2) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.up()
def testUpWithMalformedClusterAppScalefile(self): # if we try to use an IPs layout that isn't a dictionary, we should throw up # and die appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file, with an IPs layout that is a str contents = { 'ips_layout': "'master' 'ip1' 'appengine' 'ip1'", 'keyname': 'boobazblarg', 'group' : 'boobazblarg' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) flexmock(os.path) os.path.should_call('exists') os.path.should_receive('exists').with_args( '/boo/' + appscale.APPSCALEFILE).and_return(True) # finally, mock out the actual appscale tools calls. since we're running # via a cluster, this means we call add-keypair to set up SSH keys, then # run-instances to start appscale flexmock(AppScaleTools) AppScaleTools.should_receive('add_keypair') self.assertRaises(BadConfigurationException, appscale.up)
def testDeployWithCloudAppScalefile(self): # calling 'appscale deploy app' with an AppScalefile in the local # directory should collect any parameters needed for the # 'appscale-upload-app' command and then exec it appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-run-instances call fake_port = 8080 fake_host = 'fake_host' flexmock(AppScaleTools) AppScaleTools.should_receive('upload_app').and_return( (fake_host, fake_port)) app = '/bar/app' (host, port) = appscale.deploy(app) self.assertEquals(fake_host, host) self.assertEquals(fake_port, port)
def testUpWithMalformedClusterAppScalefile(self): # if we try to use an IPs layout that isn't a dictionary, we should throw up # and die appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file, with an IPs layout that is a str contents = { 'ips_layout': "'master' 'ip1' 'appengine' 'ip1'", 'keyname': 'boobazblarg', 'group' : 'boobazblarg' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) flexmock(os.path) os.path.should_call('exists') os.path.should_receive('exists').with_args( '/boo/' + appscale.APPSCALEFILE).and_return(True) # finally, mock out the actual appscale tools calls. since we're running # via a cluster, this means we call add-keypair to set up SSH keys, then # run-instances to start appscale flexmock(AppScaleTools) AppScaleTools.should_receive('add_keypair') self.assertRaises(BadConfigurationException, appscale.up)
def testUpWithEC2EnvironmentVariables(self): # if the user wants us to use their EC2 credentials when running AppScale, # we should make sure they get set appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure': 'ec2', 'machine': 'ami-ABCDEFG', 'keyname': 'bookey', 'group': 'boogroup', 'min': 1, 'max': 1, 'EC2_ACCESS_KEY': 'access key', 'EC2_SECRET_KEY': 'secret key' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, pretend that our ec2 image to use exists fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \ .and_return() flexmock(boto) boto.should_receive('connect_ec2').with_args('access key', 'secret key') \ .and_return(fake_ec2) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.up() self.assertEquals('access key', os.environ['EC2_ACCESS_KEY']) self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
def testUndeployWithCloudAppScalefile(self): # calling 'appscale undeploy app' with an AppScalefile in the local # directory should collect any parameters needed for the # 'appscale-remove-app' command and then exec it appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('remove_app') app = 'barapp' appscale.undeploy(app)
def testDeployWithCloudAppScalefileAndTestFlag(self): # same as before, but with the 'test' flag in our AppScalefile appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1, 'test' : True } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-run-instances call fake_port = 8080 fake_host = 'fake_host' flexmock(AppScaleTools) AppScaleTools.should_receive('upload_app').and_return( (fake_host, fake_port)) app = '/bar/app' (host, port) = appscale.deploy(app) self.assertEquals(fake_host, host) self.assertEquals(fake_port, port)
def testUpWithEC2EnvironmentVariables(self): # if the user wants us to use their EC2 credentials when running AppScale, # we should make sure they get set appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1, 'EC2_ACCESS_KEY' : 'access key', 'EC2_SECRET_KEY' : 'secret key' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, pretend that our ec2 image to use exists fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \ .and_return() flexmock(boto) boto.should_receive('connect_ec2').with_args('access key', 'secret key') \ .and_return(fake_ec2) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.up() self.assertEquals('access key', os.environ['EC2_ACCESS_KEY']) self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
def testUndeployWithCloudAppScalefile(self): # calling 'appscale undeploy app' with an AppScalefile in the local # directory should collect any parameters needed for the # 'appscale-remove-app' command and then exec it appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('remove_app') app = 'barapp' appscale.undeploy(app)
def testDestroyWithEC2EnvironmentVariables(self): # if the user wants us to use their EC2 credentials when running AppScale, # we should make sure they get set appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1, 'EC2_ACCESS_KEY' : 'access key', 'EC2_SECRET_KEY' : 'secret key' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-terminate-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('terminate_instances') appscale.destroy() self.assertEquals('access key', os.environ['EC2_ACCESS_KEY']) self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
def testGetLogsWithKeyname(self): # calling 'appscale logs dir' with a keyname should produce # a command to exec with the --keyname flag appscale = AppScale() contents = {"keyname": "boo"} yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # mock out the actual call to appscale-gather-logs flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') self.assertRaises(BadConfigurationException, appscale.logs, '/baz')
def testGetLogsWithNoKeyname(self): # calling 'appscale logs dir' with no keyname should produce # a command to exec without the --keyname flag appscale = AppScale() contents = { } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # mock out the actual call to appscale-gather-logs flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.logs('/baz')
def testGetLogsWithKeyname(self): # calling 'appscale logs dir' with a keyname should produce # a command to exec with the --keyname flag appscale = AppScale() contents = { "keyname" : "boo" } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # mock out the actual call to appscale-gather-logs flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') self.assertRaises(BadConfigurationException, appscale.logs, '/baz')
def testUpWithEC2EnvironmentVariables(self): # if the user wants us to use their EC2 credentials when running AppScale, # we should make sure they get set appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1, 'EC2_ACCESS_KEY' : 'access key', 'EC2_SECRET_KEY' : 'secret key', 'zone' : 'my-zone-1b' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) flexmock(os.path) os.path.should_call('exists') os.path.should_receive('exists').with_args( '/boo/' + appscale.APPSCALEFILE).and_return(True) # finally, pretend that our ec2 zone/image to use exist fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_all_instances') fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \ .and_return('anything') fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \ .and_return() flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').with_args('my-zone-1', aws_access_key_id='access key', aws_secret_access_key='secret key').and_return(fake_ec2) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.up() self.assertEquals('access key', os.environ['EC2_ACCESS_KEY']) self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
def testUpWithEC2EnvironmentVariables(self): # if the user wants us to use their EC2 credentials when running AppScale, # we should make sure they get set appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1, 'EC2_ACCESS_KEY' : 'access key', 'EC2_SECRET_KEY' : 'secret key', 'zone' : 'my-zone-1b' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) flexmock(os.path) os.path.should_call('exists') os.path.should_receive('exists').with_args( '/boo/' + appscale.APPSCALEFILE).and_return(True) # finally, pretend that our ec2 zone/image to use exist fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_all_instances') fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \ .and_return('anything') fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \ .and_return() flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').with_args('my-zone-1', aws_access_key_id='access key', aws_secret_access_key='secret key').and_return(fake_ec2) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.up() self.assertEquals('access key', os.environ['EC2_ACCESS_KEY']) self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
def testUpWithCloudAppScalefile(self): # calling 'appscale up' if there is an AppScalefile present # should call appscale-run-instances with the given config # params. here, we assume that the file is intended for use # on EC2 appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'min' : 1, 'max' : 1, 'zone' : 'my-zone-1b' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) flexmock(os.path) os.path.should_call('exists') os.path.should_receive('exists').with_args( '/boo/' + appscale.APPSCALEFILE).and_return(True) # throw in some mocks for the argument parsing for credential in EC2Agent.REQUIRED_CREDENTIALS: os.environ[credential] = "baz" # finally, pretend that our ec2 zone and image exists fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_all_instances') fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \ .and_return('anything') fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \ .and_return() flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').with_args('my-zone-1', aws_access_key_id='baz', aws_secret_access_key='baz').and_return(fake_ec2) # finally, mock out the actual appscale-run-instances call flexmock(AppScaleTools) AppScaleTools.should_receive('run_instances') appscale.up()
def testUpWithClusterAppScalefile(self): # calling 'appscale up' if there is an AppScalefile present # should call appscale-run-instances with the given config # params. here, we assume that the file is intended for use # on a virtualized cluster appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'ips_layout': { 'master': 'ip1', 'appengine': 'ip1', 'database': 'ip2', 'zookeeper': 'ip2' }, 'keyname': 'boobazblarg' } yaml_dumped_contents = yaml.dump(contents) base64_ips_layout = base64.b64encode(yaml.dump(contents["ips_layout"])) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # for this test, let's say that we don't have an SSH key already # set up for ip1 and ip2 # TODO(cgb): Add in tests where we have a key for ip1 but not ip2, # and the case where we have a key but it doesn't work flexmock(os.path) key_path = os.path.expanduser('~/.appscale/boobazblarg.key') os.path.should_call('exists') os.path.should_receive('exists').with_args(key_path).and_return( False).once() # finally, mock out the actual appscale tools calls. since we're running # via a cluster, this means we call add-keypair to set up SSH keys, then # run-instances to start appscale flexmock(AppScaleTools) AppScaleTools.should_receive('add_keypair') AppScaleTools.should_receive('run_instances') appscale.up()
def testUpWithMalformedClusterAppScalefile(self): # if we try to use an IPs layout that isn't a dictionary, we should throw up # and die appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file, with an IPs layout that is a str contents = { 'ips_layout': "'master' 'ip1' 'appengine' 'ip1'", 'keyname': 'boobazblarg' } yaml_dumped_contents = yaml.dump(contents) base64_ips_layout = base64.b64encode(yaml.dump(contents["ips_layout"])) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale tools calls. since we're running # via a cluster, this means we call add-keypair to set up SSH keys, then # run-instances to start appscale flexmock(AppScaleTools) AppScaleTools.should_receive('add_keypair') self.assertRaises(BadConfigurationException, appscale.up)
def testUpWithMalformedClusterAppScalefile(self): # if we try to use an IPs layout that isn't a dictionary, we should throw up # and die appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file, with an IPs layout that is a str contents = { 'ips_layout': "'master' 'ip1' 'appengine' 'ip1'", 'keyname': 'boobazblarg' } yaml_dumped_contents = yaml.dump(contents) base64_ips_layout = base64.b64encode(yaml.dump(contents["ips_layout"])) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale tools calls. since we're running # via a cluster, this means we call add-keypair to set up SSH keys, then # run-instances to start appscale flexmock(AppScaleTools) AppScaleTools.should_receive('add_keypair') self.assertRaises(BadConfigurationException, appscale.up)
def testUpWithClusterAppScalefile(self): # calling 'appscale up' if there is an AppScalefile present # should call appscale-run-instances with the given config # params. here, we assume that the file is intended for use # on a virtualized cluster appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'ips_layout': {'master': 'ip1', 'appengine': 'ip1', 'database': 'ip2', 'zookeeper': 'ip2'}, 'keyname': 'boobazblarg', 'group': 'boobazblarg' } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) flexmock(os.path) os.path.should_call('exists') os.path.should_receive('exists').with_args( '/boo/' + appscale.APPSCALEFILE).and_return(True) # for this test, let's say that we don't have an SSH key already # set up for ip1 and ip2 # TODO(cgb): Add in tests where we have a key for ip1 but not ip2, # and the case where we have a key but it doesn't work key_path = os.path.expanduser('~/.appscale/boobazblarg.key') os.path.should_receive('exists').with_args(key_path).and_return(False) # finally, mock out the actual appscale tools calls. since we're running # via a cluster, this means we call add-keypair to set up SSH keys, then # run-instances to start appscale flexmock(AppScaleTools) AppScaleTools.should_receive('add_keypair') AppScaleTools.should_receive('run_instances') appscale.up()
def testSetPropertyWithAppScalefile(self): # calling 'appscale set' with an AppScalefile in the local # directory should collect any parameters needed for the # 'appscale-get-property' command and then exec it appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-set-property call flexmock(AppScaleTools) AppScaleTools.should_receive('set_property') appscale.set('key', 'value')
def testSetPropertyWithAppScalefile(self): # calling 'appscale set' with an AppScalefile in the local # directory should collect any parameters needed for the # 'appscale-get-property' command and then exec it appscale = AppScale() # Mock out the actual file reading itself, and slip in a YAML-dumped # file contents = { 'infrastructure' : 'ec2', 'machine' : 'ami-ABCDEFG', 'keyname' : 'bookey', 'group' : 'boogroup', 'verbose' : True, 'min' : 1, 'max' : 1 } yaml_dumped_contents = yaml.dump(contents) self.addMockForAppScalefile(appscale, yaml_dumped_contents) # finally, mock out the actual appscale-set-property call flexmock(AppScaleTools) AppScaleTools.should_receive('set_property') appscale.set('key', 'value')