Skip to content

Commit 15e840a

Browse files
committed
Implemented get-data
- Per discussion on github, using Datastore enum: Juniper#54 (comment) - Using enum pass to function call too
1 parent 5720d52 commit 15e840a

File tree

7 files changed

+294
-5
lines changed

7 files changed

+294
-5
lines changed

Jenkinsfile

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import hudson.model.*
2+
3+
pipeline {
4+
5+
agent any
6+
7+
options {
8+
timestamps()
9+
timeout(time: 1, unit: "HOURS")
10+
}
11+
12+
environment {
13+
TMPDIR = "target"
14+
ARTIFACTID = readMavenPom().getArtifactId()
15+
GROUPID = readMavenPom().getGroupId()
16+
VERSION = readMavenPom().getVersion()
17+
BRANCH = "${GIT_BRANCH}".replaceAll("/", "-")
18+
MVN_OPTS = "--fail-at-end --threads 4"
19+
}
20+
21+
tools {
22+
maven "Maven 3.6.3"
23+
jdk "OpenJDK 11 (Latest)"
24+
}
25+
26+
stages {
27+
stage("Initialize") {
28+
steps {
29+
chuckNorris()
30+
echo sh(returnStdout: true, script: "env")
31+
notifyBitbucket0()
32+
}
33+
}
34+
35+
stage("Build & Install") {
36+
steps {
37+
// sh "cat ~/.m2/settings.xml" // For checking the default settings to ensure my mvn-settings-di2e-jenkins.xml is set right for DI2E.
38+
sh "mvn clean jacoco:prepare-agent install jacoco:report ${MVN_OPTS}"
39+
jacoco()
40+
}
41+
}
42+
43+
stage("Scan") {
44+
steps {
45+
script {
46+
try {
47+
withSonarQubeDI2E()
48+
} catch (err) {
49+
echo "Error in sonarqube upload:"
50+
echo err.getMessage()
51+
}
52+
}
53+
}
54+
}
55+
}
56+
post {
57+
always {
58+
junit "**/target/surefire-reports/*.xml"
59+
archiveArtifacts artifacts: "**/target/*.jar",
60+
fingerprint: true
61+
notifyBitbucket0()
62+
}
63+
success {
64+
script {
65+
nexusArtifactUploader0()
66+
}
67+
}
68+
}
69+
}
70+
71+
def withSonarQubeDI2E() {
72+
withSonarQubeEnv('Sonarqube Di2e Server') {
73+
script {
74+
def sonarScanner = tool name: 'SonarQube Scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
75+
// Sonarqube token 8d28335e817bb96f7dc2a1b3f56dcf1d2c03bb6a
76+
sh "mvn sonar:sonar --activate-profiles sonarqube,site-reports -D sonar.branch.name=${BRANCH} -D sonar.projectKey=RMBN-NETCONF-Java ${MVN_OPTS}"
77+
}
78+
}
79+
}
80+
81+
def nexusArtifactUploader0() {
82+
nexusArtifactUploader artifacts: [
83+
[artifactId: "${ARTIFACTID}", file: "pom.xml", type: "pom"],
84+
[artifactId: "${ARTIFACTID}", file: "target/${ARTIFACTID}-${VERSION}.jar", type: "jar"],
85+
[artifactId: "${ARTIFACTID}", classifier: "sources", file: "target/${ARTIFACTID}-${VERSION}-sources.jar", type: "jar"],
86+
[artifactId: "${ARTIFACTID}", classifier: "javadoc", file: "target/${ARTIFACTID}-${VERSION}-javadoc.jar", type: "jar"]
87+
],
88+
credentialsId: "687110ca-29bc-48c6-b35a-50b6040f1260",
89+
groupId: "${GROUPID}",
90+
nexusUrl: "nexus.di2e.net/nexus3",
91+
nexusVersion: "nexus3",
92+
protocol: "https",
93+
repository: "Public_DI2E_Maven",
94+
version: "${VERSION}"
95+
}
96+
97+
def notifyBitbucket0() {
98+
notifyBitbucket commitSha1: "${GIT_COMMIT}",
99+
considerUnstableAsSuccess: false,
100+
credentialsId: "b901ff19-3484-442d-bc11-f6b3f2be7d26",
101+
disableInprogressNotification: false,
102+
ignoreUnverifiedSSLPeer: false,
103+
includeBuildNumberInKey: false,
104+
prependParentProjectKey: false,
105+
projectKey: "",
106+
stashServerBaseUrl: "https://bitbucket.di2e.net"
107+
}

pom.xml

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<groupId>net.juniper.netconf</groupId>
99
<artifactId>netconf-java</artifactId>
10-
<version>2.1.1.6-SNAPSHOT</version>
10+
<version>2.1.1.6.7</version>
1111
<packaging>jar</packaging>
1212

