Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add spotVM and maxRunDuration feature to VM provisioning #492

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

import static com.google.cloud.graphite.platforms.plugin.client.util.ClientUtil.nameFromSelfLink;
import static com.google.jenkins.plugins.computeengine.ComputeEngineCloud.checkPermissions;
import static com.google.jenkins.plugins.computeengine.ui.helpers.ProvisioningTypeValue.PREEMPTIBLE;
import static com.google.jenkins.plugins.computeengine.ui.helpers.ProvisioningTypeValue.SPOT;

import com.google.api.client.json.GenericJson;
import com.google.api.services.compute.model.AcceleratorConfig;
import com.google.api.services.compute.model.AttachedDisk;
import com.google.api.services.compute.model.AttachedDiskInitializeParams;
Expand All @@ -42,6 +45,8 @@
import com.google.jenkins.plugins.computeengine.ssh.GoogleKeyCredential;
import com.google.jenkins.plugins.computeengine.ssh.GoogleKeyPair;
import com.google.jenkins.plugins.computeengine.ssh.GooglePrivateKey;
import com.google.jenkins.plugins.computeengine.ui.helpers.ProvisioningType;
import com.google.jenkins.plugins.computeengine.ui.helpers.ProvisioningTypeValue;
import edu.umd.cs.findbugs.annotations.Nullable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
Expand All @@ -63,6 +68,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
Expand Down Expand Up @@ -120,7 +126,19 @@
private String machineType;
private String numExecutorsStr;
private String startupScript;

/**
* Use the {@link #provisioningType} field instead.
*/
@Deprecated
private boolean preemptible;

/**
* Succeeds {@link #preemptible}.
*/
private ProvisioningType provisioningType;
gbhat618 marked this conversation as resolved.
Show resolved Hide resolved

private long maxRunDurationSeconds;

Check warning on line 141 in src/main/java/com/google/jenkins/plugins/computeengine/InstanceConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 139-141 are not covered by tests
private String minCpuPlatform;
private String labels;
private String runAsUser;
Expand Down Expand Up @@ -494,295 +512,339 @@

private Scheduling scheduling() {
Scheduling scheduling = new Scheduling();
scheduling.setPreemptible(preemptible);

if (provisioningType != null) {

Check warning on line 516 in src/main/java/com/google/jenkins/plugins/computeengine/InstanceConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 516 is only partially covered, one branch is missing
if (provisioningType.getValue() == PREEMPTIBLE) {
scheduling.setPreemptible(true);
} else if (provisioningType.getValue() == SPOT) {
scheduling.setProvisioningModel("SPOT");
// only the instance is deleted, the disk deletion is based on bootDiskAutoDelete config value
scheduling.setInstanceTerminationAction("DELETE");

Check warning on line 522 in src/main/java/com/google/jenkins/plugins/computeengine/InstanceConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 517-522 are not covered by tests
}
} else if (preemptible) { // keeping the check for `preemptible` for backward compatibility

Check warning on line 524 in src/main/java/com/google/jenkins/plugins/computeengine/InstanceConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 524 is only partially covered, one branch is missing
scheduling.setPreemptible(true);
} // else: standard provisioning

if (maxRunDurationSeconds > 0 && provisioningType.getValue() != PREEMPTIBLE) {

Check warning on line 528 in src/main/java/com/google/jenkins/plugins/computeengine/InstanceConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 528 is only partially covered, 3 branches are missing
GenericJson j = new GenericJson();
j.set("seconds", maxRunDurationSeconds);
scheduling.set("maxRunDuration", j);
// only the instance is deleted, the disk deletion is based on bootDiskAutoDelete config value
scheduling.setInstanceTerminationAction("DELETE");
}
return scheduling;
}

private List<AttachedDisk> disks() {
AttachedDisk boot = new AttachedDisk();
boot.setBoot(true);
boot.setAutoDelete(bootDiskAutoDelete);
boot.setInitializeParams(new AttachedDiskInitializeParams()
.setDiskSizeGb(bootDiskSizeGb)
.setDiskType(bootDiskType)
.setSourceImage(bootDiskSourceImageName));

List<AttachedDisk> disks = new ArrayList<>();
disks.add(boot);
return disks;
}

private List<AcceleratorConfig> accelerators() {
if (acceleratorConfiguration != null
&& notNullOrEmpty(acceleratorConfiguration.getGpuCount())
&& notNullOrEmpty(acceleratorConfiguration.getGpuType())) {
List<AcceleratorConfig> accelerators = new ArrayList<>();
accelerators.add(new AcceleratorConfig()
.setAcceleratorType(acceleratorConfiguration.getGpuType())
.setAcceleratorCount(acceleratorConfiguration.gpuCount()));
return accelerators;
}
return null;
}

private List<NetworkInterface> networkInterfaces() {
List<NetworkInterface> networkInterfaces = new ArrayList<>();

NetworkInterface networkInterface = networkInterfaceIpStackMode.getNetworkInterface();

// Don't include subnetwork name if using default
if (!networkConfiguration.getSubnetwork().equals("default")) {
networkInterface.setSubnetwork(stripSelfLinkPrefix(networkConfiguration.getSubnetwork()));
}

networkInterfaces.add(networkInterface);
return networkInterfaces;
}

private List<ServiceAccount> serviceAccounts() {
if (notNullOrEmpty(serviceAccountEmail)) {
List<ServiceAccount> serviceAccounts = new ArrayList<>();
serviceAccounts.add(new ServiceAccount()
.setEmail(serviceAccountEmail)
.setScopes(Arrays.asList(new String[] {"https://www.googleapis.com/auth/cloud-platform"})));
return serviceAccounts;
} else {
return null;
}
}

@Extension
public static final class DescriptorImpl extends Descriptor<InstanceConfiguration> {
private static ComputeClient computeClient;
private static List<ProvisioningType.ProvisioningTypeDescriptor> provisioningTypeDescriptors;

public static void setComputeClient(ComputeClient client) {
computeClient = client;
}

public static String defaultRetentionTimeMinutes() {
return DEFAULT_RETENTION_TIME_MINUTES.toString();
}

public static String defaultLaunchTimeoutSeconds() {
return DEFAULT_LAUNCH_TIMEOUT_SECONDS.toString();
}

public static String defaultBootDiskSizeGb() {
return DEFAULT_BOOT_DISK_SIZE_GB.toString();
}

public static String defaultBootDiskAutoDelete() {
return "true";
}

public static String defaultRunAsUser() {
return DEFAULT_RUN_AS_USER;
}

public static WindowsConfiguration defaultWindowsConfiguration() {
return WindowsConfiguration.builder()
.passwordCredentialsId("")
.privateKeyCredentialsId("")
.build();
}

public static SshConfiguration defaultSshConfiguration() {
return SshConfiguration.builder().customPrivateKeyCredentialsId("").build();
}

public static NetworkConfiguration defaultNetworkConfiguration() {
return new AutofilledNetworkConfiguration();
}

private static ComputeClient computeClient(Jenkins context, String credentialsId) throws IOException {
if (computeClient != null) {
return computeClient;
}
ClientFactory clientFactory = ClientUtil.getClientFactory(context, credentialsId);
return clientFactory.computeClient();
}

@Override
public String getHelpFile(String fieldName) {
String p = super.getHelpFile(fieldName);
if (p == null) {
Descriptor d = Jenkins.get().getDescriptor(ComputeEngineInstance.class);
if (d != null) p = d.getHelpFile(fieldName);
}
return p;
}

public List<NetworkConfiguration.NetworkConfigurationDescriptor> getNetworkConfigurationDescriptors() {
List<NetworkConfiguration.NetworkConfigurationDescriptor> d =
Jenkins.get().getDescriptorList(NetworkConfiguration.class);
// No deprecated regions
Iterator it = d.iterator();
while (it.hasNext()) {
NetworkConfiguration.NetworkConfigurationDescriptor o =
(NetworkConfiguration.NetworkConfigurationDescriptor) it.next();
if (o.clazz.getName().equals("NetworkConfiguration")) {
it.remove();
}
}
return d;
}

public FormValidation doCheckNetworkTags(@QueryParameter String value) {
if (value == null || value.isEmpty()) {
return FormValidation.ok();
}

String re = "[a-z]([-a-z0-9]*[a-z0-9])?";
for (String tag : value.split(" ")) {
if (!tag.matches(re)) {
return FormValidation.error("Tags must be space-delimited and each tag must match regex" + re);
}
}

return FormValidation.ok();
}

public FormValidation doCheckNamePrefix(@QueryParameter String value) {
if (value == null || value.isEmpty()) {
return FormValidation.error("A prefix is required");
}

String re = "[a-z]([-a-z0-9]*[a-z0-9])?";
if (!value.matches(re)) {
return FormValidation.error("Prefix must match regex " + re);
}

Integer maxLen = 50;
if (value.length() > maxLen) {
return FormValidation.error("Maximum length is " + maxLen);
}
return FormValidation.ok();
}

public FormValidation doCheckDescription(@QueryParameter String value) {
if (value == null || value.isEmpty()) {
return FormValidation.error("A description is required");
}
return FormValidation.ok();
}

public ListBoxModel doFillRegionItems(
@AncestorInPath Jenkins context,
@QueryParameter("projectId") @RelativePath("..") final String projectId,
@QueryParameter("credentialsId") @RelativePath("..") final String credentialsId) {
checkPermissions(Jenkins.get(), Jenkins.ADMINISTER);
ListBoxModel items = new ListBoxModel();
items.add("");
try {
ComputeClient compute = computeClient(context, credentialsId);
List<Region> regions = compute.listRegions(projectId);

for (Region r : regions) {
items.add(r.getName(), r.getSelfLink());
}
return items;
} catch (IOException ioe) {
items.clear();
items.add("Error retrieving regions");
return items;
}
}

public ListBoxModel doFillTemplateItems(
@AncestorInPath Jenkins context,
@QueryParameter("projectId") @RelativePath("..") final String projectId,
@QueryParameter("credentialsId") @RelativePath("..") final String credentialsId) {
checkPermissions(Jenkins.get(), Jenkins.ADMINISTER);
ListBoxModel items = new ListBoxModel();
items.add("");
try {
ComputeClient compute = computeClient(context, credentialsId);
List<InstanceTemplate> instanceTemplates = compute.listTemplates(projectId);

for (InstanceTemplate instanceTemplate : instanceTemplates) {
items.add(instanceTemplate.getName(), instanceTemplate.getSelfLink());
}
return items;
} catch (IOException ioe) {
items.clear();
items.add("Error retrieving instanceTemplates");
return items;
}
}

public FormValidation doCheckRegion(@QueryParameter String value) {
if (StringUtils.isEmpty(value)) {
return FormValidation.error("Please select a region...");
}
return FormValidation.ok();
}

public ListBoxModel doFillZoneItems(
@AncestorInPath Jenkins context,
@QueryParameter("projectId") @RelativePath("..") final String projectId,
@QueryParameter("region") final String region,
@QueryParameter("credentialsId") @RelativePath("..") final String credentialsId) {
checkPermissions(Jenkins.get(), Jenkins.ADMINISTER);
ListBoxModel items = new ListBoxModel();
items.add("");
try {
ComputeClient compute = computeClient(context, credentialsId);
List<Zone> zones = compute.listZones(projectId, region);

for (Zone z : zones) {
items.add(z.getName(), z.getSelfLink());
}
return items;
} catch (IOException ioe) {
items.clear();
items.add("Error retrieving zones");
return items;
} catch (IllegalArgumentException iae) {
// TODO log
return null;
}
}

public FormValidation doCheckZone(@QueryParameter String value) {
if (StringUtils.isEmpty(value)) {
return FormValidation.error("Please select a zone...");
}
return FormValidation.ok();
}

public ListBoxModel doFillMachineTypeItems(
@AncestorInPath Jenkins context,
@QueryParameter("projectId") @RelativePath("..") final String projectId,
@QueryParameter("zone") final String zone,
@QueryParameter("credentialsId") @RelativePath("..") final String credentialsId) {
checkPermissions(Jenkins.get(), Jenkins.ADMINISTER);
ListBoxModel items = new ListBoxModel();
items.add("");
try {
ComputeClient compute = computeClient(context, credentialsId);
List<MachineType> machineTypes = compute.listMachineTypes(projectId, zone);

for (MachineType m : machineTypes) {
items.add(m.getName(), m.getSelfLink());
}
return items;
} catch (IOException ioe) {
items.clear();
items.add("Error retrieving machine types");
return items;
} catch (IllegalArgumentException iae) {
// TODO log
return null;
}
}

public FormValidation doCheckMachineType(@QueryParameter String value) {
if (StringUtils.isEmpty(value)) {
return FormValidation.error("Please select a machine type...");
}
return FormValidation.ok();
}

public FormValidation doCheckMaxRunDurationSeconds(
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
@QueryParameter String value, @QueryParameter(value = "provisioningType") String provisioningTypeIdx) {
gbhat618 marked this conversation as resolved.
Show resolved Hide resolved
try {
long maxRunDurationSeconds = Long.parseLong(value);
if (maxRunDurationSeconds < 0) {
return FormValidation.error("Max run duration must be greater than or equal to 0");
}

if (StringUtils.isNotBlank(provisioningTypeIdx)) {
ProvisioningTypeValue provisioningTypeValue = provisioningTypeDescriptors
.get(Integer.parseInt(provisioningTypeIdx))
.getProvisioningTypeValue();
if (provisioningTypeValue == PREEMPTIBLE) {
return FormValidation.warning(
"Max run duration is not supported for preemptible VMs and will be ignored.");
}
}

return FormValidation.ok();
} catch (NumberFormatException e) {
return FormValidation.error("Max run duration must be non-negative number");
}
}

public ListBoxModel doFillMinCpuPlatformItems(
@AncestorInPath Jenkins context,
@QueryParameter("projectId") @RelativePath("..") final String projectId,
Expand Down Expand Up @@ -943,6 +1005,15 @@
return FormValidation.ok();
}

@SuppressWarnings("unused")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@SuppressWarnings("unused")
@SuppressWarnings("unused") // jelly

public List<ProvisioningType.ProvisioningTypeDescriptor> getProvisioningTypes() {
if (provisioningTypeDescriptors == null) {
provisioningTypeDescriptors =
Objects.requireNonNull(Jenkins.getInstanceOrNull()).getDescriptorList(ProvisioningType.class);
}
return provisioningTypeDescriptors;

Check warning on line 1014 in src/main/java/com/google/jenkins/plugins/computeengine/InstanceConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 529-1014 are not covered by tests
}

public List<NetworkInterfaceIpStackMode.Descriptor> getNetworkInterfaceIpStackModeDescriptors() {
return ExtensionList.lookup(NetworkInterfaceIpStackMode.Descriptor.class);
}
Expand All @@ -959,6 +1030,8 @@
instanceConfiguration.setNumExecutorsStr(this.numExecutorsStr);
instanceConfiguration.setStartupScript(this.startupScript);
instanceConfiguration.setPreemptible(this.preemptible);
instanceConfiguration.setProvisioningType(this.provisioningType);
instanceConfiguration.setMaxRunDurationSeconds(this.maxRunDurationSeconds);
instanceConfiguration.setMinCpuPlatform(this.minCpuPlatform);
instanceConfiguration.setLabelString(this.labels);
instanceConfiguration.setRunAsUser(this.runAsUser);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 CloudBees, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.jenkins.plugins.computeengine.ui.helpers;

import hudson.Extension;
import org.kohsuke.stapler.DataBoundConstructor;

@SuppressWarnings("unused")
public class PreemptibleVm extends ProvisioningType {

@DataBoundConstructor
public PreemptibleVm() {
super(ProvisioningTypeValue.PREEMPTIBLE);
}

Check warning on line 28 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/PreemptibleVm.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 27-28 are not covered by tests

@Extension
public static class DescriptorImpl extends ProvisioningTypeDescriptor {
@Override
public String getDisplayName() {
return "Preemptible VM";
}

@Override
public ProvisioningTypeValue getProvisioningTypeValue() {
return ProvisioningTypeValue.PREEMPTIBLE;

Check warning on line 39 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/PreemptibleVm.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 39 is not covered by tests
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2024 CloudBees, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.jenkins.plugins.computeengine.ui.helpers;

import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import org.kohsuke.stapler.DataBoundSetter;

/**
* ProvisioningType represents the type of VM to be provisioned.
*/
public abstract class ProvisioningType extends AbstractDescribableImpl<ProvisioningType> {
public ProvisioningTypeValue value;

public ProvisioningType(ProvisioningTypeValue value) {
this.value = value;
}

public ProvisioningTypeValue getValue() {
return value;
}

@DataBoundSetter
public void setProvisioningTypeValue(ProvisioningTypeValue value) {
this.value = value;
}

Check warning on line 40 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/ProvisioningType.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 29-40 are not covered by tests

public abstract static class ProvisioningTypeDescriptor extends Descriptor<ProvisioningType> {
public abstract ProvisioningTypeValue getProvisioningTypeValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2024 CloudBees, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.jenkins.plugins.computeengine.ui.helpers;

public enum ProvisioningTypeValue {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an enum here kind of defeats the purpose of having extensibility. I think it is not needed anyway as it is only used for casc compatibility which is not usually kept as per Bobby. But just in case you face this use case in the future, I would recommend either adding a specific check method returning boolean on the base implementation, or a marker interface that PreemptibleVm could implement

STANDARD,
SPOT,
PREEMPTIBLE;

Check warning on line 22 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/ProvisioningTypeValue.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 19-22 are not covered by tests
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 CloudBees, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.jenkins.plugins.computeengine.ui.helpers;

import hudson.Extension;
import org.kohsuke.stapler.DataBoundConstructor;

@SuppressWarnings("unused")
public class SpotVm extends ProvisioningType {

@DataBoundConstructor
public SpotVm() {
super(ProvisioningTypeValue.SPOT);
}

Check warning on line 28 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/SpotVm.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 27-28 are not covered by tests

@Extension
public static class DescriptorImpl extends ProvisioningTypeDescriptor {
@Override
public String getDisplayName() {
return "Spot VM";
}

@Override
public ProvisioningTypeValue getProvisioningTypeValue() {
return ProvisioningTypeValue.SPOT;

Check warning on line 39 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/SpotVm.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 39 is not covered by tests
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 CloudBees, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.jenkins.plugins.computeengine.ui.helpers;

import hudson.Extension;
import org.kohsuke.stapler.DataBoundConstructor;

@SuppressWarnings("unused")
public class Standard extends ProvisioningType {

@DataBoundConstructor
public Standard() {
super(ProvisioningTypeValue.STANDARD);
}

Check warning on line 28 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/Standard.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 27-28 are not covered by tests

@Extension
public static class DescriptorImpl extends ProvisioningTypeDescriptor {
@Override
public String getDisplayName() {
return "Standard";
}

@Override
public ProvisioningTypeValue getProvisioningTypeValue() {
return ProvisioningTypeValue.STANDARD;

Check warning on line 39 in src/main/java/com/google/jenkins/plugins/computeengine/ui/helpers/Standard.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 39 is not covered by tests
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,12 @@
<f:entry field="machineType" title="${%Machine Type}">
<f:select/>
</f:entry>
<f:entry field="preemptible" title="${%Preemptible?}">
<f:checkbox/>
<f:descriptorRadioList descriptors="${descriptor.provisioningTypes}"
gbhat618 marked this conversation as resolved.
Show resolved Hide resolved
title="Provisioning Type"
instance="${instance}"
varName="provisioningType"/>
<f:entry field="maxRunDurationSeconds" title="${%Max Run Duration Seconds}">
<f:textbox/>
</f:entry>
<f:entry field="minCpuPlatform" title="${%Minimum Cpu Platform}">
<f:select/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!--
Copyright 2024 CloudBees, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div>
The maximum duration (in seconds) after which the VM will be automatically deleted by GCP.
See <a href="https://cloud.google.com/compute/docs/instances/limit-vm-runtime">Limit the run time of a VM</a> for more details.
</div>

This file was deleted.

Loading
Loading