summaryrefslogtreecommitdiffstats
path: root/netconfsimulator/src
diff options
context:
space:
mode:
Diffstat (limited to 'netconfsimulator/src')
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java34
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java31
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java43
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java70
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java31
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java59
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java91
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java36
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java67
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java37
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java111
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java60
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java50
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java57
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java76
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java32
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java37
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java37
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java40
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java104
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java46
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java95
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java34
-rw-r--r--netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java51
-rw-r--r--netconfsimulator/src/main/resources/application.properties8
-rw-r--r--netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java211
-rw-r--r--netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java150
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java69
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java86
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java103
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java87
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java172
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java69
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java94
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java102
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java121
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java135
-rw-r--r--netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java73
-rw-r--r--netconfsimulator/src/test/resources/application-it.properties0
-rw-r--r--netconfsimulator/src/test/resources/initialConfig.xml23
-rw-r--r--netconfsimulator/src/test/resources/invalidXmlFile.xml23
-rw-r--r--netconfsimulator/src/test/resources/newYangModel.yang8
-rw-r--r--netconfsimulator/src/test/resources/updatedConfig.xml24
-rw-r--r--netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml24
44 files changed, 2911 insertions, 0 deletions
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java
new file mode 100644
index 0000000..92e5b23
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.springframework.context.annotation.Bean;
+
+@org.springframework.context.annotation.Configuration
+public class Configuration {
+
+ @Bean
+ public HttpClient httpClient() {
+ return HttpClientBuilder.create().build();
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java
new file mode 100644
index 0000000..e2a0ed0
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java
@@ -0,0 +1,31 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Main {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class, args);
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java
new file mode 100644
index 0000000..2e9df99
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@EnableSwagger2
+@Configuration
+class SwaggerConfig {
+
+ @Bean
+ Docket api() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("org.onap.netconfsimulator"))
+ .paths(PathSelectors.any())
+ .build();
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java
new file mode 100644
index 0000000..9ae5641
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.annotation.EnableKafka;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
+
+@Configuration
+@EnableKafka
+class Config {
+
+ @Value("${spring.kafka.bootstrap-servers}")
+ private String bootstrapServer;
+
+ @Value("${spring.kafka.consumer.auto-offset-reset}")
+ private String offsetReset;
+
+ @Bean
+ ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(ConsumerFactory<String, String> consumerFactory) {
+ ConcurrentKafkaListenerContainerFactory<String, String> containerFactory = new ConcurrentKafkaListenerContainerFactory<>();
+ containerFactory.setConsumerFactory(consumerFactory);
+ return containerFactory;
+ }
+
+ @Bean
+ ConsumerFactory<String, String> consumerFactory() {
+ Map<String, Object> props = new HashMap<>();
+ props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer);
+ props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+ props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+ props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, offsetReset);
+ return new DefaultKafkaConsumerFactory<>(props);
+ }
+
+
+ @Bean
+ KafkaListenerHandler kafkaListenerHandler(ConsumerFactory<String, String> consumerFactory) {
+ return new KafkaListenerHandler(consumerFactory);
+ }
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java
new file mode 100644
index 0000000..4311cd6
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+class MessageDTO {
+ private long timestamp;
+ private String configuration;
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java
new file mode 100644
index 0000000..33bbdf7
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+import java.util.List;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Slf4j
+@RequestMapping("/store")
+public class StoreController {
+
+ private StoreService service;
+
+ @Autowired
+ public StoreController(StoreService service) {
+ this.service = service;
+ }
+
+ @GetMapping("/ping")
+ String ping() {
+ return "pong";
+ }
+
+ @GetMapping("cm-history")
+ List<MessageDTO> getAllConfigurationChanges() {
+ return service.getAllMessages();
+ }
+
+ @GetMapping("/less")
+ List<MessageDTO> less(@RequestParam(value = "offset", required = false, defaultValue = "${spring.kafka.default-offset}") long offset) {
+ return service.getLastMessages(offset);
+ }
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java
new file mode 100644
index 0000000..5fddff5
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.consumer.Consumer;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.common.TopicPartition;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.stereotype.Service;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Slf4j
+@Service
+public class StoreService {
+
+ private static final String CONFIG_TOPIC = "config";
+ private static final long CONSUMING_DURATION_IN_MS = 1000;
+
+ private ConsumerFactory<String, String> consumerFactory;
+ static final List<String> TOPICS_TO_SUBSCRIBE = Collections.singletonList(CONFIG_TOPIC);
+
+ @Autowired
+ StoreService(ConsumerFactory<String, String> consumerFactory) {
+ this.consumerFactory = consumerFactory;
+ }
+
+ List<MessageDTO> getAllMessages() {
+ List<MessageDTO> messages = new ArrayList<>();
+ String clientID = Long.toString(Instant.now().getEpochSecond());
+ try (Consumer<String, String> consumer = consumerFactory.createConsumer(clientID, clientID)) {
+ consumer.subscribe(TOPICS_TO_SUBSCRIBE);
+ ConsumerRecords<String, String> consumerRecords = consumer.poll(CONSUMING_DURATION_IN_MS);
+ consumerRecords.forEach(
+ consumerRecord ->
+ messages.add(new MessageDTO(consumerRecord.timestamp(), consumerRecord.value())));
+ log.debug(String.format("consumed %d messages", consumerRecords.count()));
+ }
+ return messages;
+ }
+
+ List<MessageDTO> getLastMessages(long offset) {
+ List<MessageDTO> messages = new ArrayList<>();
+ try (Consumer<String, String> consumer = createConsumer(offset)) {
+ ConsumerRecords<String, String> consumerRecords = consumer.poll(CONSUMING_DURATION_IN_MS);
+ consumerRecords.forEach(consumerRecord ->
+ messages.add(new MessageDTO(consumerRecord.timestamp(), consumerRecord.value())));
+ }
+ return messages;
+ }
+
+ private Consumer<String, String> createConsumer(long offsetFromLastIndex) {
+ String clientID = Long.toString(Instant.now().getEpochSecond());
+ Consumer<String, String> consumer = consumerFactory.createConsumer(clientID, clientID);
+ consumer.subscribe(TOPICS_TO_SUBSCRIBE);
+ seekConsumerTo(consumer, offsetFromLastIndex);
+ return consumer;
+ }
+
+ private void seekConsumerTo(Consumer<String, String> consumer, long offsetFromLastIndex) {
+ consumer.seekToEnd(consumer.assignment());
+ consumer.poll(CONSUMING_DURATION_IN_MS);
+ TopicPartition topicPartition = consumer.assignment().iterator().next();
+ long topicCurrentSize = consumer.position(topicPartition);
+ long indexToSeek = offsetFromLastIndex > topicCurrentSize ? 0 : topicCurrentSize - offsetFromLastIndex;
+ consumer.seek(topicPartition, indexToSeek);
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java
new file mode 100644
index 0000000..e3c04c9
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka.listener;
+
+import lombok.Getter;
+import org.springframework.kafka.listener.AbstractMessageListenerContainer;
+
+@Getter
+public class KafkaListenerEntry {
+
+ private String clientId;
+ private AbstractMessageListenerContainer listenerContainer;
+
+ public KafkaListenerEntry(String clientId, AbstractMessageListenerContainer listenerContainer) {
+ this.clientId = clientId;
+ this.listenerContainer = listenerContainer;
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java
new file mode 100644
index 0000000..604315d
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka.listener;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.core.ConsumerFactory;
+
+import org.springframework.kafka.listener.ContainerProperties;
+import org.springframework.kafka.listener.KafkaMessageListenerContainer;
+import org.springframework.kafka.listener.MessageListener;
+
+
+import org.springframework.kafka.support.TopicPartitionInitialOffset;
+
+import java.time.Instant;
+
+public class KafkaListenerHandler {
+
+ private static final int PARTITION = 0;
+ private static final long NUMBER_OF_HISTORICAL_MESSAGES_TO_SHOW = -10L;
+ private static final boolean RELATIVE_TO_CURRENT = false;
+ private ConsumerFactory<String, String> consumerFactory;
+
+
+ @Autowired
+ public KafkaListenerHandler(ConsumerFactory<String, String> consumerFactory) {
+ this.consumerFactory = consumerFactory;
+ }
+
+
+ public KafkaListenerEntry createKafkaListener(MessageListener messageListener, String topicName) {
+ String clientId = Long.toString(Instant.now().getEpochSecond());
+ ContainerProperties containerProperties = new ContainerProperties(topicName);
+ containerProperties.setGroupId(clientId);
+ KafkaMessageListenerContainer<String, String> listenerContainer = createListenerContainer(containerProperties,
+ topicName);
+
+ listenerContainer.setupMessageListener(messageListener);
+ return new KafkaListenerEntry(clientId, listenerContainer);
+ }
+
+
+ KafkaMessageListenerContainer<String, String> createListenerContainer(ContainerProperties containerProperties,
+ String topicName) {
+ TopicPartitionInitialOffset config = new TopicPartitionInitialOffset(topicName, PARTITION,
+ NUMBER_OF_HISTORICAL_MESSAGES_TO_SHOW, RELATIVE_TO_CURRENT);
+ return new KafkaMessageListenerContainer<>(consumerFactory, containerProperties, config);
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java
new file mode 100644
index 0000000..90f283a
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka.model;
+
+import lombok.Getter;
+
+@Getter
+public class KafkaMessage {
+ private long timestamp;
+ private String configuration;
+
+ public KafkaMessage(long timestamp, String configuration) {
+ this.timestamp = timestamp;
+ this.configuration = configuration;
+ }
+
+ KafkaMessage() {
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java
new file mode 100644
index 0000000..cdb4a8f
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java
@@ -0,0 +1,111 @@
+/*
+ * ============LICENSE_START=======================================================
+ * NETCONF-CONTROLLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore;
+
+import com.tailf.jnc.JNCException;
+
+import java.io.IOException;
+
+import lombok.extern.slf4j.Slf4j;
+import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationService;
+import org.onap.netconfsimulator.netconfcore.model.LoadModelResponse;
+import org.onap.netconfsimulator.netconfcore.model.NetconfModelLoaderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@Slf4j
+@RestController
+@RequestMapping("netconf")
+class NetconfController {
+
+ private final NetconfConfigurationService netconfService;
+ private final NetconfModelLoaderService netconfModelLoaderService;
+
+ @Autowired
+ NetconfController(NetconfConfigurationService netconfService,
+ NetconfModelLoaderService netconfModelLoaderService) {
+ this.netconfService = netconfService;
+ this.netconfModelLoaderService = netconfModelLoaderService;
+ }
+
+ @GetMapping(value = "get", produces = "application/xml")
+ ResponseEntity<String> getNetconfConfiguration() throws IOException, JNCException {
+ return ResponseEntity.ok(netconfService.getCurrentConfiguration());
+ }
+
+ @GetMapping(value = "get/{model}/{container}", produces = "application/xml")
+ ResponseEntity<String> getNetconfConfiguration(@PathVariable String model,
+ @PathVariable String container)
+ throws IOException {
+ ResponseEntity<String> entity;
+ try {
+ entity = ResponseEntity.ok(netconfService.getCurrentConfiguration(model, container));
+ } catch (JNCException exception) {
+ log.error("Get configuration for model {} and container {} failed.", model, container,
+ exception);
+ entity = ResponseEntity.badRequest().body(exception.toString());
+ }
+ return entity;
+ }
+
+ @PostMapping(value = "edit-config", produces = "application/xml")
+ @ResponseStatus(HttpStatus.ACCEPTED)
+ ResponseEntity<String> editConfig(@RequestPart("editConfigXml") MultipartFile editConfig)
+ throws IOException, JNCException {
+ log.info("Loading updated configuration");
+ if (editConfig == null || editConfig.isEmpty()) {
+ throw new IllegalArgumentException("No XML file with proper name: editConfigXml found.");
+ }
+ return ResponseEntity
+ .status(HttpStatus.ACCEPTED)
+ .body(netconfService.editCurrentConfiguration(editConfig));
+ }
+
+ @PostMapping("model/{moduleName}")
+ ResponseEntity<String> loadNewYangModel(@RequestBody MultipartFile yangModel,
+ @RequestBody MultipartFile initialConfig, @PathVariable String moduleName)
+ throws IOException {
+ LoadModelResponse response = netconfModelLoaderService.loadYangModel(yangModel, initialConfig, moduleName);
+ return ResponseEntity
+ .status(response.getStatusCode())
+ .body(response.getMessage());
+ }
+
+ @DeleteMapping("model/{modelName}")
+ ResponseEntity<String> deleteYangModel(@PathVariable String modelName)
+ throws IOException {
+ LoadModelResponse response = netconfModelLoaderService.deleteYangModel(modelName);
+ return ResponseEntity
+ .status(response.getStatusCode())
+ .body(response.getMessage());
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java
new file mode 100644
index 0000000..d90c60d
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java
@@ -0,0 +1,60 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+class NetconfBeanConfiguration {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetconfBeanConfiguration.class);
+
+ @Value("${netconf.port}")
+ private Integer netconfPort;
+
+ @Value("${netconf.address}")
+ private String netconfAddress;
+
+ @Value("${netconf.user}")
+ private String netconfUser;
+
+ @Value("${netconf.password}")
+ private String netconfPassword;
+
+ @Bean
+ NetconfConfigurationReader configurationReader() {
+ NetconfConnectionParams params = new NetconfConnectionParams(netconfAddress, netconfPort, netconfUser, netconfPassword);
+ LOGGER.info("Configuration params are : {}", params);
+ return new NetconfConfigurationReader(params, new NetconfSessionHelper());
+ }
+
+ @Bean
+ NetconfConfigurationEditor configurationEditor() {
+ NetconfConnectionParams params =
+ new NetconfConnectionParams(netconfAddress, netconfPort, netconfUser, netconfPassword);
+ return new NetconfConfigurationEditor(params, new NetconfSessionHelper());
+ }
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java
new file mode 100644
index 0000000..992c88d
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java
@@ -0,0 +1,50 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import com.tailf.jnc.Element;
+import com.tailf.jnc.JNCException;
+import com.tailf.jnc.NetconfSession;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+
+@Slf4j
+public class NetconfConfigurationEditor {
+
+ private NetconfConnectionParams params;
+ private NetconfSessionHelper netconfSessionHelper;
+
+ public NetconfConfigurationEditor(NetconfConnectionParams params, NetconfSessionHelper netconfSessionHelper) {
+ this.params = params;
+ this.netconfSessionHelper = netconfSessionHelper;
+ }
+
+ void editConfig(Element configurationXmlElement) throws JNCException, IOException {
+ log.debug("New configuration passed to simulator: {}", configurationXmlElement.toXMLString());
+ NetconfSession session = netconfSessionHelper.createNetconfSession(params);
+ session.editConfig(configurationXmlElement);
+ session.closeSession();
+
+ log.info("Successfully updated configuration");
+ }
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java
new file mode 100644
index 0000000..10fe40e
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import com.tailf.jnc.JNCException;
+import com.tailf.jnc.NetconfSession;
+import com.tailf.jnc.NodeSet;
+import java.io.IOException;
+import java.util.Objects;
+
+class NetconfConfigurationReader {
+
+ private NetconfConnectionParams params;
+ private NetconfSessionHelper netconfSessionHelper;
+
+ NetconfConfigurationReader(NetconfConnectionParams params, NetconfSessionHelper netconfSessionHelper) {
+ this.params = params;
+ this.netconfSessionHelper = netconfSessionHelper;
+ }
+
+ String getRunningConfig() throws IOException, JNCException {
+ NetconfSession session = netconfSessionHelper.createNetconfSession(params);
+ String config = session.getConfig().toXMLString();
+ session.closeSession();
+ return config;
+ }
+
+ String getRunningConfig(String modelPath) throws IOException, JNCException {
+ NetconfSession session = netconfSessionHelper.createNetconfSession(params);
+ NodeSet config = session.getConfig(modelPath);
+ if (Objects.isNull(config) || Objects.isNull(config.first())) {
+ throw new JNCException(JNCException.ELEMENT_MISSING, modelPath);
+ }
+ session.closeSession();
+ return config.first().toXMLString();
+ }
+
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java
new file mode 100644
index 0000000..248aec4
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java
@@ -0,0 +1,76 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import com.tailf.jnc.Element;
+import com.tailf.jnc.JNCException;
+import com.tailf.jnc.XMLParser;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import org.xml.sax.InputSource;
+
+@Service
+public class NetconfConfigurationService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetconfConfigurationService.class);
+ private static final String CONFIGURATION_HAS_BEEN_ACTIVATED = "New configuration has been activated";
+
+ private final NetconfConfigurationReader netconfConfigurationReader;
+ private NetconfConfigurationEditor configurationEditor;
+ private XMLParser parser;
+
+ @Autowired
+ public NetconfConfigurationService(NetconfConfigurationReader netconfConfigurationReader,
+ NetconfConfigurationEditor netconfConfigurationEditor) throws JNCException {
+ this.netconfConfigurationReader = netconfConfigurationReader;
+ this.configurationEditor = netconfConfigurationEditor;
+ this.parser = new XMLParser();
+ }
+
+ public String getCurrentConfiguration() throws IOException, JNCException {
+ return netconfConfigurationReader.getRunningConfig();
+ }
+
+ public String getCurrentConfiguration(String model, String container) throws IOException, JNCException {
+ String path = String.format("/%s:%s", model, container);
+ return netconfConfigurationReader.getRunningConfig(path);
+ }
+
+ public String editCurrentConfiguration(MultipartFile newConfiguration) throws IOException, JNCException {
+ Element configurationElement = convertMultipartToXmlElement(newConfiguration);
+ configurationEditor.editConfig(configurationElement);
+
+ LOGGER.debug("Loading new configuration: \n{}", configurationElement.toXMLString());
+ return CONFIGURATION_HAS_BEEN_ACTIVATED;
+ }
+
+ private Element convertMultipartToXmlElement(MultipartFile editConfig) throws IOException, JNCException {
+ InputSource inputSourceUpdateConfig = new InputSource(new ByteArrayInputStream(editConfig.getBytes()));
+ return parser.parse(inputSourceUpdateConfig);
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java
new file mode 100644
index 0000000..e43ff69
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class NetconfConfigurationTO {
+
+ private String configuration;
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java
new file mode 100644
index 0000000..ace0ee0
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java
@@ -0,0 +1,37 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.ToString;
+
+@AllArgsConstructor
+@ToString
+@Getter
+class NetconfConnectionParams {
+
+ private final String address;
+ private final int port;
+ private final String user;
+ private final String password;
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java
new file mode 100644
index 0000000..69fda7d
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import com.tailf.jnc.JNCException;
+import com.tailf.jnc.NetconfSession;
+import com.tailf.jnc.SSHConnection;
+import com.tailf.jnc.SSHSession;
+import java.io.IOException;
+
+class NetconfSessionHelper {
+
+ NetconfSession createNetconfSession(NetconfConnectionParams params) throws IOException, JNCException {
+ SSHConnection sshConnection = new SSHConnection(params.getAddress(), params.getPort());
+ sshConnection.authenticateWithPassword(params.getUser(), params.getPassword());
+ return new NetconfSession(new SSHSession(sshConnection));
+ }
+
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java
new file mode 100644
index 0000000..a6e292f
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.netconfcore.model;
+
+public class LoadModelResponse {
+
+ private Integer statusCode;
+ private String message;
+
+ public LoadModelResponse(Integer statusCode, String message) {
+ this.statusCode = statusCode;
+ this.message = message;
+ }
+
+ public Integer getStatusCode() {
+ return this.statusCode;
+ }
+
+ public String getMessage() {
+ return this.message;
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java
new file mode 100644
index 0000000..7e07395
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.netconfcore.model;
+
+import java.io.IOException;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class NetconfModelLoaderService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetconfModelLoaderService.class);
+
+ @Value("${netconf.address}")
+ private String netconfIp;
+
+ @Value("${netconf.model-loader.port}")
+ private String modelLoaderPort;
+
+ private final HttpClient httpClient;
+
+ @Autowired
+ public NetconfModelLoaderService(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+ public LoadModelResponse deleteYangModel(String yangModelName) throws IOException {
+ String uri = getDeleteAddress(yangModelName);
+ HttpDelete httpDelete = new HttpDelete(uri);
+ HttpResponse httpResponse = httpClient.execute(httpDelete);
+ return parseResponse(httpResponse);
+ }
+
+ public LoadModelResponse loadYangModel(MultipartFile yangModel, MultipartFile initialConfig, String moduleName)
+ throws IOException {
+ HttpPost httpPost = new HttpPost(getBackendAddress());
+ HttpEntity httpEntity = MultipartEntityBuilder.create()
+ .addBinaryBody("yangModel", yangModel.getInputStream(), ContentType.MULTIPART_FORM_DATA,
+ yangModel.getOriginalFilename())
+ .addBinaryBody("initialConfig", initialConfig.getInputStream(), ContentType.MULTIPART_FORM_DATA,
+ initialConfig.getOriginalFilename())
+ .addTextBody("moduleName", moduleName)
+ .build();
+ httpPost.setEntity(httpEntity);
+ HttpResponse response = httpClient.execute(httpPost);
+ return parseResponse(response);
+ }
+
+ String getBackendAddress() {
+ return String.format("http://%s:%s/model", netconfIp, modelLoaderPort);
+ }
+
+ String getDeleteAddress(String yangModelName) {
+ return String.format("%s?yangModelName=%s", getBackendAddress(), yangModelName);
+ }
+
+
+ private LoadModelResponse parseResponse(HttpResponse response) throws IOException {
+ int statusCode = response.getStatusLine().getStatusCode();
+ String responseBody = EntityUtils.toString(response.getEntity());
+
+ logResponse(statusCode, responseBody);
+ return new LoadModelResponse(statusCode, responseBody);
+ }
+
+ private void logResponse(int statusCode, String responseBody) {
+ if (statusCode >= HttpStatus.BAD_REQUEST.value()) {
+ LOGGER.error(responseBody);
+ } else {
+ LOGGER.info(responseBody);
+ }
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java
new file mode 100644
index 0000000..4eaa850
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.websocket;
+
+import java.util.Collections;
+import org.onap.netconfsimulator.websocket.message.NetconfMessageEncoder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+import org.springframework.web.socket.server.standard.ServerEndpointRegistration;
+
+@Configuration
+class EndpointConfig {
+
+ @Bean
+ ServerEndpointRegistration endpointRegistration() {
+ ServerEndpointRegistration serverEndpointRegistration = new ServerEndpointRegistration("/netconf",
+ NetconfEndpoint.class);
+ serverEndpointRegistration.setEncoders(Collections.singletonList(NetconfMessageEncoder.class));
+ return serverEndpointRegistration;
+ }
+
+ @Bean
+ ServerEndpointExporter endpointExporter() {
+ return new ServerEndpointExporter();
+ }
+}
+
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java
new file mode 100644
index 0000000..5870ee1
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.websocket;
+
+
+import java.util.Optional;
+import javax.websocket.CloseReason;
+import javax.websocket.Endpoint;
+import javax.websocket.EndpointConfig;
+import javax.websocket.RemoteEndpoint;
+import javax.websocket.Session;
+
+import org.onap.netconfsimulator.kafka.listener.KafkaListenerEntry;
+import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler;
+import org.onap.netconfsimulator.websocket.message.NetconfMessageListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.listener.AbstractMessageListenerContainer;
+import org.springframework.kafka.listener.MessageListener;
+import org.springframework.stereotype.Component;
+
+//instance of this class is created every each websocket request
+@Component
+class NetconfEndpoint extends Endpoint {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetconfEndpoint.class);
+ private static final String TOPIC_NAME = "config";
+
+ private KafkaListenerHandler kafkaListenerHandler;
+
+ public Optional<KafkaListenerEntry> getEntry() {
+ return entry;
+ }
+
+ public void setEntry(Optional<KafkaListenerEntry> entry) {
+ this.entry = entry;
+ }
+
+ private Optional<KafkaListenerEntry> entry = Optional.empty();
+
+
+ @Autowired
+ NetconfEndpoint(KafkaListenerHandler listenerHandler) {
+ this.kafkaListenerHandler = listenerHandler;
+ }
+
+ @Override
+ public void onOpen(Session session, EndpointConfig endpointConfig) {
+ RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
+
+ addKafkaListener(basicRemote);
+ entry.ifPresent(x -> LOGGER.info("Session with client: {} established", x.getClientId()));
+ }
+
+ @Override
+ public void onError(Session session, Throwable throwable) {
+ LOGGER.error("Unexpected error occurred", throwable);
+ }
+
+ @Override
+ public void onClose(Session session, CloseReason closeReason) {
+ entry.ifPresent(x -> x.getListenerContainer().stop());
+ entry.ifPresent(x -> LOGGER.info("Closing connection for client: {}", x.getClientId()));
+ }
+
+
+ private void addKafkaListener(RemoteEndpoint.Basic remoteEndpoint) {
+ MessageListener messageListener = new NetconfMessageListener(remoteEndpoint);
+
+ KafkaListenerEntry kafkaListener = kafkaListenerHandler.createKafkaListener(messageListener, TOPIC_NAME);
+
+ AbstractMessageListenerContainer listenerContainer = kafkaListener.getListenerContainer();
+ listenerContainer.start();
+ entry = Optional.of(kafkaListener);
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java
new file mode 100644
index 0000000..349b7e2
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.websocket.message;
+
+import org.onap.netconfsimulator.kafka.model.KafkaMessage;
+import org.springframework.web.socket.adapter.standard.ConvertingEncoderDecoderSupport;
+
+public class NetconfMessageEncoder extends ConvertingEncoderDecoderSupport.TextEncoder<KafkaMessage> {
+
+ private static final String MESSAGE_FORMAT = "%s: %s";
+
+ @Override
+ public String encode(KafkaMessage netconfMessage) {
+ return String.format(MESSAGE_FORMAT, netconfMessage.getTimestamp(), netconfMessage.getConfiguration());
+ }
+}
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java
new file mode 100644
index 0000000..61610de
--- /dev/null
+++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.websocket.message;
+
+import java.io.IOException;
+import javax.websocket.EncodeException;
+import javax.websocket.RemoteEndpoint;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.onap.netconfsimulator.kafka.model.KafkaMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.kafka.listener.MessageListener;
+
+public class NetconfMessageListener implements MessageListener<String, String> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetconfMessageListener.class);
+ private RemoteEndpoint.Basic remoteEndpoint;
+
+ public NetconfMessageListener(RemoteEndpoint.Basic remoteEndpoint) {
+ this.remoteEndpoint = remoteEndpoint;
+ }
+
+ @Override
+ public void onMessage(ConsumerRecord<String, String> message) {
+ LOGGER.debug("Attempting to send message to {}", remoteEndpoint);
+ try {
+ remoteEndpoint
+ .sendObject(new KafkaMessage(message.timestamp(), message.value()));
+ } catch (IOException | EncodeException exception) {
+ LOGGER.error("Error during sending message to remote", exception);
+ }
+ }
+}
diff --git a/netconfsimulator/src/main/resources/application.properties b/netconfsimulator/src/main/resources/application.properties
new file mode 100644
index 0000000..3947cf3
--- /dev/null
+++ b/netconfsimulator/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+netconf.port=830
+netconf.address=netopeer
+netconf.user=netconf
+netconf.password=netconf
+netconf.model-loader.port=5002
+spring.kafka.bootstrap-servers=kafka1:9092
+spring.kafka.default-offset=100
+spring.kafka.consumer.auto-offset-reset=earliest
diff --git a/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java b/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java
new file mode 100644
index 0000000..95ef586
--- /dev/null
+++ b/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java
@@ -0,0 +1,211 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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 integration;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.palantir.docker.compose.connection.DockerMachine;
+import com.palantir.docker.compose.connection.waiting.HealthChecks;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.bitbucket.radistao.test.annotation.BeforeAllMethods;
+import org.bitbucket.radistao.test.runner.BeforeAfterSpringTestRunner;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import com.palantir.docker.compose.DockerComposeRule;
+import org.onap.netconfsimulator.kafka.model.KafkaMessage;
+import org.springframework.http.HttpStatus;
+
+import java.io.IOException;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(BeforeAfterSpringTestRunner.class)
+public class NetconfFunctionsIT {
+
+ private static NetconfSimulatorClient client;
+ private static ObjectMapper objectMapper;
+
+ private static final DockerMachine dockerMachine = DockerMachine
+ .localMachine()
+ .build();
+
+ private static DockerComposeRule docker = DockerComposeRule.builder()
+ .file("docker-compose.yml")
+ .machine(dockerMachine)
+ .removeConflictingContainersOnStartup(true)
+ .waitingForService("sftp-server", HealthChecks.toHaveAllPortsOpen())
+ .waitingForService("ftpes-server", HealthChecks.toHaveAllPortsOpen())
+ .waitingForService("zookeeper", HealthChecks.toHaveAllPortsOpen())
+ .waitingForService("netopeer", HealthChecks.toHaveAllPortsOpen())
+ .waitingForService("kafka1", HealthChecks.toHaveAllPortsOpen())
+ .waitingForService("netconf-simulator", HealthChecks.toHaveAllPortsOpen())
+ .build();
+
+ @ClassRule
+ public static TestRule exposePortMappings = docker;
+
+ @BeforeClass
+ public static void setUpClass() {
+ objectMapper = new ObjectMapper();
+ client = new NetconfSimulatorClient(String.format("http://%s:%d", docker.containers().ip(), 9000));
+ }
+
+ @BeforeAllMethods
+ public void setupBeforeAll() throws InterruptedException {
+ if (client.isServiceAvailable(Instant.now(), Duration.ofSeconds(45))) {
+ Thread.sleep(60000);
+ return;
+ }
+ fail("Application failed to start within established timeout: 45 seconds. Exiting.");
+ }
+
+ @Before
+ public void setUp() {
+ client.reinitializeClient();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ client.releaseClient();
+ }
+
+ @Test
+ public void testShouldLoadModelEditConfigurationAndDeleteModule() throws IOException {
+ // do load
+ try (CloseableHttpResponse response = client
+ .loadModel("newyangmodel", "newYangModel.yang", "initialConfig.xml")) {
+ assertResponseStatusCode(response, HttpStatus.OK);
+ String original = client.getResponseContentAsString(response);
+ assertThat(original).isEqualTo("\"Successfully started\"\n");
+ }
+ // do edit-config
+ try (CloseableHttpResponse updateResponse = client.updateConfig()) {
+ String afterUpdateConfigContent = client.getResponseContentAsString(updateResponse);
+ assertResponseStatusCode(updateResponse, HttpStatus.ACCEPTED);
+ assertThat(afterUpdateConfigContent).isEqualTo("New configuration has been activated");
+ }
+ // do delete
+ try (CloseableHttpResponse deleteResponse = client.deleteModel("newyangmodel")) {
+ assertResponseStatusCode(deleteResponse, HttpStatus.OK);
+ String original = client.getResponseContentAsString(deleteResponse);
+ assertThat(original).isEqualTo("\"Successfully deleted\"\n");
+ }
+ }
+
+ @Test
+ public void testShouldGetCurrentConfigurationAndEditItSuccessfully() throws IOException {
+ try (CloseableHttpResponse updateResponse = client.updateConfig();
+ CloseableHttpResponse newCurrentConfigResponse = client.getCurrentConfig()) {
+ String afterUpdateConfigContent = client.getResponseContentAsString(updateResponse);
+
+ assertResponseStatusCode(updateResponse, HttpStatus.ACCEPTED);
+ assertResponseStatusCode(newCurrentConfigResponse, HttpStatus.OK);
+
+ assertThat(afterUpdateConfigContent).isEqualTo("New configuration has been activated");
+ }
+ }
+
+ @Test
+ public void testShouldPersistConfigChangesAndGetAllWhenRequested() throws IOException {
+ client.updateConfig();
+
+ try (CloseableHttpResponse newAllConfigChangesResponse = client.getAllConfigChanges()) {
+ String newAllConfigChangesString = client.getResponseContentAsString(newAllConfigChangesResponse);
+ assertResponseStatusCode(newAllConfigChangesResponse, HttpStatus.OK);
+
+ List<KafkaMessage> kafkaMessages = objectMapper
+ .readValue(newAllConfigChangesString, new TypeReference<List<KafkaMessage>>() {
+ });
+
+ assertThat(kafkaMessages.size()).isGreaterThanOrEqualTo(1);
+ Set<String> configChangeContent = kafkaMessages.stream().map(KafkaMessage::getConfiguration)
+ .collect(Collectors.toSet());
+ assertThat(configChangeContent)
+ .anyMatch(el -> el.contains("new value: /pnf-simulator:config/itemValue1 = 100"));
+ assertThat(configChangeContent)
+ .anyMatch(el -> el.contains("new value: /pnf-simulator:config/itemValue2 = 200"));
+ }
+ }
+
+ @Test
+ public void testShouldGetLastMessage() throws IOException {
+ client.updateConfig();
+
+ try (CloseableHttpResponse lastConfigChangesResponse = client.getLastConfigChanges(2)) {
+ String newAllConfigChangesString = client.getResponseContentAsString(lastConfigChangesResponse);
+ List<KafkaMessage> kafkaMessages = objectMapper
+ .readValue(newAllConfigChangesString, new TypeReference<List<KafkaMessage>>() {
+ });
+
+ assertThat(kafkaMessages).hasSize(2);
+ assertThat(kafkaMessages.get(0).getConfiguration())
+ .contains("new value: /pnf-simulator:config/itemValue1 = 100");
+ assertThat(kafkaMessages.get(1).getConfiguration())
+ .contains("new value: /pnf-simulator:config/itemValue2 = 200");
+ }
+ }
+
+ @Test
+ public void testShouldLoadNewYangModelAndReconfigure() throws IOException {
+ try (CloseableHttpResponse response = client
+ .loadModel("newyangmodel", "newYangModel.yang", "initialConfig.xml")) {
+ assertResponseStatusCode(response, HttpStatus.OK);
+
+ String original = client.getResponseContentAsString(response);
+
+ assertThat(original).isEqualTo("\"Successfully started\"\n");
+ }
+ }
+
+ @Test
+ public void shouldGetLoadedModelByName() throws IOException {
+ testShouldLoadNewYangModelAndReconfigure();
+
+ try (CloseableHttpResponse response = client.getConfigByModelAndContainerNames("newyangmodel", "config2")) {
+ assertResponseStatusCode(response, HttpStatus.OK);
+ String config = client.getResponseContentAsString(response);
+
+ assertThat(config).isEqualTo(
+ "<config2 xmlns=\"http://onap.org/newyangmodel\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+ + " <item1>100</item1>\n"
+ + "</config2>\n");
+ }
+
+ }
+
+ private void assertResponseStatusCode(HttpResponse response, HttpStatus expectedStatus) {
+ assertThat(response.getStatusLine().getStatusCode()).isEqualTo(expectedStatus.value());
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java b/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java
new file mode 100644
index 0000000..61f2ef1
--- /dev/null
+++ b/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java
@@ -0,0 +1,150 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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 integration;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.junit.platform.commons.logging.Logger;
+import org.junit.platform.commons.logging.LoggerFactory;
+import org.springframework.util.ResourceUtils;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.time.Instant;
+
+class NetconfSimulatorClient {
+
+ private CloseableHttpClient netconfClient;
+ private String simulatorBaseUrl;
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfSimulatorClient.class);
+
+ NetconfSimulatorClient(String simulatorBaseUrl) {
+ this.netconfClient = HttpClients.createDefault();
+ this.simulatorBaseUrl = simulatorBaseUrl;
+ }
+
+ CloseableHttpResponse loadModel(String moduleName, String yangModelFileName, String initialiConfigFileName) throws IOException {
+ String updateConfigUrl = String.format("%s/netconf/model/%s", simulatorBaseUrl, moduleName);
+ HttpPost httpPost = new HttpPost(updateConfigUrl);
+ HttpEntity updatedConfig = MultipartEntityBuilder
+ .create()
+ .addBinaryBody("yangModel", ResourceUtils.getFile(String.format("classpath:%s", yangModelFileName)))
+ .addBinaryBody("initialConfig", ResourceUtils.getFile(String.format("classpath:%s",initialiConfigFileName)))
+ .addTextBody("moduleName", moduleName)
+ .build();
+ httpPost.setEntity(updatedConfig);
+ return netconfClient.execute(httpPost);
+ }
+
+ CloseableHttpResponse deleteModel(String moduleName) throws IOException {
+ String deleteModuleUrl = String.format("%s/netconf/model/%s", simulatorBaseUrl, moduleName);
+ HttpDelete httpDelete = new HttpDelete(deleteModuleUrl);
+ return netconfClient.execute(httpDelete);
+ }
+
+ boolean isServiceAvailable(Instant startTime, Duration maxWaitingDuration) throws InterruptedException {
+ boolean isServiceReady = false;
+ while (Duration.between(startTime, Instant.now()).compareTo(maxWaitingDuration) < 1){
+ if(checkIfSimResponds()){
+ return true;
+ }
+ else {
+ LOG.info(() -> "Simulator not ready yet, retrying in 5s...");
+ Thread.sleep(5000);
+ }
+ }
+ return isServiceReady;
+ }
+
+ private boolean checkIfSimResponds() throws InterruptedException {
+ try(CloseableHttpResponse pingResponse = getCurrentConfig()){
+ String responseString = getResponseContentAsString(pingResponse);
+ if(pingResponse.getStatusLine().getStatusCode() == 200 && !responseString.trim().isEmpty()){
+ return true;
+ }
+ }
+ catch(IOException ex){
+ LOG.error(ex, () -> "EXCEPTION");
+ Thread.sleep(5000);
+ }
+ return false;
+ }
+
+ CloseableHttpResponse getCurrentConfig() throws IOException {
+ String netconfAddress = String.format("%s/netconf/get", simulatorBaseUrl);
+ HttpGet get = new HttpGet(netconfAddress);
+ return netconfClient.execute(get);
+ }
+
+ CloseableHttpResponse getConfigByModelAndContainerNames(String model, String container) throws IOException {
+ String netconfAddress = String
+ .format("%s/netconf/get/%s/%s", simulatorBaseUrl, model, container);
+ HttpGet get = new HttpGet(netconfAddress);
+ return netconfClient.execute(get);
+ }
+
+ CloseableHttpResponse updateConfig() throws IOException {
+ String updateConfigUrl = String.format("%s/netconf/edit-config", simulatorBaseUrl);
+ HttpPost httpPost = new HttpPost(updateConfigUrl);
+ HttpEntity updatedConfig = MultipartEntityBuilder
+ .create()
+ .addBinaryBody("editConfigXml", ResourceUtils.getFile("classpath:updatedConfig.xml"))
+ .build();
+ httpPost.setEntity(updatedConfig);
+ return netconfClient.execute(httpPost);
+ }
+
+ CloseableHttpResponse getAllConfigChanges() throws IOException {
+ String netconfStoreCmHistoryAddress = String.format("%s/store/cm-history", simulatorBaseUrl);
+ HttpGet configurationChangesResponse = new HttpGet(netconfStoreCmHistoryAddress);
+ return netconfClient.execute(configurationChangesResponse);
+ }
+
+ CloseableHttpResponse getLastConfigChanges(int howManyLastChanges) throws IOException {
+ String netconfStoreCmHistoryAddress = String.format("%s/store/less?offset=%d", simulatorBaseUrl, howManyLastChanges);
+ HttpGet configurationChangesResponse = new HttpGet(netconfStoreCmHistoryAddress);
+ return netconfClient.execute(configurationChangesResponse);
+ }
+
+ void releaseClient() throws IOException {
+ netconfClient.close();
+ }
+
+ void reinitializeClient(){
+ netconfClient = HttpClients.createDefault();
+ }
+
+ String getResponseContentAsString(HttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ String entityStringRepr = EntityUtils.toString(entity);
+ EntityUtils.consume(entity);
+ return entityStringRepr;
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java
new file mode 100644
index 0000000..5ddf2b2
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+
+import java.util.Map;
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaProducerFactory;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.core.ProducerFactory;
+import org.springframework.kafka.test.utils.KafkaTestUtils;
+
+import static org.onap.netconfsimulator.kafka.StoreServiceTest.embeddedKafka;
+
+@Configuration
+class EmbeddedKafkaConfig {
+
+ @Bean
+ KafkaTemplate<String, String> kafkaTemplate(){
+ return new KafkaTemplate<>(producerFactory());
+ }
+
+ @Bean
+ @Autowired
+ ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(ConsumerFactory<String, String> consumerFactory){
+ ConcurrentKafkaListenerContainerFactory<String, String> containerFactory = new ConcurrentKafkaListenerContainerFactory<>();
+ containerFactory.setConsumerFactory(consumerFactory);
+ return containerFactory;
+ }
+
+ @Bean
+ ConsumerFactory<String, String> consumerFactory(){
+ Map<String, Object> consumerProperties =
+ KafkaTestUtils.consumerProps("sender", "false", embeddedKafka.getEmbeddedKafka());
+ consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
+ return new DefaultKafkaConsumerFactory<>(consumerProperties);
+ }
+
+ private ProducerFactory<String, String> producerFactory() {
+ Map<String, Object> senderProperties =
+ KafkaTestUtils.senderProps(embeddedKafka.getEmbeddedKafka().getBrokersAsString());
+ return new DefaultKafkaProducerFactory<>(senderProperties);
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java
new file mode 100644
index 0000000..02eec12
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+import java.time.Instant;
+import java.util.List;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import static org.mockito.Mockito.when;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class StoreControllerTest {
+
+ private static final String MESSAGE_3 = "message 3";
+ private static final String MESSAGE_2 = "message 2";
+ private static final String MESSAGE_1 = "message 1";
+
+ private static final List<MessageDTO> ALL_MESSAGES = Lists.newArrayList(new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_1),
+ new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_2),
+ new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_3));
+
+ @Mock
+ private StoreService service;
+
+ @InjectMocks
+ private StoreController storeController;
+
+
+ @Test
+ public void lessShouldTakeAllMessagesTest() {
+ when(service.getLastMessages(3)).thenReturn(ALL_MESSAGES);
+
+ List<MessageDTO> lessResponse = storeController.less(3);
+
+ assertResponseContainsExpectedMessages(lessResponse, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3);
+ }
+
+ @Test
+ public void lessShouldTakeTwoMessagesTest() {
+ when(service.getLastMessages(2)).thenReturn(Lists.newArrayList(new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_1)));
+
+ List<MessageDTO> lessResult = storeController.less(2);
+
+ assertResponseContainsExpectedMessages(lessResult, 1, MESSAGE_1);
+ }
+
+ @Test
+ public void shouldGetAllMessages(){
+ when(service.getAllMessages()).thenReturn(ALL_MESSAGES);
+
+ List<MessageDTO> allMsgResult = storeController.getAllConfigurationChanges();
+
+ assertResponseContainsExpectedMessages(allMsgResult, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3);
+ }
+
+ private void assertResponseContainsExpectedMessages(List<MessageDTO> actualMessages, int expectedMessageCount, String... expectedMessages){
+ Assertions.assertThat(actualMessages.stream().map(MessageDTO::getConfiguration))
+ .hasSize(expectedMessageCount)
+ .containsExactly(expectedMessages);
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java
new file mode 100644
index 0000000..fd36116
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka;
+
+import org.bitbucket.radistao.test.annotation.BeforeAllMethods;
+import org.bitbucket.radistao.test.runner.BeforeAfterSpringTestRunner;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.test.context.EmbeddedKafka;
+import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(BeforeAfterSpringTestRunner.class)
+@SpringBootTest(classes = {StoreService.class, EmbeddedKafkaConfig.class})
+@EmbeddedKafka
+public class StoreServiceTest {
+
+ private static final String MESSAGE_1 = "message1";
+ private static final String MESSAGE_2 = "message2";
+ private static final String MESSAGE_3 = "message3";
+
+ @ClassRule
+ public static EmbeddedKafkaRule embeddedKafka = new EmbeddedKafkaRule(1, true, 1, "config");
+
+ @Autowired
+ StoreService service;
+
+ @Autowired
+ KafkaTemplate<String, String> kafkaTemplate;
+
+ @BeforeAllMethods
+ public void setupBeforeAll() {
+ prepareProducer();
+ }
+
+ @Test
+ public void testShouldReturnAllAvailableMessages(){
+
+ List<MessageDTO> actualMessages = service.getAllMessages();
+
+ assertResponseContainsExpectedMessages(actualMessages, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3);
+ }
+
+ @Test
+ public void testShouldGetLastMessagesRespectingOffset(){
+
+ List<MessageDTO> wantedLastMsg = service.getLastMessages(1L);
+
+ assertResponseContainsExpectedMessages(wantedLastMsg, 1, MESSAGE_3);
+ }
+
+ @Test
+ public void testShouldGetAll3Messages() {
+ List<MessageDTO> wantedLastMsgs = service.getLastMessages(3L);
+
+ assertResponseContainsExpectedMessages(wantedLastMsgs, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3);
+ }
+
+ private void prepareProducer(){
+ kafkaTemplate.send("config", "message1");
+ kafkaTemplate.send("config", "message2");
+ kafkaTemplate.send("config", "message3");
+ }
+
+ private void assertResponseContainsExpectedMessages(List<MessageDTO> actualMessages, int expectedMessageCount, String... expectedMessages){
+ assertThat(actualMessages.stream().map(MessageDTO::getConfiguration))
+ .hasSize(expectedMessageCount)
+ .containsExactly(expectedMessages);
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java
new file mode 100644
index 0000000..fcb7266
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.kafka.listener;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.listener.ContainerProperties;
+import org.springframework.kafka.listener.KafkaMessageListenerContainer;
+import org.springframework.kafka.listener.MessageListener;
+
+class KafkaListenerHandlerTest {
+
+ private static final String CLIENT_ID_REGEX = "[0-9]{10,}";
+ private static final String SAMPLE_TOPIC = "sampleTopic";
+
+ @Mock
+ private ConsumerFactory<String, String> consumerFactory;
+
+ @Mock
+ private KafkaMessageListenerContainer<String, String> kafkaMessageListenerContainer;
+
+ @Mock
+ private MessageListener messageListener;
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ }
+
+
+ @Test
+ void shouldProperlyCreateKafkaListener() {
+ KafkaListenerHandler kafkaListenerHandler = spy(new KafkaListenerHandler(consumerFactory));
+ doReturn(kafkaMessageListenerContainer).when(kafkaListenerHandler)
+ .createListenerContainer(any(ContainerProperties.class), eq(SAMPLE_TOPIC));
+
+ KafkaListenerEntry kafkaListenerEntry = kafkaListenerHandler
+ .createKafkaListener(messageListener, SAMPLE_TOPIC);
+
+ assertThat(kafkaListenerEntry.getListenerContainer()).isEqualTo(kafkaMessageListenerContainer);
+ assertThat(kafkaListenerEntry.getClientId()).matches(CLIENT_ID_REGEX);
+ }
+
+ @Test
+ void shouldProperlyCreateContainer() {
+ KafkaListenerHandler kafkaListenerHandler = spy(new KafkaListenerHandler(consumerFactory));
+ ContainerProperties containerProperties = new ContainerProperties(SAMPLE_TOPIC);
+ containerProperties.setMessageListener(mock(MessageListener.class));
+
+ KafkaMessageListenerContainer<String, String> listenerContainer = kafkaListenerHandler
+ .createListenerContainer(containerProperties, SAMPLE_TOPIC);
+
+ ContainerProperties actualProperties = listenerContainer.getContainerProperties();
+ assertThat(actualProperties.getTopics()).isEqualTo(containerProperties.getTopics());
+ assertThat(actualProperties.getMessageListener()).isEqualTo(containerProperties.getMessageListener());
+ }
+
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java
new file mode 100644
index 0000000..73fb627
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java
@@ -0,0 +1,172 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import com.tailf.jnc.JNCException;
+import java.io.IOException;
+import java.nio.file.Files;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationService;
+import org.onap.netconfsimulator.netconfcore.model.LoadModelResponse;
+import org.onap.netconfsimulator.netconfcore.model.NetconfModelLoaderService;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+class NetconfControllerTest {
+
+ private MockMvc mockMvc;
+
+ @Mock
+ private NetconfConfigurationService netconfService;
+
+ @Mock
+ private NetconfModelLoaderService netconfModelLoaderService;
+
+ @InjectMocks
+ private NetconfController controller;
+
+ private static final String SAMPLE_CONFIGURATION = "<config xmlns=\"http://onap.org/pnf-simulator\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><itemValue1>11</itemValue1><itemValue2>22</itemValue2></config>";
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+ }
+
+ @Test
+ void testShouldDigestMultipartFile() throws Exception {
+ byte[] bytes =
+ Files.readAllBytes(ResourceUtils.getFile("classpath:updatedConfig.xml").toPath());
+ MockMultipartFile file = new MockMultipartFile("editConfigXml", bytes);
+
+ mockMvc
+ .perform(MockMvcRequestBuilders.multipart("/netconf/edit-config").file(file))
+ .andExpect(status().isAccepted());
+
+ verify(netconfService).editCurrentConfiguration(any(MultipartFile.class));
+ }
+
+ @Test
+ void testShouldThrowExceptionWhenEditConfigFileWithIncorrectNameProvided() throws Exception {
+ MockMultipartFile file = new MockMultipartFile("wrongName", new byte[0]);
+
+ mockMvc
+ .perform(MockMvcRequestBuilders.multipart("/netconf/edit-config").file(file))
+ .andExpect(status().isBadRequest());
+
+ verify(netconfService, never()).editCurrentConfiguration(any(MultipartFile.class));
+ }
+
+ @Test
+ void testShouldReturnCurrentConfiguration() throws Exception {
+ when(netconfService.getCurrentConfiguration()).thenReturn(SAMPLE_CONFIGURATION);
+
+ String contentAsString =
+ mockMvc
+ .perform(get("/netconf/get"))
+ .andExpect(status().isOk())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ verify(netconfService).getCurrentConfiguration();
+ assertThat(contentAsString).isEqualTo(SAMPLE_CONFIGURATION);
+ }
+
+ @Test
+ void testShouldReturnConfigurationForGivenPath() throws Exception {
+ when(netconfService.getCurrentConfiguration("sampleModel", "sampleContainer"))
+ .thenReturn(SAMPLE_CONFIGURATION);
+
+ String contentAsString =
+ mockMvc
+ .perform(get("/netconf/get/sampleModel/sampleContainer"))
+ .andExpect(status().isOk())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ verify(netconfService).getCurrentConfiguration("sampleModel", "sampleContainer");
+ assertThat(contentAsString).isEqualTo(SAMPLE_CONFIGURATION);
+ }
+
+ @Test
+ void testShouldRaiseBadRequestWhenConfigurationIsNotPresent() throws Exception {
+ when(netconfService.getCurrentConfiguration("sampleModel", "sampleContainer2"))
+ .thenThrow(new JNCException(JNCException.ELEMENT_MISSING, "/sampleModel:sampleContainer2"));
+
+ String contentAsString =
+ mockMvc
+ .perform(get("/netconf/get/sampleModel/sampleContainer2"))
+ .andExpect(status().isBadRequest())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ assertThat(contentAsString).isEqualTo("Element does not exists: /sampleModel:sampleContainer2");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenNoConfigurationPresent() throws IOException, JNCException {
+ when(netconfService.getCurrentConfiguration()).thenThrow(JNCException.class);
+
+ assertThatThrownBy(() -> mockMvc.perform(get("/netconf/get")))
+ .hasRootCauseExactlyInstanceOf(JNCException.class);
+ }
+
+ @Test
+ void testShouldDeleteYangModel() throws Exception {
+ String responseOkString = "Alles klar";
+ String yangModelName = "someModel";
+ LoadModelResponse loadModelResponse = new LoadModelResponse(200, responseOkString);
+ String uri = String.format("/netconf/model/%s", yangModelName);
+ when(netconfModelLoaderService.deleteYangModel(yangModelName)).thenReturn(loadModelResponse);
+
+ String contentAsString =
+ mockMvc
+ .perform(delete(uri))
+ .andExpect(status().isOk())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ verify(netconfModelLoaderService).deleteYangModel(yangModelName);
+ assertThat(contentAsString).isEqualTo(responseOkString);
+ }
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java
new file mode 100644
index 0000000..371bdd8
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import com.tailf.jnc.Element;
+import com.tailf.jnc.JNCException;
+import com.tailf.jnc.NetconfSession;
+import com.tailf.jnc.XMLParser;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationEditor;
+import org.springframework.util.ResourceUtils;
+import org.xml.sax.InputSource;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+class NetconfConfigurationEditorTest {
+
+ @Mock
+ private NetconfSession session;
+ @Mock
+ private NetconfSessionHelper netconfSessionHelper;
+
+ private NetconfConfigurationEditor editor;
+
+ @BeforeEach
+ void setUp() throws IOException, JNCException {
+ initMocks(this);
+ NetconfConnectionParams params = null;
+ Mockito.when(netconfSessionHelper.createNetconfSession(params)).thenReturn(session);
+ editor = new NetconfConfigurationEditor(params, netconfSessionHelper);
+ }
+
+ @Test
+ void testShouldEditConfigSuccessfully() throws IOException, JNCException {
+ byte[] bytes =
+ Files.readAllBytes(ResourceUtils.getFile("classpath:updatedConfig.xml").toPath());
+ Element editConfigXml = new XMLParser().parse(new InputSource(new ByteArrayInputStream(bytes)));
+
+ editor.editConfig(editConfigXml);
+
+ verify(session).editConfig(editConfigXml);
+ }
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java
new file mode 100644
index 0000000..a0a15b9
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java
@@ -0,0 +1,94 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.tailf.jnc.Element;
+import com.tailf.jnc.JNCException;
+import com.tailf.jnc.NetconfSession;
+import com.tailf.jnc.NodeSet;
+import java.io.IOException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+class NetconfConfigurationReaderTest {
+
+ private static final String NETCONF_MODEL_PATH = "";
+ private static final String EXPECTED_STRING_XML = "<?xml version=\"1.0\"?>";
+ private NetconfConfigurationReader reader;
+
+ @Mock
+ private NetconfSession netconfSession;
+
+ @Mock
+ private NetconfSessionHelper netconfSessionHelper;
+
+ @Mock
+ private NodeSet nodeSet;
+
+ @Mock
+ private Element element;
+
+ @BeforeEach
+ void setUp() throws IOException, JNCException {
+ MockitoAnnotations.initMocks(this);
+ NetconfConnectionParams params = null;
+ Mockito.when(netconfSessionHelper.createNetconfSession(params)).thenReturn(netconfSession);
+ reader = new NetconfConfigurationReader(params, netconfSessionHelper);
+ }
+
+ @Test
+ void properlyReadXML() throws IOException, JNCException {
+ when(netconfSession.getConfig()).thenReturn(nodeSet);
+ when(nodeSet.toXMLString()).thenReturn(EXPECTED_STRING_XML);
+
+ String result = reader.getRunningConfig();
+
+ verify(netconfSession).getConfig();
+ verify(nodeSet).toXMLString();
+ assertThat(result).isEqualTo(EXPECTED_STRING_XML);
+ }
+
+ @Test
+ void shouldProperlyReadXmlByName() throws IOException, JNCException {
+ when(netconfSession.getConfig("/sample:test")).thenReturn(nodeSet);
+ when(nodeSet.first()).thenReturn(element);
+ when(element.toXMLString()).thenReturn(EXPECTED_STRING_XML);
+
+ String result = reader.getRunningConfig("/sample:test");
+
+ verify(netconfSession).getConfig("/sample:test");
+ verify(nodeSet, times(2)).first();
+ verify(element).toXMLString();
+
+ assertThat(result).isEqualTo(EXPECTED_STRING_XML);
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java
new file mode 100644
index 0000000..6da6572
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java
@@ -0,0 +1,102 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. 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.netconfsimulator.netconfcore.configuration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.tailf.jnc.Element;
+import com.tailf.jnc.JNCException;
+import java.io.IOException;
+import java.nio.file.Files;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.util.ResourceUtils;
+
+class NetconfConfigurationServiceTest {
+
+ @Mock
+ NetconfConfigurationReader reader;
+
+ @Mock
+ NetconfConfigurationEditor editor;
+
+ @InjectMocks
+ NetconfConfigurationService service;
+
+ private static String CURRENT_CONFIG_XML_STRING =
+ "<config xmlns=\"http://onap.org/pnf-simulator\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+ + " <itemValue1>100</itemValue1>\n"
+ + " <itemValue2>200</itemValue2>\n"
+ + "</config>\n";
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ }
+
+ @Test
+ void testShouldReturnCorrectCurrentConfiguration() throws IOException, JNCException {
+ String expectedConfiguration = CURRENT_CONFIG_XML_STRING;
+ when(reader.getRunningConfig()).thenReturn(CURRENT_CONFIG_XML_STRING);
+
+ String actualCurrentConfiguration = service.getCurrentConfiguration();
+
+ assertThat(actualCurrentConfiguration).isEqualToIgnoringCase(expectedConfiguration);
+ }
+
+ @Test
+ void testShouldThrowExceptionWhenCurrentConfigurationDoesNotExists() throws IOException, JNCException{
+ when(reader.getRunningConfig()).thenThrow(JNCException.class);
+
+ assertThatThrownBy(() -> service.getCurrentConfiguration()).isInstanceOf(JNCException.class);
+ }
+
+ @Test
+ void testShouldEditConfigurationSuccessfully() throws IOException, JNCException{
+ byte[] bytes =
+ Files.readAllBytes(ResourceUtils.getFile("classpath:updatedConfig.xml").toPath());
+ MockMultipartFile editConfigXmlContent = new MockMultipartFile("editConfigXml", bytes);
+ ArgumentCaptor<Element> elementCaptor = ArgumentCaptor.forClass(Element.class);
+ doNothing().when(editor).editConfig(elementCaptor.capture());
+
+ service.editCurrentConfiguration(editConfigXmlContent);
+
+ assertThat(elementCaptor.getValue().toXMLString()).isEqualTo(CURRENT_CONFIG_XML_STRING);
+ }
+
+ @Test
+ void testShouldRaiseExceptionWhenMultipartFileIsInvalidXmlFile() throws IOException {
+ byte[] bytes =
+ Files.readAllBytes(ResourceUtils.getFile("classpath:invalidXmlFile.xml").toPath());
+ MockMultipartFile editConfigXmlContent = new MockMultipartFile("editConfigXml", bytes);
+
+ assertThatThrownBy(() -> service.editCurrentConfiguration(editConfigXmlContent)).isInstanceOf(JNCException.class);
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java
new file mode 100644
index 0000000..a10876b
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.netconfcore.model;
+
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.web.multipart.MultipartFile;
+
+class NetconfModelLoaderServiceTest {
+
+ @Mock
+ private HttpClient httpClient;
+
+ private NetconfModelLoaderService modelLoaderService;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.initMocks(this);
+ modelLoaderService = new NetconfModelLoaderService(httpClient);
+ }
+
+
+ @Test
+ void shouldSendMultipartToServer() throws IOException {
+ //given
+ String loadModelAddress = modelLoaderService.getBackendAddress();
+ makeMockClientReturnStatusOk(httpClient, HttpPost.class);
+ ArgumentCaptor<HttpPost> postArgumentCaptor = ArgumentCaptor.forClass(HttpPost.class);
+ MultipartFile yangMmodel = mock(MultipartFile.class);
+ MultipartFile initialConfig = mock(MultipartFile.class);
+ String moduleName = "moduleName";
+ when(yangMmodel.getInputStream()).thenReturn(getEmptyImputStream());
+ when(initialConfig.getInputStream()).thenReturn(getEmptyImputStream());
+
+ //when
+ LoadModelResponse response = modelLoaderService.loadYangModel(yangMmodel, initialConfig, moduleName);
+
+ //then
+ verify(httpClient).execute(postArgumentCaptor.capture());
+ HttpPost sentPost = postArgumentCaptor.getValue();
+ assertThat(response.getStatusCode()).isEqualTo(200);
+ assertThat(response.getMessage()).isEqualTo("");
+ assertThat(sentPost.getURI().toString()).isEqualTo(loadModelAddress);
+ assertThat(sentPost.getEntity().getContentType().getElements()[0].getName()).isEqualTo("multipart/form-data");
+ }
+
+ @Test
+ void shouldSendDeleteRequestToServer() throws IOException {
+ //given
+ String yangModelName = "sampleModel";
+ String deleteModelAddress = modelLoaderService.getDeleteAddress(yangModelName);
+ makeMockClientReturnStatusOk(httpClient, HttpDelete.class);
+ ArgumentCaptor<HttpDelete> deleteArgumentCaptor = ArgumentCaptor.forClass(HttpDelete.class);
+
+ //when
+ LoadModelResponse response = modelLoaderService.deleteYangModel(yangModelName);
+
+ //then
+ verify(httpClient).execute(deleteArgumentCaptor.capture());
+ HttpDelete sendDelete = deleteArgumentCaptor.getValue();
+ assertThat(response.getStatusCode()).isEqualTo(200);
+ assertThat(response.getMessage()).isEqualTo("");
+ assertThat(sendDelete.getURI().toString()).isEqualTo(deleteModelAddress);
+ }
+
+ private void makeMockClientReturnStatusOk(HttpClient client,
+ Class<? extends HttpRequestBase> httpMethodClass) throws IOException {
+ HttpResponse httpResponse = mock(HttpResponse.class);
+ StatusLine mockStatus = mock(StatusLine.class);
+ HttpEntity mockEntity = mock(HttpEntity.class);
+
+ when(client.execute(any(httpMethodClass))).thenReturn(httpResponse);
+ when(httpResponse.getStatusLine()).thenReturn(mockStatus);
+ when(mockStatus.getStatusCode()).thenReturn(200);
+ when(httpResponse.getEntity()).thenReturn(mockEntity);
+ when(mockEntity.getContent()).thenReturn(getEmptyImputStream());
+ }
+
+ private InputStream getEmptyImputStream() {
+ return new ByteArrayInputStream("".getBytes());
+ }
+
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java
new file mode 100644
index 0000000..c1484d4
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.websocket;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.util.Map;
+import java.util.Optional;
+import javax.websocket.CloseReason;
+import javax.websocket.EndpointConfig;
+import javax.websocket.RemoteEndpoint;
+import javax.websocket.Session;
+import org.apache.kafka.common.Metric;
+import org.apache.kafka.common.MetricName;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.onap.netconfsimulator.kafka.listener.KafkaListenerEntry;
+import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler;
+import org.onap.netconfsimulator.websocket.message.NetconfMessageListener;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.listener.AbstractMessageListenerContainer;
+
+import org.springframework.kafka.listener.ContainerProperties;
+import org.springframework.kafka.listener.GenericMessageListener;
+
+class NetconfEndpointTest {
+
+
+ @Mock
+ private KafkaListenerHandler kafkaListenerHandler;
+
+ @Mock
+ private Session session;
+
+ @Mock
+ private EndpointConfig endpointConfig;
+
+ @Mock
+ private RemoteEndpoint.Basic remoteEndpoint;
+
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ }
+
+
+ @Test
+ void shouldCreateKafkaListenerWhenClientInitializeConnection() {
+ NetconfEndpoint netconfEndpoint = new NetconfEndpoint(kafkaListenerHandler);
+ AbstractMessageListenerContainer abstractMessageListenerContainer = getListenerContainer();
+ when(session.getBasicRemote()).thenReturn(remoteEndpoint);
+ KafkaListenerEntry kafkaListenerEntry = new KafkaListenerEntry("sampleGroupId",
+ abstractMessageListenerContainer);
+ when(kafkaListenerHandler.createKafkaListener(any(NetconfMessageListener.class), eq("config")))
+ .thenReturn(kafkaListenerEntry);
+
+ netconfEndpoint.onOpen(session, endpointConfig);
+
+ assertThat(netconfEndpoint.getEntry().get().getClientId()).isEqualTo("sampleGroupId");
+ assertThat(netconfEndpoint.getEntry().get().getListenerContainer()).isEqualTo(abstractMessageListenerContainer);
+
+ verify(abstractMessageListenerContainer).start();
+ }
+
+
+ @Test
+ void shouldCloseListenerWhenClientDisconnects() {
+ NetconfEndpoint netconfEndpoint = new NetconfEndpoint(kafkaListenerHandler);
+ AbstractMessageListenerContainer abstractMessageListenerContainer = getListenerContainer();
+ netconfEndpoint.setEntry( Optional.of(new KafkaListenerEntry("sampleGroupId", abstractMessageListenerContainer)) );
+
+ netconfEndpoint.onClose(session, mock(CloseReason.class));
+
+ verify(abstractMessageListenerContainer).stop();
+ }
+
+ class TestAbstractMessageListenerContainer extends AbstractMessageListenerContainer {
+
+
+ TestAbstractMessageListenerContainer(ContainerProperties containerProperties) {
+ super(mock(ConsumerFactory.class),containerProperties);
+ }
+
+ @Override
+ protected void doStart() {
+
+ }
+
+ @Override
+ protected void doStop(Runnable callback) {
+
+ }
+
+ @Override
+ public Map<String, Map<MetricName, ? extends Metric>> metrics() {
+ return null;
+ }
+ }
+
+ private AbstractMessageListenerContainer getListenerContainer() {
+ ContainerProperties containerProperties = new ContainerProperties("config");
+ containerProperties.setGroupId("sample");
+ containerProperties.setMessageListener(mock(GenericMessageListener.class));
+ TestAbstractMessageListenerContainer testAbstractMessageListenerContainer = new TestAbstractMessageListenerContainer(
+ containerProperties);
+ return spy(testAbstractMessageListenerContainer);
+ }
+}
diff --git a/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java b/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java
new file mode 100644
index 0000000..bb040d1
--- /dev/null
+++ b/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. 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.netconfsimulator.websocket.message;
+
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.io.IOException;
+import javax.websocket.EncodeException;
+import javax.websocket.RemoteEndpoint;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.onap.netconfsimulator.kafka.model.KafkaMessage;
+
+
+class NetconfMessageListenerTest {
+
+ private static final ConsumerRecord<String, String> KAFKA_RECORD = new ConsumerRecord<>("sampleTopic", 0, 0,
+ "sampleKey", "sampleValue");
+
+ @Mock
+ private RemoteEndpoint.Basic remoteEndpoint;
+
+ @InjectMocks
+ private NetconfMessageListener netconfMessageListener;
+
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ }
+
+
+ @Test
+ void shouldProperlyParseAndSendConsumerRecord() throws IOException, EncodeException {
+ netconfMessageListener.onMessage(KAFKA_RECORD);
+
+ verify(remoteEndpoint).sendObject(any(KafkaMessage.class));
+ }
+
+
+
+ @Test
+ void shouldNotPropagateEncodeException() throws IOException, EncodeException {
+ doThrow(new EncodeException("","")).when(remoteEndpoint).sendObject(any(KafkaMessage.class));
+
+ netconfMessageListener.onMessage(KAFKA_RECORD);
+ }
+}
diff --git a/netconfsimulator/src/test/resources/application-it.properties b/netconfsimulator/src/test/resources/application-it.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/netconfsimulator/src/test/resources/application-it.properties
diff --git a/netconfsimulator/src/test/resources/initialConfig.xml b/netconfsimulator/src/test/resources/initialConfig.xml
new file mode 100644
index 0000000..f28a1a0
--- /dev/null
+++ b/netconfsimulator/src/test/resources/initialConfig.xml
@@ -0,0 +1,23 @@
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. 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=========================================================
+ -->
+
+<config2 xmlns="http://onap.org/newyangmodel">
+ <item1>100</item1>
+</config2>
diff --git a/netconfsimulator/src/test/resources/invalidXmlFile.xml b/netconfsimulator/src/test/resources/invalidXmlFile.xml
new file mode 100644
index 0000000..3debd8c
--- /dev/null
+++ b/netconfsimulator/src/test/resources/invalidXmlFile.xml
@@ -0,0 +1,23 @@
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. 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=========================================================
+ -->
+
+<config xmlns="http://onap.org/pnf-simulator" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <itemValue1>100</itemValue1>
+<config>
diff --git a/netconfsimulator/src/test/resources/newYangModel.yang b/netconfsimulator/src/test/resources/newYangModel.yang
new file mode 100644
index 0000000..bbe66c3
--- /dev/null
+++ b/netconfsimulator/src/test/resources/newYangModel.yang
@@ -0,0 +1,8 @@
+module newyangmodel {
+ namespace "http://onap.org/newyangmodel";
+ prefix config2;
+ container config2 {
+ config true;
+ leaf item1 {type uint32;}
+ }
+}
diff --git a/netconfsimulator/src/test/resources/updatedConfig.xml b/netconfsimulator/src/test/resources/updatedConfig.xml
new file mode 100644
index 0000000..628a710
--- /dev/null
+++ b/netconfsimulator/src/test/resources/updatedConfig.xml
@@ -0,0 +1,24 @@
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. 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=========================================================
+ -->
+
+<config xmlns="http://onap.org/pnf-simulator" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <itemValue1>100</itemValue1>
+ <itemValue2>200</itemValue2>
+</config>
diff --git a/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml b/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml
new file mode 100644
index 0000000..5bc0e42
--- /dev/null
+++ b/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml
@@ -0,0 +1,24 @@
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. 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=========================================================
+ -->
+
+<config xmlns="http://onap.org/pnf-simulator" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <itemValue1>500</itemValue1>
+ <itemValue2>1000</itemValue2>
+</config>