1313
<properties>
@@ -143,9 +143,89 @@
143143
</execution>
144144
</executions>
145145
</plugin>
146+
<plugin>
147+
<groupId>org.sonarsource.scanner.maven</groupId>
148+
<artifactId>sonar-maven-plugin</artifactId>
149+
<version>3.7.0.1746</version>
150+
</plugin>
151+
<plugin>
152+
<groupId>org.jacoco</groupId>
153+
<artifactId>jacoco-maven-plugin</artifactId>
154+
<version>0.8.7</version>
155+
<executions>
156+
<execution>
157+
<goals>
158+
<goal>prepare-agent</goal>
159+
</goals>
160+
</execution>
161+
<execution>
162+
<id>report</id>
163+
<phase>prepare-package</phase>
164+
<goals>
165+
<goal>report</goal>
166+
</goals>
167+
</execution>
168+
</executions>
169+
</plugin>
170+
<plugin>
171+
<groupId>pl.project13.maven</groupId>
172+
<artifactId>git-commit-id-plugin</artifactId>
173+
<version>4.0.3</version>
174+
<executions>
175+
<execution>
176+
<id>get-the-git-infos</id>
177+
<goals>
178+
<goal>revision</goal>
179+
</goals>
180+
<phase>initialize</phase>
181+
</execution>
182+
</executions>
183+
<configuration>
184+
<generateGitPropertiesFile>true</generateGitPropertiesFile>
185+
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
186+
<includeOnlyProperties>
187+
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
188+
<includeOnlyProperty>^git.branch$</includeOnlyProperty>
189+
<includeOnlyProperty>^git.remote.origin.url$</includeOnlyProperty>
190+
<IncludeOnlyProperty>^git.commit.time$</IncludeOnlyProperty>
191+
<includeOnlyProperty>^git.commit.message.(short|full)$</includeOnlyProperty>
192+
<includeOnlyProperty>^git.commit.user.(name|email)$</includeOnlyProperty>
193+
<includeOnlyProperty>^git.tags$</includeOnlyProperty>
194+
<includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
195+
</includeOnlyProperties>
196+
<verbose>true</verbose> <!-- Also using maven-antrun to output info so it appears after install -->
197+
<commitIdGenerationMode>full</commitIdGenerationMode>
198+
<injectAllReactorProjects>true</injectAllReactorProjects>
199+
</configuration>
200+
</plugin>
146201
</plugins>
147202
</build>
148203

204+
<profiles>
205+
<profile>
206+
<id>sonarqube</id>
207+
<properties>
208+
<!--suppress UnresolvedMavenProperty -->
209+
<sonar.host.url>${sonar.server.host.url}</sonar.host.url>
210+
<!--suppress UnresolvedMavenProperty -->
211+
<sonar.login>${sonar.server.login}</sonar.login>
212+
</properties>
213+
</profile>
214+
<profile>
215+
<id>site-reports</id>
216+
<activation>
217+
<property>
218+
<name>testmode</name>
219+
<value>all</value>
220+
</property>
221+
</activation>
222+
<properties>
223+
<exclude.tests>org.junit.Ignore</exclude.tests>
224+
<ignoreFailtest>true</ignoreFailtest>
225+
</properties>
226+
</profile>
227+
</profiles>
228+
149229
<reporting>
150230
<plugins>
151231
<plugin>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package net.juniper.netconf;
2+
3+
public interface IntegrationTest {
4+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package net.juniper.netconf;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.junit.Test;
5+
import org.junit.experimental.categories.Category;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
@Slf4j
10+
@Category(IntegrationTest.class)
11+
public class NetconfSessionIT {
12+
13+
@Test //Expectation is no exception thrown.
14+
public void testNetconfSessionWithKey() throws Exception {
15+
try (Device device = Device.builder()
16+
.hostName("localhost")
17+
.userName(System.getProperty("user.name"))
18+
.keyBasedAuthentication(true)
19+
.pemKeyFile("/home/vagrant/.ssh/netconf_rsa")
20+
.strictHostKeyChecking(false)
21+
.build()) {
22+
device.connect();
23+
XML xml = device.getRunningConfig();
24+
assertThat(xml).isNotNull();
25+
assertThat(String.valueOf(xml).trim()).isNotBlank();
26+
log.debug("XML:\n{}", xml);
27+
}
28+
}
29+
}

src/main/java/net/juniper/netconf/Device.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import lombok.NonNull;
1818
import lombok.ToString;
1919
import lombok.extern.slf4j.Slf4j;
20+
import net.juniper.netconf.element.Datastore;
2021
import net.juniper.netconf.element.Hello;
2122
import org.w3c.dom.Document;
2223
import org.xml.sax.SAXException;
@@ -838,14 +839,41 @@ public XML getRunningConfig(String configTree) throws SAXException,
838839
return this.netconfSession.getRunningConfig(configTree);
839840
}
840841

841-
public XML getRunningConfigAndState(String filter) throws IOException, SAXException {
842+
/**
843+
* Retrieve the running configuration, or part of the configuration.
844+
*
845+
* @param xpathFilter example <code><filter xmlns:model='urn:path:for:my:model' select='/model:*'></filter></code>
846+
* @return configuration data as XML object.
847+
* @throws java.io.IOException If there are errors communicating with the netconf server.
848+
* @throws org.xml.sax.SAXException If there are errors parsing the XML reply.
849+
*/
850+
public XML getRunningConfigAndState(String xpathFilter) throws IOException, SAXException {
842851
if (netconfSession == null) {
843852
throw new IllegalStateException("Cannot execute RPC, you need to " +
844853
"establish a connection first.");
845854
}
846-
return this.netconfSession.getRunningConfigAndState(filter);
855+
return this.netconfSession.getRunningConfigAndState(xpathFilter);
847856
}
848857

858+
859+
/**
860+
* Run the <get-data> call to netconf server and retrieve data as an XML.
861+
*
862+
* @param xpathFilter example <code><filter xmlns:model='urn:path:for:my:model' select='/model:*'></filter></code>
863+
* @param datastore running, startup, candidate, or operational
864+
* @return configuration data as XML object.
865+
* @throws java.io.IOException If there are errors communicating with the netconf server.
866+
* @throws org.xml.sax.SAXException If there are errors parsing the XML reply.
867+
*/
868+
public XML getData(String xpathFilter, @NonNull Datastore datastore) throws IOException, SAXException {
869+
if (netconfSession == null) {
870+
throw new IllegalStateException("Cannot execute RPC, you need to " +
871+
"establish a connection first.");
872+
}
873+
return this.netconfSession.getData(xpathFilter, datastore);
874+
}
875+
876+
849877
/**
850878
* Retrieve the whole candidate configuration.
851879
*

src/main/java/net/juniper/netconf/NetconfSession.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.jcraft.jsch.JSchException;
1515
import lombok.NonNull;
1616
import lombok.extern.slf4j.Slf4j;
17+
import net.juniper.netconf.element.Datastore;
1718
import net.juniper.netconf.element.Hello;
1819
import net.juniper.netconf.element.RpcReply;
1920
import org.w3c.dom.Document;
@@ -159,6 +160,8 @@ private void sendRpcRequest(String rpc) throws IOException {
159160
// RFC conformance for XML type, namespaces and message ids for RPCs
160161
messageId++;
161162
rpc = rpc.replace("<rpc>", "<rpc" + getRpcAttributes() + " message-id=\"" + messageId + "\">").trim();
163+
rpc = rpc.replace("<datastore>", "<datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">");
164+
rpc = rpc.replace("<get-data>", "<get-data xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-nmda\">");
162165
if (!rpc.contains(NetconfConstants.XML_VERSION)) {
163166
rpc = NetconfConstants.XML_VERSION + rpc;
164167
}
@@ -301,17 +304,31 @@ private String getConfig(String configTree) throws IOException {
301304
return lastRpcReply;
302305
}
303306

304-
public XML getRunningConfigAndState(String filter) throws IOException, SAXException {
307+
public XML getRunningConfigAndState(String xpathFilter) throws IOException, SAXException {
305308
String rpc = "<rpc>" +
306309
"<get>" +
307-
(filter == null ? "" : filter) +
310+
(xpathFilter == null ? "" : xpathFilter) +
308311
"</get>" +
309312
"</rpc>" +
310313
NetconfConstants.DEVICE_PROMPT;
311314
setLastRpcReply(getRpcReply(rpc));
312315
return convertToXML(lastRpcReply);
313316
}
314317

318+
public XML getData(String xpathFilter, @NonNull Datastore datastore)
319+
throws IOException, SAXException {
320+
321+
String rpc = "<rpc>" +
322+
"<get-data>" +
323+
"<datastore>ds:" + datastore.getTag() + "</datastore>" +
324+
(xpathFilter == null ? "" : xpathFilter) +
325+
"</get-data>" +
326+
"</rpc>" +
327+
NetconfConstants.DEVICE_PROMPT;
328+
lastRpcReply = getRpcReply(rpc);
329+
return convertToXML(lastRpcReply);
330+
}
331+
315332
private String getConfig(String target, String configTree)
316333
throws IOException {
317334

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package net.juniper.netconf.element;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
7+
/**
8+
* Datastore
9+
* <p>
10+
* As defined by RFC-8342.
11+
* See https://datatracker.ietf.org/doc/html/rfc8342#section-5
12+
*/
13+
@Slf4j
14+
@Getter
15+
@RequiredArgsConstructor
16+
public enum Datastore {
17+
RUNNING("running"),
18+
CANDIDATE("candidate"),
19+
STARTUP("startup"),
20+
INTENDED("intended"),
21+
OPERATIONAL("operational");
22+
23+
public final String tag;
24+
}

0 commit comments

Comments
 (0)