2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Nokia. All rights reserved.
6 * =============================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.appc.adapter.chef.impl;
23 import static com.google.common.collect.Maps.immutableEntry;
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
26 import static org.mockito.BDDMockito.given;
28 import com.google.common.collect.ImmutableMap;
29 import com.google.common.collect.ImmutableMap.Builder;
31 import java.util.Map.Entry;
32 import org.apache.http.HttpStatus;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.mockito.InjectMocks;
37 import org.mockito.Mock;
38 import org.mockito.runners.MockitoJUnitRunner;
39 import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory;
40 import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient;
41 import org.onap.appc.adapter.chef.chefclient.api.ChefResponse;
42 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
43 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
45 @RunWith(MockitoJUnitRunner.class)
46 public class ChefAdapterImplVNFCOperationsTest {
48 private static final String CHEF_END_POINT = "https://localhost/organizations/onap";
49 private static final String USERNAME = "testclient";
50 private static final String ORGANIZATIONS = "onap";
51 private static final String SERVER_ADDRESS = "localhost";
52 private static final String CLIENT_PRIVATE_KEY_PATH = "/opt/onap/appc/chef/localhost/onap/testclient.pem";
53 private static final String RESULT_CODE_ATTR_KEY = "chefServerResult.code";
54 private static final String RESULT_MESSAGE_ATTR_KEY = "chefServerResult.message";
55 private static final String FAILURE_STATUS = "failure";
56 private static final String SUCCESS_STATUS = "success";
57 private static final String CHEF_ADAPTER_ERROR_PREFIX = "Chef Adapter error:";
58 private static final String ENV_PARAM_KEY = "Environment";
59 private static final String ENV_JSON_VALUE = "{name:envName}";
62 private PrivateKeyChecker privateKeyChecker;
64 private ChefApiClientFactory chefApiClientFactory;
66 private ChefApiClient chefApiClient;
69 private ChefAdapterFactory chefAdapterFactory;
70 private SvcLogicContext svcLogicContext;
74 svcLogicContext = new SvcLogicContext();
78 public void vnfcEnvironment_shouldSkipEnvironmentCreation_whenEnvParamIsEmpty() throws SvcLogicException {
80 Map<String, String> params = givenInputParams(immutableEntry(ENV_PARAM_KEY, ""));
83 chefAdapterFactory.create().vnfcEnvironment(params, svcLogicContext);
86 assertThat(svcLogicContext.getStatus()).isEqualTo(SUCCESS_STATUS);
87 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
88 .isEqualTo(Integer.toString(HttpStatus.SC_OK));
89 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).isEqualTo("Skip Environment block ");
93 public void vnfcEnvironment_shouldCreateNewEnvironment_forEnvParam_whenRequestedEnvDoesNotExist()
94 throws SvcLogicException {
96 String expectedErrorMessage = "New Environment Created";
97 Map<String, String> params = givenInputParams(immutableEntry(ENV_PARAM_KEY, ENV_JSON_VALUE));
98 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
99 given(chefApiClientFactory.create(CHEF_END_POINT, ORGANIZATIONS, USERNAME,
100 CLIENT_PRIVATE_KEY_PATH)).willReturn(chefApiClient);
101 given(chefApiClient.put("/environments/" + "envName", ENV_JSON_VALUE))
102 .willReturn(ChefResponse.create(HttpStatus.SC_NOT_FOUND, ""));
103 given(chefApiClient.post("/environments", ENV_JSON_VALUE))
104 .willReturn(ChefResponse.create(HttpStatus.SC_CREATED, expectedErrorMessage));
107 chefAdapterFactory.create().vnfcEnvironment(params, svcLogicContext);
110 assertThat(svcLogicContext.getStatus()).isEqualTo(SUCCESS_STATUS);
111 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
112 .isEqualTo(Integer.toString(HttpStatus.SC_CREATED));
113 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).isEqualTo(expectedErrorMessage);
117 public void vnfcEnvironment_shouldNotAttemptEnvCreation_andThrowException_whenPrivateKeyCheckFails() {
119 String expectedErrorMsg = "Cannot find the private key in the APPC file system, please load the private key to ";
120 Map<String, String> params = givenInputParams(immutableEntry(ENV_PARAM_KEY, ENV_JSON_VALUE));
121 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(false);
124 assertThatExceptionOfType(SvcLogicException.class)
125 .isThrownBy(() -> chefAdapterFactory.create().vnfcEnvironment(params, svcLogicContext))
126 .withMessage(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMsg + CLIENT_PRIVATE_KEY_PATH);
128 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
129 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
130 .isEqualTo(Integer.toString(HttpStatus.SC_INTERNAL_SERVER_ERROR));
131 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
132 .isEqualTo(expectedErrorMsg + CLIENT_PRIVATE_KEY_PATH);
136 public void vnfcEnvironment_shouldNotAttemptEnvCreation_andHandleJSONException_whenJSONParamsAreMalformed() {
138 String expectedErrorMessage = "Error posting request due to invalid JSON block: ";
139 Map<String, String> params = givenInputParams(immutableEntry(ENV_PARAM_KEY, "MALFORMED_JSON"));
140 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
143 assertThatExceptionOfType(SvcLogicException.class)
144 .isThrownBy(() -> chefAdapterFactory.create().vnfcEnvironment(params, svcLogicContext))
145 .withMessageStartingWith(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMessage);
147 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
148 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
149 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
150 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
151 .startsWith(expectedErrorMessage);
155 public void vnfcEnvironment_shouldNotAttemptEnvCreation_andHandleException_whenExceptionOccursDuringExecution() {
157 String expectedErrorMessage = "Error posting request: ";
158 Map<String, String> params = givenInputParams(immutableEntry(ENV_PARAM_KEY, ENV_JSON_VALUE));
159 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
160 given(chefApiClientFactory.create(CHEF_END_POINT, ORGANIZATIONS, USERNAME,
161 CLIENT_PRIVATE_KEY_PATH)).willThrow(new NullPointerException("Null value encountered"));
164 assertThatExceptionOfType(SvcLogicException.class)
165 .isThrownBy(() -> chefAdapterFactory.create().vnfcEnvironment(params, svcLogicContext))
166 .withMessage(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMessage + "Null value encountered");
168 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
169 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
170 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
171 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).startsWith(expectedErrorMessage);
175 public void vnfcNodeObjects_shouldUpdateNodeObjects_andSetCodeAndMessageFromLastSuccessfulResponseInSvcLogicContext()
176 throws SvcLogicException {
178 ChefResponse firstNodeResponse = ChefResponse.create(HttpStatus.SC_OK, "firstMessage");
179 ChefResponse secondNodeResponse = ChefResponse.create(HttpStatus.SC_OK, "secondMessage");
180 int expectedHttpStatus = HttpStatus.SC_OK;
181 String expectedMessage = "secondMessage";
183 assertNodeObjectsAreUpdatedFor(firstNodeResponse, secondNodeResponse, expectedHttpStatus, expectedMessage);
187 public void vnfcNodeObjects_shouldStopProcessingNodeObjectUpdates_whenFirstReturnedResponseIsOtherThan_200()
188 throws SvcLogicException {
189 ChefResponse firstNodeResponse = ChefResponse.create(HttpStatus.SC_ACCEPTED, "firstMessage");
190 ChefResponse secondNodeResponse = ChefResponse.create(HttpStatus.SC_OK, "secondMessage");
191 int expectedHttpStatus = HttpStatus.SC_ACCEPTED;
192 String expectedMessage = "firstMessage";
194 assertNodeObjectsAreUpdatedFor(firstNodeResponse, secondNodeResponse, expectedHttpStatus, expectedMessage);
197 public void assertNodeObjectsAreUpdatedFor(ChefResponse firstNodeResponse, ChefResponse secondNodeResponse,
198 int expectedHttpStatus, String expectedMessage) throws SvcLogicException {
200 Map<String, String> params = givenInputParams(
201 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]"),
202 immutableEntry("Node", "{name:nodeName}"));
204 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
205 given(chefApiClientFactory.create(CHEF_END_POINT, ORGANIZATIONS, USERNAME,
206 CLIENT_PRIVATE_KEY_PATH)).willReturn(chefApiClient);
207 given(chefApiClient.put("/nodes/" + "test1.vnf_b.onap.com", "{\"name\":\"test1.vnf_b.onap.com\"}"))
208 .willReturn(firstNodeResponse);
210 .put("/nodes/" + "test2.vnf_b.onap.com", "{\"name\":\"test2.vnf_b.onap.com\"}"))
211 .willReturn(secondNodeResponse);
214 chefAdapterFactory.create().vnfcNodeobjects(params, svcLogicContext);
217 assertThat(svcLogicContext.getStatus()).isEqualTo(SUCCESS_STATUS);
218 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
219 .isEqualTo(Integer.toString(expectedHttpStatus));
220 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).isEqualTo(expectedMessage);
224 public void vnfcNodeObjects_shouldThrowSvcLogicException_whenNodeListParamIsEmpty() {
225 Map<String, String> params = givenInputParams(
226 immutableEntry("NodeList", ""),
227 immutableEntry("Node", "{name:nodeName}"));
228 checkMissingParamsAreValidated(params);
232 public void vnfcNodeObjects_shouldThrowSvcLogicException_whenNodeParamIsEmpty() {
233 Map<String, String> params = givenInputParams(
234 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]"),
235 immutableEntry("Node", ""));
236 checkMissingParamsAreValidated(params);
239 public void checkMissingParamsAreValidated(Map<String, String> params) {
241 String expectedErrorMsg = "Missing Mandatory param(s) Node , NodeList ";
244 assertThatExceptionOfType(SvcLogicException.class)
245 .isThrownBy(() -> chefAdapterFactory.create().vnfcNodeobjects(params, svcLogicContext))
246 .withMessage(CHEF_ADAPTER_ERROR_PREFIX + "Error posting request: " + expectedErrorMsg);
248 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
249 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
250 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
251 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
252 .isEqualTo("Error posting request: " + expectedErrorMsg);
256 public void vnfcNodeObjects_shouldNotUpdateNodes_andHandleJSONException_whenJSONParamsAreMalformed() {
258 Map<String, String> params = givenInputParams(
259 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]"),
260 immutableEntry("Node", "MALFORMED_JSON"));
261 String expectedErrorMessage = "Error posting request due to invalid JSON block: ";
262 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
265 assertThatExceptionOfType(SvcLogicException.class)
266 .isThrownBy(() -> chefAdapterFactory.create().vnfcNodeobjects(params, svcLogicContext))
267 .withMessageStartingWith(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMessage);
269 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
270 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
271 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
272 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
273 .startsWith(expectedErrorMessage);
277 public void vnfcPushJob_shouldUpdateSvcContextWithJobId_whenPushJobWasSuccessfullyCreatedWithCallbackUrl()
278 throws SvcLogicException {
279 Map<String, String> params = givenInputParams(
280 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]"),
281 immutableEntry("CallbackCapable", "true"),
282 immutableEntry("RequestId", "666"),
283 immutableEntry("CallbackUrl", "someURLForCallback"));
284 int expectedResponseStatus = HttpStatus.SC_CREATED;
285 String expectedResponseMessage = "jobs:666-9";
287 assertVnfcPushJobExecutionFor(params, buildJsonRequestWithCallback(), expectedResponseStatus,
288 expectedResponseMessage);
289 assertThat(svcLogicContext.getAttribute("jobID")).isEqualTo("666");
292 private String buildJsonRequestWithCallback() {
293 return "{" + "\"command\": \"chef-client\"," + "\"run_timeout\": 300," + "\"nodes\":"
294 + "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]" + "," + "\"env\": {\"RequestId\": \"" + "666"
295 + "\", \"CallbackUrl\": \""
296 + "someURLForCallback" + "\"}," + "\"capture_output\": true" + "}";
300 public void vnfcPushJob_shouldUpdateSvcContextWithJobId_whenPushJobWasSuccessfullyCreatedWithoutCallbackUrl()
301 throws SvcLogicException {
302 Map<String, String> params = givenInputParams(
303 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]"),
304 immutableEntry("RequestId", "666"));
305 int expectedResponseStatus = HttpStatus.SC_OK;
306 String expectedResponseMessage = "jobs:666-9";
308 assertVnfcPushJobExecutionFor(params, buildJsonRequestWithoutCallback(), expectedResponseStatus,
309 expectedResponseMessage);
310 assertThat(svcLogicContext.getAttribute("jobID")).isBlank();
313 private String buildJsonRequestWithoutCallback() {
314 return "{" + "\"command\": \"chef-client\"," + "\"run_timeout\": 300," + "\"nodes\":"
315 + "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]" + "," + "\"env\": {}," + "\"capture_output\": true"
319 public void assertVnfcPushJobExecutionFor(Map<String, String> params, String pushRequestWithCallback,
320 int expectedResponseStatus, String expectedResponseMessage) throws SvcLogicException {
322 given(chefApiClientFactory.create(CHEF_END_POINT, ORGANIZATIONS, USERNAME,
323 CLIENT_PRIVATE_KEY_PATH)).willReturn(chefApiClient);
324 given(chefApiClient.post("/pushy/jobs", pushRequestWithCallback))
325 .willReturn(ChefResponse.create(expectedResponseStatus, expectedResponseMessage));
328 chefAdapterFactory.create().vnfcPushJob(params, svcLogicContext);
331 assertThat(svcLogicContext.getStatus()).isEqualTo(SUCCESS_STATUS);
332 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
333 .isEqualTo(Integer.toString(expectedResponseStatus));
334 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).isEqualTo(expectedResponseMessage);
338 public void vnfcPushJob_shouldNotPushJob_andThrowException_whenNodeListParamIsEmpty() {
340 String expectedErrorMessage = "Error posting request: Missing Mandatory param(s) NodeList ";
341 Map<String, String> params = givenInputParams();
343 assertThatExceptionOfType(SvcLogicException.class)
344 .isThrownBy(() -> chefAdapterFactory.create().vnfcPushJob(params, svcLogicContext))
345 .withMessageStartingWith(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMessage);
347 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
348 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
349 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
350 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).isEqualTo(expectedErrorMessage);
354 public void fetchResults_shouldNotFetchResults_andThrowException_whenNodeListParamIsEmpty() {
356 String expectedErrorMessage = "Error posting request: Missing Mandatory param(s) NodeList ";
357 Map<String, String> params = givenInputParams();
359 assertThatExceptionOfType(SvcLogicException.class)
360 .isThrownBy(() -> chefAdapterFactory.create().fetchResults(params, svcLogicContext))
361 .withMessageStartingWith(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMessage);
363 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
364 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
365 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
366 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY)).isEqualTo(expectedErrorMessage);
370 public void fetchResults_shouldNotFetchResults_andThrowException_whenPrivateKeyCheckFails() {
372 Map<String, String> params = givenInputParams(
373 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\", \"test2.vnf_b.onap.com\"]"));
374 String expectedErrorMessage =
375 "Error posting request: "
376 + CHEF_ADAPTER_ERROR_PREFIX
377 + "Cannot find the private key in the APPC file system, please load the private key to "
378 + CLIENT_PRIVATE_KEY_PATH;
379 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(false);
382 assertThatExceptionOfType(SvcLogicException.class)
383 .isThrownBy(() -> chefAdapterFactory.create().fetchResults(params, svcLogicContext))
384 .withMessage(CHEF_ADAPTER_ERROR_PREFIX + expectedErrorMessage);
386 assertThat(svcLogicContext.getStatus()).isEqualTo(FAILURE_STATUS);
387 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
388 .isEqualTo(Integer.toString(HttpStatus.SC_UNAUTHORIZED));
389 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
390 .isEqualTo(expectedErrorMessage);
394 public void fetchResults_shouldUpdateSvcLogicContextWithJsonResponse_fromSuccessfulChefServerCall()
395 throws SvcLogicException {
397 String json = "{normal:{PushJobOutput : \"ssh start/running, process 1090\"}}";
398 Map<String, String> params = givenInputParams(
399 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\"]"));
400 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
401 given(chefApiClientFactory.create(CHEF_END_POINT, ORGANIZATIONS, USERNAME,
402 CLIENT_PRIVATE_KEY_PATH)).willReturn(chefApiClient);
403 given(chefApiClient.get("/nodes/" + "test1.vnf_b.onap.com"))
404 .willReturn(ChefResponse.create(HttpStatus.SC_OK, json));
407 chefAdapterFactory.create().fetchResults(params, svcLogicContext);
410 assertThat(svcLogicContext.getStatus()).isEqualTo(SUCCESS_STATUS);
411 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
412 .isEqualTo(Integer.toString(HttpStatus.SC_OK));
413 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
414 .isEqualTo("{\"test1.vnf_b.onap.com\":{\"PushJobOutput\":\"ssh start/running, process 1090\"}}");
418 public void fetchResults_shouldUpdateSvcLogicContextWithFailedMessage_whenReturnedJSONMessageIsMissingAttribute()
419 throws SvcLogicException {
421 String json = "{normal:{invalidKey : \"ssh start/running, process 1090\"}}";
422 Map<String, String> params = givenInputParams(
423 immutableEntry("NodeList", "[\"test1.vnf_b.onap.com\"]"));
424 given(privateKeyChecker.doesExist(CLIENT_PRIVATE_KEY_PATH)).willReturn(true);
425 given(chefApiClientFactory.create(CHEF_END_POINT, ORGANIZATIONS, USERNAME,
426 CLIENT_PRIVATE_KEY_PATH)).willReturn(chefApiClient);
427 given(chefApiClient.get("/nodes/" + "test1.vnf_b.onap.com"))
428 .willReturn(ChefResponse.create(HttpStatus.SC_OK, json));
431 chefAdapterFactory.create().fetchResults(params, svcLogicContext);
434 assertThat(svcLogicContext.getStatus()).isEqualTo(SUCCESS_STATUS);
435 assertThat(svcLogicContext.getAttribute(RESULT_CODE_ATTR_KEY))
436 .isEqualTo(Integer.toString(HttpStatus.SC_INTERNAL_SERVER_ERROR));
437 assertThat(svcLogicContext.getAttribute(RESULT_MESSAGE_ATTR_KEY))
438 .isEqualTo("Cannot find PushJobOutput");
441 private Map<String, String> givenInputParams(Entry<String, String>... entries) {
442 Builder<String, String> paramsBuilder = ImmutableMap.builder();
443 paramsBuilder.put("username", USERNAME)
444 .put("serverAddress", SERVER_ADDRESS)
445 .put("organizations", ORGANIZATIONS);
447 for (Entry<String, String> entry : entries) {
448 paramsBuilder.put(entry);
450 return paramsBuilder.build();