diff options
author | Alexis de Talhouët <adetalhouet89@gmail.com> | 2018-08-15 14:30:43 -0400 |
---|---|---|
committer | Dan Timoney <dt5972@att.com> | 2018-08-23 15:07:07 +0000 |
commit | eae6b96f6529e4a9f350809a5def4d82a904501b (patch) | |
tree | 84a4310a211e01b7c70c674f6441a6632ec7e78d /netbox-client/provider/src/main/java | |
parent | d2dd55d20da25862545a827cce6cd8f0071a4f99 (diff) |
Added netbox client to assign/unassign ip
Change-Id: Ied317c7f251936ced116b6a3ea81789c82095df6
Issue-ID: CCSDK-462
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
Diffstat (limited to 'netbox-client/provider/src/main/java')
9 files changed, 623 insertions, 0 deletions
diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java new file mode 100644 index 000000000..869a57cef --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.api; + +public class IpamException extends Exception { + + public IpamException(final String message) { + super(message); + } + + public IpamException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java new file mode 100644 index 000000000..57d727add --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.api; + +import org.onap.ccsdk.sli.adaptors.netbox.model.IPAddress; +import org.onap.ccsdk.sli.adaptors.netbox.model.Prefix; + +public interface NetboxClient { + + /** + * Assign next available IP in prefix. + * + * @param prefix The prefix from which to get next available IP. + * @return The IPAddress + * @throws IpamException If something goes wrong. + */ + IPAddress assign(Prefix prefix) throws IpamException; + + /** + * Free the IP. + * + * @param ip The IP to release. + * @throws IpamException If something goes wrong. + */ + void unassign(IPAddress ip) throws IpamException; +} + diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java new file mode 100644 index 000000000..0520ad5e5 --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.impl; + +import com.google.common.annotations.VisibleForTesting; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSerializer; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.concurrent.CompletionException; +import org.apache.http.HttpResponse; +import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException; +import org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient; +import org.onap.ccsdk.sli.adaptors.netbox.model.IPAddress; +import org.onap.ccsdk.sli.adaptors.netbox.model.Prefix; +import org.onap.ccsdk.sli.adaptors.netbox.model.Status; + +public class NetboxClientImpl implements NetboxClient { + + private static final String NEXT_AVAILABLE_IP_IN_PREFIX_PATH = "/api/ipam/prefixes/%s/available-ips/"; + private static final String IP_ADDRESS_PATH = "/api/ipam/ip-addresses/%s/"; + private static final String EMPTY_STRING = ""; + private static final String ID_MISSING_MSG = "Id must be set"; + + private final NetboxHttpClient client; + private final Gson gson; + + public NetboxClientImpl(final NetboxHttpClient client) { + this.client = client; + final JsonSerializer<Status> vlanStatusDeserializer = (val, type, context) -> val.toJson(); + gson = new GsonBuilder() + .registerTypeAdapter(Status.class, vlanStatusDeserializer) + .create(); + } + + @Override + public IPAddress assign(final Prefix prefix) throws IpamException { + checkArgument(prefix.getId() != null); + try { + return client.post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefix.getId()), EMPTY_STRING) + .thenApply(this::getIpAddress) + .toCompletableFuture() + .join(); + } catch (CompletionException e) { + // Unwrap the ComplettionException and wrap in IpamException + throw new IpamException("Fail to assign IP for Prefix(id= " + prefix.getId() + "). " + e.getMessage(), + e.getCause()); + } + } + + @Override + public void unassign(final IPAddress ipAddress) throws IpamException { + checkArgument(ipAddress.getId() != null); + try { + client.delete(String.format(IP_ADDRESS_PATH, ipAddress.getId())) + .thenAccept(this::checkResult) + .toCompletableFuture() + .join(); + } catch (CompletionException e) { + // Unwrap the ComplettionException and wrap in IpamException + throw new IpamException("Fail to unassign IP for IPAddress(id= " + ipAddress.getId() + "). " + e.getMessage(), + e.getCause()); + } + } + + @VisibleForTesting + IPAddress getIpAddress(final HttpResponse response) { + if (response.getStatusLine().getStatusCode() != 201) { + throw new IllegalStateException(NetboxHttpClient.getBodyAsString(response)); + } + try (final Reader reader = new InputStreamReader(response.getEntity().getContent())) { + return gson.fromJson(reader, IPAddress.class); + } catch (final IOException e) { + throw new IllegalStateException(e); + } + } + + private static void checkArgument(final boolean argument) throws IpamException { + if (!argument) { + throw new IpamException(ID_MISSING_MSG); + } + } + + private void checkResult(final HttpResponse response) { + if (response.getStatusLine().getStatusCode() - 200 >= 100) { + throw new IllegalStateException( + "Netbox request failed with status: " + NetboxHttpClient.getBodyAsString(response)); + } + } +} diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java new file mode 100644 index 000000000..a77b4d3e9 --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.impl; + +import static org.apache.http.HttpHeaders.ACCEPT; +import static org.apache.http.HttpHeaders.AUTHORIZATION; +import static org.apache.http.HttpHeaders.CONTENT_TYPE; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.Scanner; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; +import javax.net.ssl.SSLContext; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.concurrent.FutureCallback; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.apache.http.ssl.SSLContexts; +import org.apache.http.ssl.TrustStrategy; +import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException; +import org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties; + +public class NetboxHttpClient implements AutoCloseable { + + private static final String APPLICATION_JSON = "application/json"; + + private final CloseableHttpAsyncClient client; + private final String url; + private final String token; + + // Used by the blueprint container + public NetboxHttpClient(NetboxProperties properties) { + this(properties.getHost(), properties.getApiKey()); + } + + NetboxHttpClient(final String url, final String token) { + this.url = url; + this.token = token; + + final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true; + final SSLContext sslContext; + try { + sslContext = SSLContexts.custom() + .loadTrustMaterial(null, acceptingTrustStrategy).build(); + } catch (final NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { + throw new IllegalStateException("Can't create http client", e); + } + client = HttpAsyncClientBuilder.create() + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .setSSLContext(sslContext) + .build(); + + } + + // Has to be public for blueprint container to access it + public void init() { + client.start(); + } + + @Override + public void close() throws IOException { + client.close(); + } + + CompletionStage<HttpResponse> post(final String uri, final String requestBody) { + return sendRequest(uri, requestBody, HttpPost::new); + } + + CompletionStage<HttpResponse> delete(final String uri) { + return sendRequest(uri, HttpDelete::new); + } + + static String getBodyAsString(final HttpResponse response) { + final String body; + if (response.getEntity() != null) { + try (final Scanner s = new java.util.Scanner(response.getEntity().getContent()).useDelimiter("\\A")) { + body = s.hasNext() ? s.next() : ""; + } catch (final IOException e) { + throw new IllegalStateException(e); + } + } else { + body = ""; + } + return response.toString() + "\n" + body; + } + + private <T extends HttpUriRequest> CompletionStage<HttpResponse> sendRequest(final String uri, + final Function<String, T> supplier) { + final T request = supplier.apply(url + uri); + request.addHeader(ACCEPT, APPLICATION_JSON); + request.addHeader(CONTENT_TYPE, APPLICATION_JSON); + request.addHeader(AUTHORIZATION, "Token " + token); + return sendRequest(request); + } + + private <T extends HttpEntityEnclosingRequest & HttpUriRequest> + CompletionStage<HttpResponse> sendRequest(final String uri, final String body, + final Function<String, T> supplier) { + final T request = supplier.apply(url + uri); + request.addHeader(ACCEPT, APPLICATION_JSON); + request.addHeader(CONTENT_TYPE, APPLICATION_JSON); + request.addHeader(AUTHORIZATION, "Token " + token); + request.setEntity(new StringEntity(body, Charset.forName("UTF-8"))); + return sendRequest(request); + } + + private CompletionStage<HttpResponse> sendRequest(final HttpUriRequest request) { + final CompletableFuture<HttpResponse> future = new CompletableFuture<>(); + client.execute(request, new FutureCallback<HttpResponse>() { + @Override + public void completed(final HttpResponse httpResponse) { + future.complete(httpResponse); + } + + @Override + public void failed(final Exception e) { + future.completeExceptionally(new IpamException("Netbox request failed", e)); + } + + @Override + public void cancelled() { + future.cancel(false); + } + }); + return future; + } +}
\ No newline at end of file diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java new file mode 100644 index 000000000..6d62fff9f --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.model; + +import java.util.Objects; + +public class IPAddress extends Identifiable { + + private Status.Values status; + private String address; + + public void setStatus(Status.Values status) { + this.status = status; + } + + public void setAddress(String address) { + this.address = address; + } + + public Status.Values getStatus() { + return status; + } + + public String getAddress() { + return address; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IPAddress ipAddress = (IPAddress) o; + return Objects.equals(status, ipAddress.status) && + Objects.equals(address, ipAddress.address); + } + + @Override + public int hashCode() { + return Objects.hash(status, address); + } +} diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java new file mode 100644 index 000000000..501088d78 --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.model; + +public abstract class Identifiable { + + private Integer id; + + public Integer getId() { + return id; + } + + public void setId(final Integer id) { + this.id = id; + } +} diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java new file mode 100644 index 000000000..b20be91db --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.model; + +public class Prefix extends Identifiable { + +} diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Status.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Status.java new file mode 100644 index 000000000..c56828a80 --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Status.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.model; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.google.gson.annotations.SerializedName; + +public class Status { + + private Integer value; + private String label; + + public Integer getValue() { + return value; + } + + public void setValue(final Integer value) { + this.value = value; + } + + public String getLabel() { + return label; + } + + public void setLabel(final String label) { + this.label = label; + } + + public JsonElement toJson() { + return new JsonPrimitive(value); + } + + public enum Values { + @SerializedName("1") + ACTIVE(1, "Active"), + @SerializedName("2") + RESERVED(2, "Reserved"); + + private final int value; + private final String label; + + Values(final int value, final String label) { + this.value = value; + this.label = label; + } + + public int getValue() { + return value; + } + + public String getLabel() { + return label; + } + + public Status getStatus() { + final Status status = new Status(); + status.setValue(value); + status.setLabel(label); + return status; + } + + } +} diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java new file mode 100644 index 000000000..ee493ec18 --- /dev/null +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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 org.onap.ccsdk.sli.adaptors.netbox.property; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; + +import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException; +import org.onap.ccsdk.sli.core.utils.JREFileResolver; +import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver; +import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver; +import org.onap.ccsdk.sli.core.utils.common.BundleContextFileResolver; +import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Responsible for determining the properties file to use. + * + * <ol> + * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li> + * <li>A directory identified by the JRE argument <code>netbox.properties</code></li> + * <li>A <code>netbox.properties</code> file located in the karaf root directory</li> + * </ol> + * + * Partial copy and adaptation of org.onap.ccsdk.sli.adaptors.aai.AAIServiceProvider + */ +public class NetboxProperties { + + private static final Logger LOG = LoggerFactory.getLogger(NetboxProperties.class); + + private static final String NETBOX_PROPERTY_FILE_NAME = "netbox.properties"; + private static final String MISSING_PROPERTY_FILE = + "Missing configuration properties resource for Netbox: " + NETBOX_PROPERTY_FILE_NAME; + private static final String NETBOX_URL_PROP = "org.onap.ccsdk.sli.adaptors.netbox.url"; + private static final String NETBOX_API_KEY_PROP = "org.onap.ccsdk.sli.adaptors.netbox.apikey"; + + private Set<PropertiesFileResolver> fileResolvers = new HashSet<>(); + private Properties properties; + + public NetboxProperties() { + fileResolvers.add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable")); + fileResolvers.add(new BundleContextFileResolver("Using property file (2) from BundleContext property", + NetboxProperties.class)); + fileResolvers.add(new JREFileResolver("Using property file (3) from JRE argument", NetboxProperties.class)); + fileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this)); + + loadProps(); + } + + public String getHost() { + checkArgument(properties != null); + return properties.getProperty(NETBOX_URL_PROP); + } + + public String getApiKey() { + checkArgument(properties != null); + return properties.getProperty(NETBOX_API_KEY_PROP); + } + + private void checkArgument(final boolean argument) { + if (!argument) { + LOG.info("Propety file {} was missing, trying to reload it", NETBOX_PROPERTY_FILE_NAME); + loadProps(); + if (properties == null) { + throw new IllegalArgumentException(MISSING_PROPERTY_FILE); + } + } + } + + private void loadProps() { + // determines properties file as according to the priority described in the class header comment + final File propertiesFile = determinePropertiesFile(); + if (propertiesFile != null) { + try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) { + properties = new Properties(); + properties.load(fileInputStream); + } catch (final IOException e) { + String errorMsg = "Failed to load properties for file: " + propertiesFile.toString(); + LOG.error(errorMsg, new IpamException(errorMsg)); + } + } + } + + private File determinePropertiesFile() { + for (final PropertiesFileResolver resolver : fileResolvers) { + final Optional<File> fileOptional = resolver.resolveFile(NETBOX_PROPERTY_FILE_NAME); + if (fileOptional.isPresent()) { + final File file = fileOptional.get(); + LOG.info("{} {}", resolver.getSuccessfulResolutionMessage(), file.getPath()); + return file; + } + } + + LOG.error(MISSING_PROPERTY_FILE, new IpamException(MISSING_PROPERTY_FILE)); + return null; + } +} |