aboutsummaryrefslogtreecommitdiffstats
path: root/participant/participant-impl/participant-impl-kserve/src/main/java
diff options
context:
space:
mode:
authorLiam Fallon <liam.fallon@est.tech>2023-02-20 16:12:59 +0000
committerGerrit Code Review <gerrit@onap.org>2023-02-20 16:12:59 +0000
commit705bf225334bff05156ecf44ac72abffe01c859a (patch)
tree351e2b4669af88c8202e53c9180258a328ba9a3e /participant/participant-impl/participant-impl-kserve/src/main/java
parentc8c13eef9a8b2c24baf7e5c3b7b2504e90a01e12 (diff)
parentdf28b0a551c8397d437d29453abcd2e26bcec9b2 (diff)
Merge "Add kserve participant"
Diffstat (limited to 'participant/participant-impl/participant-impl-kserve/src/main/java')
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/Application.java61
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java46
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/ParticipantConfig.java43
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/SecurityConfig.java48
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/exception/KserveException.java39
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java167
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidator.java102
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/KserveClient.java112
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/ConfigurationEntity.java37
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/KserveInferenceEntity.java49
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/CustomResourceDefinitionParameters.java43
-rwxr-xr-xparticipant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/KserveParticipantParameters.java44
12 files changed, 791 insertions, 0 deletions
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/Application.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/Application.java
new file mode 100755
index 000000000..c5299e235
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/Application.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve;
+
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.util.Config;
+import java.io.IOException;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * Starter.
+ */
+// @formatter:off
+@SpringBootApplication
+@ComponentScan({"org.onap.policy.clamp.acm.participant.kserve", "org.onap.policy.clamp.acm.participant.intermediary"})
+@ConfigurationPropertiesScan("org.onap.policy.clamp.acm.participant.kserve.parameters")
+//@formatter:on
+public class Application {
+
+ /**
+ * Main class.
+ *
+ * @param args args
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * Default Api Client bean creation.
+ *
+ * @return ApiClient
+ * @throws IOException exception
+ */
+ @Bean
+ public ApiClient defaultApiClient() throws IOException {
+ return Config.fromCluster();
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java
new file mode 100755
index 000000000..92dc5d3d6
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.config;
+
+import io.micrometer.core.aop.TimedAspect;
+import io.micrometer.core.instrument.MeterRegistry;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MicrometerConfig {
+
+ /**
+ * Load up the metrics registry.
+ */
+ @Bean
+ public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor,
+ MeterRegistry registry) {
+ return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, "");
+ }
+
+ @Bean
+ public TimedAspect timedAspect(MeterRegistry registry) {
+ return new TimedAspect(registry);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/ParticipantConfig.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/ParticipantConfig.java
new file mode 100755
index 000000000..1a671343a
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/ParticipantConfig.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.config;
+
+import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.clamp.acm.participant.kserve.handler.AutomationCompositionElementHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ParticipantConfig {
+
+ /**
+ * Register AutomationCompositionElementListener.
+ *
+ * @param intermediaryApi the ParticipantIntermediaryApi
+ * @param acElementHandler the AutomationComposition Element Handler
+ */
+ @Autowired
+ public void registerAutomationCompositionElementListener(ParticipantIntermediaryApi intermediaryApi,
+ AutomationCompositionElementHandler acElementHandler) {
+ intermediaryApi.registerAutomationCompositionElementListener(acElementHandler);
+ acElementHandler.setIntermediaryApi(intermediaryApi);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/SecurityConfig.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/SecurityConfig.java
new file mode 100755
index 000000000..f9dbc08fc
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/SecurityConfig.java
@@ -0,0 +1,48 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 2023 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+public class SecurityConfig {
+
+ /**
+ * Return the configuration of how access to this module's REST end points is secured.
+ *
+ * @param http the HTTP security settings
+ * @return the HTTP security settings
+ */
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http
+ .httpBasic()
+ .and()
+ .authorizeHttpRequests()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .csrf()
+ .disable();
+ return http.build();
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/exception/KserveException.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/exception/KserveException.java
new file mode 100755
index 000000000..045c80c21
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/exception/KserveException.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.exception;
+
+import javax.ws.rs.core.Response;
+import org.onap.policy.models.base.PfModelException;
+
+public class KserveException extends PfModelException {
+
+ public KserveException(String message) {
+ super(Response.Status.BAD_GATEWAY, message);
+ }
+
+ public KserveException(int statusCode, String message, Exception e) {
+ super(Response.Status.fromStatusCode(statusCode), message, e);
+ }
+
+ public KserveException(String message, Exception originalException) {
+ super(Response.Status.BAD_GATEWAY, message, originalException);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java
new file mode 100755
index 000000000..cae70565f
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java
@@ -0,0 +1,167 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.handler;
+
+import io.kubernetes.client.openapi.ApiException;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import javax.validation.Validation;
+import javax.validation.ValidationException;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.apache.http.HttpStatus;
+import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
+import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.clamp.acm.participant.kserve.exception.KserveException;
+import org.onap.policy.clamp.acm.participant.kserve.k8s.InferenceServiceValidator;
+import org.onap.policy.clamp.acm.participant.kserve.k8s.KserveClient;
+import org.onap.policy.clamp.acm.participant.kserve.models.ConfigurationEntity;
+import org.onap.policy.clamp.acm.participant.kserve.models.KserveInferenceEntity;
+import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
+import org.onap.policy.clamp.models.acm.concepts.DeployState;
+import org.onap.policy.clamp.models.acm.concepts.LockState;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfModelException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class handles implementation of automationCompositionElement updates.
+ */
+@Component
+@RequiredArgsConstructor
+public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
+
+ private static final Coder CODER = new StandardCoder();
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+
+ @Setter
+ private ParticipantIntermediaryApi intermediaryApi;
+
+ private final KserveClient kserveClient;
+
+ @Getter
+ private static final Map<UUID, ConfigurationEntity> configRequestMap = new HashMap<>();
+
+
+ private static class ThreadConfig {
+
+ private int uninitializedToPassiveTimeout = 60;
+ private int statusCheckInterval = 30;
+ }
+
+ @Override
+ public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) {
+ var configurationEntity = configRequestMap.get(automationCompositionElementId);
+ if (configurationEntity != null) {
+ try {
+ for (KserveInferenceEntity kserveInferenceEntity : configurationEntity.getKserveInferenceEntities()) {
+ kserveClient.undeployInferenceService(kserveInferenceEntity.getNamespace(),
+ kserveInferenceEntity.getName());
+ }
+ configRequestMap.remove(automationCompositionElementId);
+ intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
+ automationCompositionElementId, DeployState.UNDEPLOYED, LockState.NONE);
+ } catch (IOException | ApiException exception) {
+ LOGGER.warn("Deletion of Inference service failed", exception);
+ }
+ }
+ }
+
+ /**
+ * Callback method to handle an update on an automation composition element.
+ *
+ * @param automationCompositionId the ID of the automation composition
+ * @param element the information on the automation composition element
+ * @param properties properties Map
+ */
+ @Override
+ public void deploy(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties)
+ throws PfModelException {
+ try {
+ var configurationEntity = CODER.convert(properties, ConfigurationEntity.class);
+ var violations = Validation.buildDefaultValidatorFactory().getValidator().validate(configurationEntity);
+ if (violations.isEmpty()) {
+ boolean isAllInferenceSvcDeployed = true;
+ var config = CODER.convert(properties, ThreadConfig.class);
+ for (KserveInferenceEntity kserveInferenceEntity : configurationEntity.getKserveInferenceEntities()) {
+ kserveClient.deployInferenceService(kserveInferenceEntity.getNamespace(),
+ kserveInferenceEntity.getPayload());
+
+ if (!checkInferenceServiceStatus(kserveInferenceEntity.getName(),
+ kserveInferenceEntity.getNamespace(), config.uninitializedToPassiveTimeout,
+ config.statusCheckInterval)) {
+ isAllInferenceSvcDeployed = false;
+ break;
+ }
+ }
+ if (isAllInferenceSvcDeployed) {
+ configRequestMap.put(element.getId(), configurationEntity);
+ intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
+ DeployState.DEPLOYED, LockState.LOCKED);
+ } else {
+ LOGGER.error("Inference Service deployment failed");
+ }
+ } else {
+ LOGGER.error("Violations found in the config request parameters: {}", violations);
+ throw new ValidationException("Constraint violations in the config request");
+ }
+ } catch (ValidationException | ExecutionException | InterruptedException | CoderException e) {
+ throw new KserveException(HttpStatus.SC_BAD_REQUEST, "Invalid Configuration", e);
+ } catch (IOException | ApiException e) {
+ throw new KserveException(HttpStatus.SC_BAD_REQUEST, "Failed to configure the inference service", e);
+ }
+ }
+
+ /**
+ * Check the status of Inference Service.
+ *
+ * @param inferenceServiceName name of the inference service
+ * @param namespace kubernetes namespace
+ * @param timeout Inference service time check
+ * @param statusCheckInterval Status check time interval
+ * @return status of the inference service
+ * @throws ExecutionException Exception on execution
+ * @throws InterruptedException Exception on inference service status check
+ */
+ public boolean checkInferenceServiceStatus(String inferenceServiceName, String namespace, int timeout,
+ int statusCheckInterval) throws ExecutionException, InterruptedException {
+ // Invoke runnable thread to check pod status
+ Future<String> result = executor.submit(
+ new InferenceServiceValidator(inferenceServiceName, namespace, timeout, statusCheckInterval,
+ kserveClient), "Done");
+ return (!result.get().isEmpty()) && result.isDone();
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidator.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidator.java
new file mode 100755
index 000000000..65c4c7e27
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidator.java
@@ -0,0 +1,102 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 2023 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.k8s;
+
+import io.kubernetes.client.openapi.ApiException;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import lombok.SneakyThrows;
+import org.onap.policy.clamp.acm.participant.kserve.exception.KserveException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class InferenceServiceValidator implements Runnable {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private final KserveClient kserveClient;
+
+ private final int statusCheckInterval;
+
+ //Timeout for the thread to exit.
+ private final int timeout;
+
+ private final String inferenceServiceName;
+
+ private final String namespace;
+
+ /**
+ * Constructor for PodStatusValidator.
+ *
+ * @param inferenceServiceName name of the inference service
+ * @param namespace kubernetes namespace
+ * @param timeout timeout for the thread to exit
+ * @param statusCheckInterval Interval to check pod status
+ */
+ public InferenceServiceValidator(String inferenceServiceName, String namespace, int timeout,
+ int statusCheckInterval, KserveClient kserveClient) {
+ this.inferenceServiceName = inferenceServiceName;
+ this.namespace = namespace;
+ this.timeout = timeout;
+ this.statusCheckInterval = statusCheckInterval;
+ this.kserveClient = kserveClient;
+ }
+
+
+ @SneakyThrows
+ @Override
+ public void run() {
+ logger.info("Polling the status of deployed Inference Service {} in namespace {}", inferenceServiceName,
+ namespace);
+ try {
+ verifyInferenceServiceStatus();
+ } catch (KserveException | IOException e) {
+ throw new KserveException("Error verifying the status of the inference service. Exiting", e);
+ }
+ }
+
+ /**
+ * Verify inference service status.
+ * @throws KserveException exception
+ * @throws IOException exception
+ * @throws InterruptedException exception
+ * @throws ApiException exception
+ */
+ private void verifyInferenceServiceStatus()
+ throws KserveException, IOException, InterruptedException, ApiException {
+ var isVerified = false;
+ long endTime = System.currentTimeMillis() + (timeout * 1000L);
+
+ while (!isVerified && System.currentTimeMillis() < endTime) {
+ var output = kserveClient.getInferenceServiceStatus(namespace, inferenceServiceName);
+ isVerified = output.equalsIgnoreCase(Boolean.TRUE.toString());
+ if (!isVerified) {
+ logger.info("Waiting for the inference service {} to be active ", inferenceServiceName);
+ // Recheck status of pods in specific intervals.
+ Thread.sleep(statusCheckInterval * 1000L);
+ } else {
+ logger.info("Inference Service {} is Ready to use ", inferenceServiceName);
+ }
+ }
+ if (!isVerified) {
+ throw new KserveException("Time out Exception verifying the status of the inference service");
+ }
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/KserveClient.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/KserveClient.java
new file mode 100755
index 000000000..b5e7892eb
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/k8s/KserveClient.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.k8s;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.CustomObjectsApi;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import javax.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import okhttp3.Response;
+import org.onap.policy.clamp.acm.participant.kserve.parameters.CustomResourceDefinitionParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class KserveClient {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private final ApiClient apiClient;
+
+ private final CustomResourceDefinitionParameters crdParams;
+
+ CustomObjectsApi customObjectsApi;
+
+ @PostConstruct
+ void initialize() {
+ apiClient.setDebugging(logger.isDebugEnabled());
+ customObjectsApi = new CustomObjectsApi(apiClient);
+ }
+
+ /**
+ * Deploy the inference service.
+ *
+ * @param namespace k8s namespace
+ * @param jsonContent k8s payload
+ * @throws ApiException exception
+ */
+ public boolean deployInferenceService(String namespace, String jsonContent) throws ApiException, IOException {
+ var httpCall = customObjectsApi.createNamespacedCustomObjectCall(crdParams.getGroup(), crdParams.getVersion(),
+ namespace, crdParams.getPlural(), jsonContent.getBytes(), null, null, null, null);
+ try (Response httpResponse = httpCall.execute()) {
+ logger.debug("Response of inference service deploy in namespace {} is {}", namespace, httpResponse);
+ return httpResponse.isSuccessful();
+ }
+ }
+
+ /**
+ * Undeploy inference service.
+ *
+ * @param namespace k8s namespace
+ * @param inferenceServiceName name of the inference service
+ * @throws ApiException exception
+ */
+ public boolean undeployInferenceService(String namespace, String inferenceServiceName)
+ throws ApiException, IOException {
+ var httpCall = customObjectsApi.deleteNamespacedCustomObjectCall(crdParams.getGroup(), crdParams.getVersion(),
+ namespace, crdParams.getPlural(), inferenceServiceName, crdParams.getGracePeriod(), false, null, null,
+ null, null);
+ try (Response httpResponse = httpCall.execute()) {
+ logger.debug("Response of inference service undeploy in namespace {} is {}", namespace, httpResponse);
+ return httpResponse.isSuccessful();
+ }
+ }
+
+ /**
+ * Get the status of Inference service.
+ *
+ * @param namespace k8s namespace
+ * @param inferenceServiceName name of the inference service
+ * @return State of the inference service
+ * @throws ApiException exception on k8s client
+ * @throws IOException exception
+ */
+ public String getInferenceServiceStatus(String namespace, String inferenceServiceName)
+ throws ApiException, IOException {
+ var httpCall =
+ customObjectsApi.getNamespacedCustomObjectCall(crdParams.getGroup(), crdParams.getVersion(), namespace,
+ crdParams.getPlural(), inferenceServiceName, null);
+ try (Response httpResponse = httpCall.execute()) {
+ logger.debug("Response of getting inference service in {} is {}", namespace, httpResponse);
+ if (httpResponse.isSuccessful() && httpResponse.body() != null) {
+ JsonNode jsonNode = new ObjectMapper().readTree(httpResponse.body().string());
+ return jsonNode.at("/status/conditions/2/status").asText();
+ }
+ }
+ return Boolean.FALSE.toString();
+ }
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/ConfigurationEntity.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/ConfigurationEntity.java
new file mode 100755
index 000000000..ab85b7c52
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/ConfigurationEntity.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.models;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class ConfigurationEntity {
+
+ @NotNull
+ @Valid
+ private List<KserveInferenceEntity> kserveInferenceEntities;
+
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/KserveInferenceEntity.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/KserveInferenceEntity.java
new file mode 100755
index 000000000..3717970c2
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/models/KserveInferenceEntity.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import javax.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+@Data
+@AllArgsConstructor
+@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+public class KserveInferenceEntity {
+
+ @NotNull
+ @JsonIgnore
+ private ToscaConceptIdentifier kserveInferenceEntityId;
+
+ @NotNull
+ private String name;
+
+ @NotNull
+ private String payload;
+
+ @NotNull
+ private String namespace;
+
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/CustomResourceDefinitionParameters.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/CustomResourceDefinitionParameters.java
new file mode 100755
index 000000000..69a7cb466
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/CustomResourceDefinitionParameters.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.parameters;
+
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+@Validated
+@Data
+@ConfigurationProperties(prefix = "customresourcedefinition")
+public class CustomResourceDefinitionParameters {
+
+ @NotNull
+ private String group;
+
+ @NotNull
+ private String version;
+
+ @NotNull
+ private String plural;
+
+ private int gracePeriod = 10;
+}
diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/KserveParticipantParameters.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/KserveParticipantParameters.java
new file mode 100755
index 000000000..81582e1f0
--- /dev/null
+++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/parameters/KserveParticipantParameters.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.kserve.parameters;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import lombok.Getter;
+import lombok.Setter;
+import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantIntermediaryParameters;
+import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantParameters;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * Class to hold all parameters needed for the Kserve participant.
+ */
+@Validated
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "participant")
+public class KserveParticipantParameters implements ParticipantParameters {
+
+ @NotNull
+ @Valid
+ private ParticipantIntermediaryParameters intermediaryParameters;
+}