mirror of https://github.com/apache/jclouds.git
JCLOUDS-906: Add ServiceAccounts to GoogleComputeEngineTemplateOptions
This commit is contained in:
parent
aa33619c92
commit
55348c0ddb
|
@ -138,15 +138,14 @@ public final class GoogleComputeEngineServiceAdapter
|
||||||
tags.add(naming.name(ports));
|
tags.add(naming.name(ports));
|
||||||
}
|
}
|
||||||
|
|
||||||
NewInstance newInstance = NewInstance.create(
|
NewInstance newInstance = new NewInstance.Builder( name,
|
||||||
name, // name
|
|
||||||
template.getHardware().getUri(), // machineType
|
template.getHardware().getUri(), // machineType
|
||||||
network, // network
|
network,
|
||||||
disks, // disks
|
disks)
|
||||||
group, // description
|
.description(group)
|
||||||
Tags.create(null, ImmutableList.copyOf(tags)) // tags
|
.tags(Tags.create(null, ImmutableList.copyOf(tags)))
|
||||||
);
|
.serviceAccounts(options.serviceAccounts())
|
||||||
|
.build();
|
||||||
|
|
||||||
// Add metadata from template and for ssh key and image id
|
// Add metadata from template and for ssh key and image id
|
||||||
newInstance.metadata().putAll(options.getUserMetadata());
|
newInstance.metadata().putAll(options.getUserMetadata());
|
||||||
|
@ -177,7 +176,7 @@ public final class GoogleComputeEngineServiceAdapter
|
||||||
null, // networkInterfaces
|
null, // networkInterfaces
|
||||||
null, // disks
|
null, // disks
|
||||||
newInstance.metadata(), // metadata
|
newInstance.metadata(), // metadata
|
||||||
null, // serviceAccounts
|
newInstance.serviceAccounts(), // serviceAccounts
|
||||||
Scheduling.create(OnHostMaintenance.MIGRATE, true) // scheduling
|
Scheduling.create(OnHostMaintenance.MIGRATE, true) // scheduling
|
||||||
));
|
));
|
||||||
checkState(instanceVisible.apply(instance), "instance %s is not api visible!", instance.get());
|
checkState(instanceVisible.apply(instance), "instance %s is not api visible!", instance.get());
|
||||||
|
|
|
@ -16,16 +16,19 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.googlecomputeengine.compute.options;
|
package org.jclouds.googlecomputeengine.compute.options;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
|
||||||
|
|
||||||
/** Instance options specific to Google Compute Engine. */
|
/** Instance options specific to Google Compute Engine. */
|
||||||
public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
|
public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
|
||||||
|
|
||||||
private boolean autoCreateKeyPair = true;
|
private boolean autoCreateKeyPair = true;
|
||||||
|
private List<ServiceAccount> serviceAccounts;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GoogleComputeEngineTemplateOptions clone() {
|
public GoogleComputeEngineTemplateOptions clone() {
|
||||||
|
@ -40,6 +43,7 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
|
||||||
if (to instanceof GoogleComputeEngineTemplateOptions) {
|
if (to instanceof GoogleComputeEngineTemplateOptions) {
|
||||||
GoogleComputeEngineTemplateOptions eTo = GoogleComputeEngineTemplateOptions.class.cast(to);
|
GoogleComputeEngineTemplateOptions eTo = GoogleComputeEngineTemplateOptions.class.cast(to);
|
||||||
eTo.autoCreateKeyPair(autoCreateKeyPair());
|
eTo.autoCreateKeyPair(autoCreateKeyPair());
|
||||||
|
eTo.serviceAccounts(serviceAccounts());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,12 +56,30 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether an SSH key pair should be created automatically.
|
* Gets whether an SSH key pair should be created automatically.
|
||||||
*/
|
*/
|
||||||
public boolean autoCreateKeyPair() {
|
public boolean autoCreateKeyPair() {
|
||||||
return autoCreateKeyPair;
|
return autoCreateKeyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a list of service accounts, with their specified scopes, to authorize on created instance.
|
||||||
|
* For example, to give a node the 'compute' scope you would add a service account with the email 'default'
|
||||||
|
* and the scope 'https://www.googleapis.com/auth/compute'
|
||||||
|
* These scopes will be given to all nodes created with these template options.
|
||||||
|
*/
|
||||||
|
public GoogleComputeEngineTemplateOptions serviceAccounts(List<ServiceAccount> serviceAccounts){
|
||||||
|
this.serviceAccounts = serviceAccounts;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of service accounts, with their specified scopes, that will be authorize on created instances.
|
||||||
|
*/
|
||||||
|
public List<ServiceAccount> serviceAccounts(){
|
||||||
|
return serviceAccounts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jclouds.googlecomputeengine.domain;
|
package org.jclouds.googlecomputeengine.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -80,7 +81,8 @@ public abstract class NewInstance {
|
||||||
return create(name, machineType, network, Arrays.asList(AttachDisk.newBootDisk(sourceImage)), null, null);
|
return create(name, machineType, network, Arrays.asList(AttachDisk.newBootDisk(sourceImage)), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NewInstance create(String name, URI machineType, URI network, List<AttachDisk> disks, @Nullable String description, @Nullable Tags tags) {
|
public static NewInstance create(String name, URI machineType, URI network, List<AttachDisk> disks,
|
||||||
|
@Nullable String description, @Nullable Tags tags) {
|
||||||
checkArgument(disks.get(0).boot(), "disk 0 must be a boot disk! %s", disks);
|
checkArgument(disks.get(0).boot(), "disk 0 must be a boot disk! %s", disks);
|
||||||
boolean foundBoot = false;
|
boolean foundBoot = false;
|
||||||
for (AttachDisk disk : disks) {
|
for (AttachDisk disk : disks) {
|
||||||
|
@ -93,13 +95,86 @@ public abstract class NewInstance {
|
||||||
description, tags != null ? tags : Tags.create(), Metadata.create(), null, null);
|
description, tags != null ? tags : Tags.create(), Metadata.create(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SerializedNames({ "name", "machineType", "canIpForward", "networkInterfaces", "disks", "description", "tags", "metadata",
|
@SerializedNames({ "name", "machineType", "canIpForward", "networkInterfaces", "disks", "description",
|
||||||
"serviceAccounts", "scheduling" })
|
"tags", "metadata", "serviceAccounts", "scheduling" })
|
||||||
static NewInstance create(String name, URI machineType, Boolean canIpForward, List<NetworkInterface> networkInterfaces,
|
static NewInstance create(String name, URI machineType, Boolean canIpForward,
|
||||||
List<AttachDisk> disks, String description, Tags tags, Metadata metadata, List<ServiceAccount> serviceAccounts, Scheduling scheduling) {
|
List<NetworkInterface> networkInterfaces, List<AttachDisk> disks, String description,
|
||||||
return new AutoValue_NewInstance(name, machineType, canIpForward, networkInterfaces, disks, description, tags, metadata, serviceAccounts, scheduling);
|
Tags tags, Metadata metadata, List<ServiceAccount> serviceAccounts, Scheduling scheduling) {
|
||||||
|
return new AutoValue_NewInstance(name, machineType, canIpForward, networkInterfaces, disks, description,
|
||||||
|
tags, metadata, serviceAccounts, scheduling);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewInstance() {
|
NewInstance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String name;
|
||||||
|
private URI machineType;
|
||||||
|
private Boolean canIpForward;
|
||||||
|
private List<NetworkInterface> networkInterfaces;
|
||||||
|
private List<AttachDisk> disks;
|
||||||
|
private String description;
|
||||||
|
private Tags tags;
|
||||||
|
private Metadata metadata;
|
||||||
|
private List<ServiceAccount> serviceAccounts;
|
||||||
|
private Scheduling scheduling;
|
||||||
|
|
||||||
|
public Builder(String name, URI machineType, URI network, List<AttachDisk> disks) {
|
||||||
|
checkNotNull(name, "NewInstance name cannot be null");
|
||||||
|
this.name = name;
|
||||||
|
this.machineType = machineType;
|
||||||
|
this.networkInterfaces = ImmutableList.of(NetworkInterface.create(network));
|
||||||
|
this.disks = disks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder(String name, URI machineType, URI network, URI sourceImage) {
|
||||||
|
checkNotNull(name, "NewInstance name cannot be null");
|
||||||
|
this.name = name;
|
||||||
|
this.machineType = machineType;
|
||||||
|
this.networkInterfaces = ImmutableList.of(NetworkInterface.create(network));
|
||||||
|
this.disks = Arrays.asList(AttachDisk.newBootDisk(sourceImage));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder canIpForward(Boolean canIpForward){
|
||||||
|
this.canIpForward = canIpForward;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder description(String description){
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder tags(Tags tags){
|
||||||
|
this.tags = tags;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder metadata(Metadata metadata){
|
||||||
|
this.metadata = metadata;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of service accounts, with their specified scopes, authorized for this instance.
|
||||||
|
* Service accounts generate access tokens that can be accessed through the metadata server
|
||||||
|
* and used to authenticate applications on the instance.
|
||||||
|
* Note: to add scopes to the default service account on the VM you can use 'default' as
|
||||||
|
* a keyword for email.
|
||||||
|
*/
|
||||||
|
public Builder serviceAccounts(List<ServiceAccount> serviceAccounts){
|
||||||
|
this.serviceAccounts = serviceAccounts;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder scheduling(Scheduling scheduling){
|
||||||
|
this.scheduling = scheduling;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NewInstance build() {
|
||||||
|
return create(name, machineType, canIpForward, networkInterfaces, disks, description, tags != null ? tags : Tags.create(),
|
||||||
|
metadata != null ? metadata : Metadata.create(), serviceAccounts, scheduling);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,10 +40,6 @@ public abstract class Tags implements Cloneable {
|
||||||
return Tags.create(null, null);
|
return Tags.create(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Tags create(String fingerprint) {
|
|
||||||
return Tags.create(fingerprint, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SerializedNames({ "fingerprint", "items" })
|
@SerializedNames({ "fingerprint", "items" })
|
||||||
public static Tags create(String fingerprint, ImmutableList<String> items) { // Dictates the type when created from json!
|
public static Tags create(String fingerprint, ImmutableList<String> items) { // Dictates the type when created from json!
|
||||||
ImmutableList<String> empty = ImmutableList.of();
|
ImmutableList<String> empty = ImmutableList.of();
|
||||||
|
|
|
@ -34,7 +34,9 @@ import org.jclouds.googlecomputeengine.domain.Instance;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
|
import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
|
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling;
|
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling;
|
||||||
|
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling.OnHostMaintenance;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.SerialPortOutput;
|
import org.jclouds.googlecomputeengine.domain.Instance.SerialPortOutput;
|
||||||
|
import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
|
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
|
||||||
import org.jclouds.googlecomputeengine.domain.Metadata;
|
import org.jclouds.googlecomputeengine.domain.Metadata;
|
||||||
import org.jclouds.googlecomputeengine.domain.NewInstance;
|
import org.jclouds.googlecomputeengine.domain.NewInstance;
|
||||||
|
@ -99,11 +101,16 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
||||||
);
|
);
|
||||||
instance.metadata().put("mykey", "myvalue");
|
instance.metadata().put("mykey", "myvalue");
|
||||||
|
|
||||||
instance2 = NewInstance.create(
|
instance2 = new NewInstance.Builder(INSTANCE_NAME2, // name
|
||||||
INSTANCE_NAME2, // name
|
|
||||||
getDefaultMachineTypeUrl(), // machineType
|
getDefaultMachineTypeUrl(), // machineType
|
||||||
getNetworkUrl(INSTANCE_NETWORK_NAME), // network
|
getNetworkUrl(INSTANCE_NETWORK_NAME), // network
|
||||||
imageUri); // sourceImage
|
imageUri) // sourceImage
|
||||||
|
.canIpForward(true)
|
||||||
|
.description("description")
|
||||||
|
.tags(Tags.create(null, ImmutableList.of("tag1")))
|
||||||
|
.serviceAccounts(ImmutableList.of(ServiceAccount.create("default", ImmutableList.of("https://www.googleapis.com/auth/compute"))))
|
||||||
|
.scheduling(Scheduling.create(OnHostMaintenance.MIGRATE, true))
|
||||||
|
.build();
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
@ -116,6 +123,18 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
||||||
return api.disksInZone(DEFAULT_ZONE_NAME);
|
return api.disksInZone(DEFAULT_ZONE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(groups = "live", dependsOnMethods = "testInsertInstance")
|
||||||
|
public void testGetInstance2() {
|
||||||
|
Instance instance = api().get(INSTANCE_NAME2);
|
||||||
|
assertNotNull(instance);
|
||||||
|
assertInstanceEquals(instance, this.instance2);
|
||||||
|
assertTrue(instance.canIpForward());
|
||||||
|
assertEquals(instance.description(), "description");
|
||||||
|
assertEquals(instance.serviceAccounts().get(0).scopes(), ImmutableList.of("https://www.googleapis.com/auth/compute"));
|
||||||
|
assertTrue(instance.scheduling().automaticRestart());
|
||||||
|
assertEquals(instance.scheduling().onHostMaintenance(), OnHostMaintenance.MIGRATE);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(groups = "live")
|
@Test(groups = "live")
|
||||||
public void testInsertInstance() {
|
public void testInsertInstance() {
|
||||||
// need to insert the network first
|
// need to insert the network first
|
||||||
|
@ -294,7 +313,7 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
||||||
assertOperationDoneSuccessfully(api().reset(INSTANCE_NAME));
|
assertOperationDoneSuccessfully(api().reset(INSTANCE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = "live", dependsOnMethods = "testInsertInstance")
|
@Test(groups = "live", dependsOnMethods = "testGetInstance2")
|
||||||
public void testStopInstance() {
|
public void testStopInstance() {
|
||||||
Instance originalInstance = api().get(INSTANCE_NAME2);
|
Instance originalInstance = api().get(INSTANCE_NAME2);
|
||||||
assertEquals(originalInstance.status(), Instance.Status.RUNNING);
|
assertEquals(originalInstance.status(), Instance.Status.RUNNING);
|
||||||
|
|
|
@ -27,6 +27,8 @@ import org.jclouds.googlecomputeengine.domain.AttachDisk;
|
||||||
import org.jclouds.googlecomputeengine.domain.AttachDisk.DiskInterface;
|
import org.jclouds.googlecomputeengine.domain.AttachDisk.DiskInterface;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
|
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
|
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
|
||||||
|
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling;
|
||||||
|
import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
|
||||||
import org.jclouds.googlecomputeengine.domain.Metadata;
|
import org.jclouds.googlecomputeengine.domain.Metadata;
|
||||||
import org.jclouds.googlecomputeengine.domain.NewInstance;
|
import org.jclouds.googlecomputeengine.domain.NewInstance;
|
||||||
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling.OnHostMaintenance;
|
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling.OnHostMaintenance;
|
||||||
|
@ -250,6 +252,41 @@ public class InstanceApiMockTest extends BaseGoogleComputeEngineApiMockTest {
|
||||||
assertSent(server, "POST", "/projects/party/zones/us-central1-a/instances/test-1/stop");
|
assertSent(server, "POST", "/projects/party/zones/us-central1-a/instances/test-1/stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void builderTest() throws Exception {
|
||||||
|
server.enqueue(jsonResponse("/zone_operation.json"));
|
||||||
|
|
||||||
|
NewInstance newInstance = new NewInstance.Builder("test-1", // name
|
||||||
|
URI.create(url("/projects/party/zones/us-central1-a/machineTypes/n1-standard-1")), // machineType
|
||||||
|
URI.create(url("/projects/party/global/networks/default")), // network
|
||||||
|
URI.create(url("/projects/party/global/images/centos-6-2-v20120326"))).build(); // sourceImage)
|
||||||
|
|
||||||
|
assertEquals(instanceApi().create(newInstance), new ParseZoneOperationTest().expected(url("/projects")));
|
||||||
|
assertSent(server, "POST", "/projects/party/zones/us-central1-a/instances",
|
||||||
|
stringFromResource("/instance_insert_simple.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert_builder_allOptions() throws Exception {
|
||||||
|
server.enqueue(jsonResponse("/zone_operation.json"));
|
||||||
|
|
||||||
|
NewInstance newInstance = new NewInstance.Builder(
|
||||||
|
"test-1", // name
|
||||||
|
URI.create(url("/projects/party/zones/us-central1-a/machineTypes/n1-standard-1")), // machineType
|
||||||
|
URI.create(url("/projects/party/global/networks/default")), // network
|
||||||
|
Arrays.asList(AttachDisk.existingBootDisk(URI.create(url("/projects/party/zones/us-central1-a/disks/test")))))
|
||||||
|
.canIpForward(true)
|
||||||
|
.description("desc")
|
||||||
|
.tags(null)
|
||||||
|
.metadata(Metadata.create().put("aKey", "aValue"))
|
||||||
|
.serviceAccounts(ImmutableList.of(ServiceAccount.create("default",
|
||||||
|
ImmutableList.of("https://www.googleapis.com/auth/compute"))))
|
||||||
|
.scheduling(Scheduling.create(OnHostMaintenance.MIGRATE, true))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals(instanceApi().create(newInstance), new ParseZoneOperationTest().expected(url("/projects")));
|
||||||
|
assertSent(server, "POST", "/projects/party/zones/us-central1-a/instances",
|
||||||
|
stringFromResource("/instance_insert_full.json"));
|
||||||
|
}
|
||||||
|
|
||||||
InstanceApi instanceApi(){
|
InstanceApi instanceApi(){
|
||||||
return api().instancesInZone("us-central1-a");
|
return api().instancesInZone("us-central1-a");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"name": "test-1",
|
||||||
|
"machineType": "https://www.googleapis.com/compute/v1/projects/party/zones/us-central1-a/machineTypes/n1-standard-1",
|
||||||
|
"canIpForward": true,
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"network": "https://www.googleapis.com/compute/v1/projects/party/global/networks/default",
|
||||||
|
"accessConfigs": [
|
||||||
|
{
|
||||||
|
"type": "ONE_TO_ONE_NAT"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"disks": [
|
||||||
|
{
|
||||||
|
"type": "PERSISTENT",
|
||||||
|
"source": "https://www.googleapis.com/compute/v1/projects/party/zones/us-central1-a/disks/test",
|
||||||
|
"boot": true,
|
||||||
|
"autoDelete": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "desc",
|
||||||
|
"tags": {
|
||||||
|
"items": []
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"key": "aKey",
|
||||||
|
"value": "aValue"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"serviceAccounts": [
|
||||||
|
{
|
||||||
|
"email": "default",
|
||||||
|
"scopes": [
|
||||||
|
"https://www.googleapis.com/auth/compute"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scheduling": {
|
||||||
|
"onHostMaintenance": "MIGRATE",
|
||||||
|
"automaticRestart": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue