Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -56,6 +56,8 @@ public class JCloudsSlaveTemplate implements Describable<JCloudsSlaveTemplate>,
public static final String OPENSTACK_CLOUD_NAME_KEY = "jenkins-cloud-name";
// To be attached on all servers provisioned from configured templates
public static final String OPENSTACK_TEMPLATE_NAME_KEY = "jenkins-template-name";
// To be attached on all servers provisioned from configured templates
public static final String OPENSTACK_NETWORK_ORDER = "jenkins-network-order";

private static final Logger LOGGER = Logger.getLogger(JCloudsSlaveTemplate.class.getName());

Expand Down Expand Up @@ -305,6 +307,7 @@ public boolean canProvision(final Label label) {
List<String> networks = selectNetworkIds(openstack, nid);
LOGGER.fine("Setting networks to " + networks);
builder.networks(networks);
builder.addMetadataItem(OPENSTACK_NETWORK_ORDER, String.join(",", selectNetworkOrder(openstack, nid)));
}

String securityGroups = opts.getSecurityGroups();
Expand Down Expand Up @@ -478,6 +481,30 @@ private String getServerName() {

return ret.stream().map(Network::getId).collect(Collectors.toList());
}
@VisibleForTesting
/*package*/ static @Nonnull List<String> selectNetworkOrder(@Nonnull Openstack openstack, @Nonnull String spec) {
if (spec == null || spec.isEmpty()) throw new IllegalArgumentException();

List<List<String>> declared = TokenGroup.from(spec, ',', '|');

List<String> allDeclaredNetworks = declared.stream().flatMap(Collection::stream).collect(Collectors.toList());

if (declared.isEmpty() || declared.contains(Collections.emptyList()) || allDeclaredNetworks.contains("")) {
throw new IllegalArgumentException("Networks declaration contains blank '" + declared + "'");
}

Map<String, Network> osNetworksById = openstack.getNetworks(allDeclaredNetworks);
Map<String, Network> osNetworksByName = osNetworksById.values().stream().collect(Collectors.toMap(Network::getName, n -> n));

final Function<String, String> RESOLVE_IDS_TO_NAME = n -> {
if (osNetworksByName.containsKey(n)) return n;
Network network = osNetworksById.getOrDefault(n, null);
if (network != null) return network.getName();
throw new IllegalArgumentException("No network name '" + n + "' found for " + spec);
};

return allDeclaredNetworks.stream().map(RESOLVE_IDS_TO_NAME).distinct().collect(Collectors.toList());
}

/*package for testing*/ @CheckForNull String getUserData() {
return UserDataConfig.resolve(getEffectiveSlaveOptions().getUserDataId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import hudson.Util;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;
import jenkins.plugins.openstack.compute.JCloudsSlaveTemplate;
import jenkins.plugins.openstack.compute.auth.OpenstackCredential;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
Expand Down Expand Up @@ -72,6 +73,7 @@
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -735,7 +737,18 @@ public static Address getAccessIpAddressObject(@Nonnull Server server) {
Address fixedIPv4 = null;
Address fixedIPv6 = null;
Address floatingIPv6 = null;
Collection<List<? extends Address>> addressMap = server.getAddresses().getAddresses().values();
String order= server.getMetadata().get(JCloudsSlaveTemplate.OPENSTACK_NETWORK_ORDER);
Collection<List<? extends Address>> addressMap;
if (order != null && !order.isEmpty()) {
final List<String> listOrder = Arrays.asList(order.split(","));

TreeMap<String, List<? extends Address>> sortedAddress = new TreeMap<>(Comparator.comparingInt(listOrder::indexOf));
sortedAddress.putAll(server.getAddresses().getAddresses());
addressMap = sortedAddress.values();
} else {
addressMap = server.getAddresses().getAddresses().values();
}

for (List<? extends Address> addresses: addressMap) {
for (Address addr: addresses) {
String type = addr.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import static jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.parseSecurityGroups;
import static jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.selectNetworkIds;
import static jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.selectNetworkOrder;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -517,4 +518,66 @@ public void selectNetworksWhenUtilizationApiDisabled() {
// If we have not utilization info, result will likely be suboptimal
assertEquals(Arrays.asList("uuid-empty", "uuid-full", "uuid-loaded", "uuid-empty"), selectNetworkIds(os, "empty|full,full,loaded|empty,empty"));
}

@Test
public void selectNetworkOrderTest() {
JCloudsSlaveTemplate t = j.dummySlaveTemplate("foo");
JCloudsCloud c = j.dummyCloud(t);
j.configureSlaveProvisioning(c, Collections.emptyList());

Network fullNet = mockNetwork("full");
Network emptyNet = mockNetwork("empty");
Network loadedNet = mockNetwork("loaded");
Map<String, Network> networkMap = new HashMap<>();
Stream.of(fullNet, emptyNet, loadedNet).forEach(n -> {
networkMap.put(n.getId(), n );
networkMap.put(n.getName(), n);
});

Openstack os = c.getOpenstack();
doAnswer(i -> {
Map<String, Network> ret = new HashMap<>();

for (String netSpec : ((List<String>) i.getArguments()[0])) {
Network n = networkMap.get(netSpec);
ret.put(n.getId(), n);
}
return ret;
}).when(os).getNetworks(any());
doAnswer(i -> {
Map<String, Network> requestedNets = (Map<String, Network>) i.getArguments()[0];

Map<Network, Integer> ret = new HashMap<>();
if (requestedNets.containsKey(fullNet.getId())) {
ret.put(fullNet, 0);
}
if (requestedNets.containsKey(emptyNet.getId())) {
ret.put(emptyNet, 10);
}
if (requestedNets.containsKey(loadedNet.getId())) {
ret.put(loadedNet, 5);
}
return ret;
}).when(os).getNetworksCapacity(any());

assertEquals(singletonList("empty"), selectNetworkOrder(os, "empty"));
assertEquals(singletonList("loaded"), selectNetworkOrder(os, "loaded"));
assertEquals(singletonList("full"), selectNetworkOrder(os, "full"));
assertEquals(singletonList("empty"), selectNetworkOrder(os, "uuid-empty"));
assertEquals(singletonList("loaded"), selectNetworkOrder(os, "uuid-loaded"));
assertEquals(singletonList("full"), selectNetworkOrder(os, "uuid-full"));
assertEquals(Arrays.asList("empty", "full", "loaded"), selectNetworkOrder(os, "empty,uuid-full,loaded"));
assertEquals(Arrays.asList("empty"), selectNetworkOrder(os, "empty,uuid-empty,empty"));

assertEquals(Arrays.asList("empty","full"), selectNetworkOrder(os, "empty|full"));
assertEquals(Arrays.asList("empty","loaded"), selectNetworkOrder(os, "empty|loaded"));
assertEquals(Arrays.asList("loaded","full"), selectNetworkOrder(os, "loaded|full"));
assertEquals(Arrays.asList("empty", "loaded", "full"), selectNetworkOrder(os, "empty|loaded|full"));
assertEquals(Arrays.asList("full", "loaded", "empty"), selectNetworkOrder(os, "full|loaded|empty"));

assertEquals(Arrays.asList("empty", "full", "loaded"), selectNetworkOrder(os, "empty|full,full,loaded|empty,empty"));
assertEquals(Arrays.asList("empty", "loaded"), selectNetworkOrder(os, "empty|empty,loaded|loaded,empty|empty"));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;

import jenkins.plugins.openstack.compute.JCloudsSlaveTemplate;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
Expand All @@ -19,6 +20,8 @@
import org.openstack4j.api.networking.ext.NetworkIPAvailabilityService;
import org.openstack4j.api.storage.BlockVolumeSnapshotService;
import org.openstack4j.model.common.ActionResponse;
import org.openstack4j.model.compute.Address;
import org.openstack4j.model.compute.Addresses;
import org.openstack4j.model.compute.Fault;
import org.openstack4j.model.compute.Server;
import org.openstack4j.model.compute.builder.ServerCreateBuilder;
Expand Down Expand Up @@ -485,6 +488,60 @@ public void deleteFloatingIpsWhenDeletingMachine() {
verify(fips, never()).delete("keep-me");
}


@Test
public void getAccessIpAddress() {
getAccesIpAdressTest(getAddressesOneAddress(), Collections.singletonList("default_network"),"DEFAULT_IP");

getAccesIpAdressTest(getAddressesTwoAddress(), Arrays.asList("first_network", "second_network"),"FIRST_IP");
getAccesIpAdressTest(getAddressesTwoAddress(), Arrays.asList("second_network", "first_network"),"SECOND_IP");
}

private Addresses getAddressesOneAddress() {
Address address = getAddress("DEFAULT_IP", "fixed", 4);
Addresses addresses = mock(Addresses.class);
Map<String, List<? extends Address>> mapAdresses = new HashMap<String, List<? extends Address>>() {{
put("default_network", Collections.singletonList(address));
}};
when(addresses.getAddresses()).thenReturn(mapAdresses);
when(addresses.getAddresses(any()))
.thenAnswer((Answer<List<? extends Address>>) invocationOnMock -> mapAdresses.get(invocationOnMock.getArguments()[0]));
return addresses;
}
private Addresses getAddressesTwoAddress() {
Address firstIp = getAddress("FIRST_IP", "fixed", 4);
Address secondIp = getAddress("SECOND_IP", "fixed", 4);
Addresses addresses = mock(Addresses.class);
Map<String, List<? extends Address>> mapAdresses = new HashMap<String, List<? extends Address>>() {{
put("first_network", Collections.singletonList(firstIp));
put("second_network", Collections.singletonList(secondIp));
}};
when(addresses.getAddresses()).thenReturn(mapAdresses);
when(addresses.getAddresses(any()))
.thenAnswer((Answer<List<? extends Address>>) invocationOnMock -> mapAdresses.get(invocationOnMock.getArguments()[0]));
return addresses;
}

private Address getAddress(String ip, String type, int version) {
Address address = mock(Address.class);
when(address.getAddr()).thenReturn(ip);
when(address.getVersion()).thenReturn(version);
when(address.getType()).thenReturn(type);
return address;
}

private void getAccesIpAdressTest(Addresses addresses,List<String> networkOrder, String result) {
Server server = mock(Server.class);
when(server.getAddresses()).thenReturn(addresses);
Map<String,String> metadata = new HashMap<>();
metadata.put(JCloudsSlaveTemplate.OPENSTACK_NETWORK_ORDER, String.join(",", networkOrder));
when(server.getMetadata()).thenReturn(metadata);

String ipAdresse = Openstack.getAccessIpAddress(server);

assertThat(ipAdresse, equalTo(result));
}

/**
* Track the state of the openstack to be manifested by different client calls;
*/
Expand Down
Loading