From 9528b14d965dde96f1fee59e42bdf469120752bd Mon Sep 17 00:00:00 2001 From: brig Date: Mon, 28 Aug 2023 22:05:06 +0200 Subject: [PATCH] up --- .../concord/it/server/AbstractServerIT.java | 4 + .../concord/it/server/AnsibleIT.java | 1247 ++++++++--------- .../concord/it/server/AnsibleLookupIT.java | 491 ++++--- .../concord/it/server/AnsiblePolicyIT.java | 172 +-- .../server/AnsiblePolicyVerboseLimitIT.java | 507 ++++--- .../concord/it/server/AnsibleRetryIT.java | 118 +- 6 files changed, 1255 insertions(+), 1284 deletions(-) diff --git a/it/server/src/test/java/com/walmartlabs/concord/it/server/AbstractServerIT.java b/it/server/src/test/java/com/walmartlabs/concord/it/server/AbstractServerIT.java index 438ccbc99d..69f5015ed4 100644 --- a/it/server/src/test/java/com/walmartlabs/concord/it/server/AbstractServerIT.java +++ b/it/server/src/test/java/com/walmartlabs/concord/it/server/AbstractServerIT.java @@ -192,6 +192,10 @@ protected T fromJson(File f, Class classOfT) throws IOException { return getApiClient().getObjectMapper().readValue(f, classOfT); } + protected T fromJson(InputStream is, Class classOfT) throws IOException { + return getApiClient().getObjectMapper().readValue(is, classOfT); + } + protected String createRepo(String resource) throws Exception { Path tmpDir = createTempDir(); diff --git a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleIT.java b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleIT.java index cdb97218cd..a2daa6af17 100644 --- a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleIT.java +++ b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleIT.java @@ -1,636 +1,611 @@ -//package com.walmartlabs.concord.it.server; -// -///*- -// * ***** -// * Concord -// * ----- -// * Copyright (C) 2017 - 2018 Walmart Inc. -// * ----- -// * 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. -// * ===== -// */ -// -//import com.google.common.io.Files; -//import com.walmartlabs.concord.client.*; -//import com.walmartlabs.concord.common.ConfigurationUtils; -//import org.junit.jupiter.api.Test; -// -//import java.io.File; -//import java.io.FileInputStream; -//import java.io.InputStream; -//import java.net.URI; -//import java.net.URL; -//import java.nio.file.Paths; -//import java.util.*; -//import java.util.regex.Pattern; -// -//import static com.walmartlabs.concord.common.IOUtils.grep; -//import static com.walmartlabs.concord.it.common.ITUtils.archive; -//import static com.walmartlabs.concord.it.common.ServerClient.*; -//import static org.junit.jupiter.api.Assertions.assertEquals; -//import static org.junit.jupiter.api.Assertions.assertNotNull; -// -//public class AnsibleIT extends AbstractServerIT { -// -// @Test -// public void testHello() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansible").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*\"msg\":.*Hello, world.*", ab); -// } -// -// @Test -// public void testSkipTags() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleSkipTags").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*\"msg\":.*Hello2, world.*", ab); -// assertEquals(0, grep(".*Hello, world.*", ab).size(), "unexpected 'Hello, world' log"); -// } -// -// @Test -// public void testVault() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleVault").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello, Concord.*", ab); -// } -// -// @Test -// public void testVaultWithMultiplePasswords() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleVaultMultiplePasswords").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello, Concord.*", ab); -// } -// -// @Test -// public void testVaultWithMultiplePasswordFiles() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleVaultMultiplePasswordFiles").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello, Concord.*", ab); -// } -// -// @Test -// @SuppressWarnings("unchecked") -// public void testTwoAnsibleRuns() throws Exception { -// URI dir = AnsibleIT.class.getResource("twoAnsible").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*\"msg\":.*Hello!.*", ab); -// assertLog(".*\"msg\":.*Bye-bye!.*", ab); -// -// // --- -// -// File resp = processApi.downloadAttachment(spr.getInstanceId(), "ansible_stats_v2.json"); -// assertNotNull(resp); -// -// List> stats = fromJson(resp, List.class); -// -// assertEquals(2, stats.size()); -// -// assertEquals("playbook/hello.yml", stats.get(0).get("playbook")); -// Collection oks = (Collection)ConfigurationUtils.get(stats.get(0), "stats", "ok"); -// assertNotNull(oks); -// assertEquals(1, oks.size()); -// assertEquals("127.0.0.1", oks.iterator().next()); -// } -// -// @Test -// public void testWithForm() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleWithForm").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForStatus(processApi, spr.getInstanceId(), ProcessEntry.StatusEnum.SUSPENDED); -// -// // --- -// -// ProcessFormsApi formsApi = new ProcessFormsApi(getApiClient()); -// List forms = formsApi.list(pir.getInstanceId()); -// assertEquals(1, forms.size()); -// -// formsApi.submit(pir.getInstanceId(), forms.get(0).getName(), Collections.singletonMap("msg", "Hello!")); -// -// // --- -// -// pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*\"msg\":.*Hello!.*", ab); -// } -// -// @Test -// public void testWithFormSuspensionPostAnsible() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleWithPostFormSuspension/payload").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // -- -// -// URI playbookUri = AnsibleIT.class.getResource("ansibleWithPostFormSuspension/playbook/hello.yml").toURI(); -// File playbookFileContent = new File(playbookUri); -// InputStream playbookStream = Files.asByteSource(playbookFileContent).openStream(); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// input.put("playbook.yml", playbookStream); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForStatus(processApi, spr.getInstanceId(), ProcessEntry.StatusEnum.SUSPENDED); -// -// // --- -// -// ProcessFormsApi formsApi = new ProcessFormsApi(getApiClient()); -// List forms = formsApi.list(pir.getInstanceId()); -// assertEquals(1, forms.size()); -// -// formsApi.submit(pir.getInstanceId(), forms.get(0).getName(), Collections.singletonMap("msg", "Hello!")); -// -// // --- -// -// pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello!.*", ab); -// } -// -// @Test -// public void testExtenalPlaybook() throws Exception { -// -// URI dir = AnsibleIT.class.getResource("ansibleExternalPlaybook/payload").toURI(); -// URL playbookUrl = AnsibleIT.class.getResource("ansibleExternalPlaybook/playbook/hello.yml"); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// File playbook = Paths.get(playbookUrl.toURI()).toFile(); -// input.put("myplaybook.yml", new FileInputStream(playbook)); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// } -// -// @Test -// public void testMergeDefaults() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleMergeDefaults").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*_callbacks:myCallbackDir.*", ab); -// } -// -// @Test -// public void testGroupVars() throws Exception { -// String orgName = "org_" + randomString(); -// OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); -// orgApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// // --- -// -// String secretName = "secret_" + randomString(); -// addPlainSecret(orgName, secretName, false, null, "greetings: \"Hi there!\"".getBytes()); -// -// // --- -// -// URI dir = AnsibleIT.class.getResource("ansibleGroupVars").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// input.put("arguments.myOrgName", orgName); -// input.put("arguments.mySecretName", secretName); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*\"msg\":.*Hi there!.*", ab); -// } -// -// @Test -// public void testOutVars() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleOutVars").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*\"msg\":.*First hello from ansible.*", ab); -// assertLog(".*\"msg\":.*Second message.*", ab); -// } -// -// @Test -// public void testStats() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleStats").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*OK:.*127.0.0.1.*", ab); -// } -// -// @Test -// public void testBadStrings() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleBadStrings").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*THIS TASK CONTAINS SENSITIVE INFORMATION.*", ab); -// } -// -// @Test -// public void testRawStrings() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleRawStrings").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*" + Pattern.quote("message '{{.lalala}}'") + ".*", ab); -// assertLog(".*" + Pattern.quote("message {{.unsafe}}") + ".*", ab); -// } -// -// @Test -// @SuppressWarnings("unchecked") -// public void testTemplateArgs() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleTemplateArgs").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*message iddqd.*", ab); -// -// // --- -// ProcessEventsApi eventsApi = new ProcessEventsApi(getApiClient()); -// List events = eventsApi.list(pir.getInstanceId(), "ANSIBLE", null, null, null, null, null, null); -// assertNotNull(events); -// // one pre and one post event -// assertEquals(2, events.size()); -// Map data = events.stream() -// .filter(e -> "post".equals(e.getData().get("phase"))) -// .findAny() -// .orElseThrow(() -> new RuntimeException("post event not found")) -// .getData(); -// assertEquals("message iddqd", ((Map) data.get("result")).get("msg")); -// } -// -// @Test -// public void testExtraVarsFiles() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleExtraVarsFiles").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello from a JSON file!.*", ab); -// assertLog(".*Hello from a YAML file!.*", ab); -// } -// -// @Test -// public void testMultiInventories() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleMultiInventory").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello aaa.*", ab); -// assertLog(".*Hello bbb.*", ab); -// } -// -// @Test -// public void testMultiInventoryFiles() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleMultiInventoryFile").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello aaa.*", ab); -// assertLog(".*Hello bbb.*", ab); -// } -// -// @Test -// public void testLimitWithMultipleHost() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLimitWithMultipleHost").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLogAtLeast(".*Hello aaa.*", 2, ab); -// assertLogAtLeast(".*Hello ccc.*", 2, ab); -// assertNoLog(".*Hello bbb.*", ab); -// } -// -// @Test -// public void testInventoryMixMatch() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleInventoryMix").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello!.*", ab); -// } -// -// @Test -// public void testInventoryNameInvalidChars() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleInventoryName").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// StartProcessResponse spr = start(payload); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello!.*", ab); -// } -// -// @Test -// public void testLogFiltering() throws Exception { -// // run w/o filtering first -// -// URI dir = AnsibleIT.class.getResource("ansibleLogFiltering").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("arguments.doFilter", false); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Hello! my_password=.*", ab); -// -// // and then run with the filtering enabled -// -// input = new HashMap<>(); -// input.put("arguments.doFilter", true); -// input.put("archive", payload); -// -// spr = start(input); -// -// // --- -// -// pir = waitForCompletion(processApi, spr.getInstanceId()); -// -// ab = getLog(pir.getLogFileName()); -// assertNoLog(".*Hello! my_password=.*", ab); -// assertLog(".*SENSITIVE INFORMATION.*", ab); -// } -//} +package com.walmartlabs.concord.it.server; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * 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. + * ===== + */ + +import com.google.common.io.Files; +import com.walmartlabs.concord.client.*; +import com.walmartlabs.concord.common.ConfigurationUtils; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.nio.file.Paths; +import java.util.*; +import java.util.regex.Pattern; + +import static com.walmartlabs.concord.common.IOUtils.grep; +import static com.walmartlabs.concord.it.common.ITUtils.archive; +import static com.walmartlabs.concord.it.common.ServerClient.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class AnsibleIT extends AbstractServerIT { + + @Test + public void testHello() throws Exception { + URI dir = AnsibleIT.class.getResource("ansible").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*\"msg\":.*Hello, world.*", ab); + } + + @Test + public void testSkipTags() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleSkipTags").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*\"msg\":.*Hello2, world.*", ab); + assertEquals(0, grep(".*Hello, world.*", ab).size(), "unexpected 'Hello, world' log"); + } + + @Test + public void testVault() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleVault").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello, Concord.*", ab); + } + + @Test + public void testVaultWithMultiplePasswords() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleVaultMultiplePasswords").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello, Concord.*", ab); + } + + @Test + public void testVaultWithMultiplePasswordFiles() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleVaultMultiplePasswordFiles").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello, Concord.*", ab); + } + + @Test + @SuppressWarnings("unchecked") + public void testTwoAnsibleRuns() throws Exception { + URI dir = AnsibleIT.class.getResource("twoAnsible").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("archive", payload); + StartProcessResponse spr = start(input); + + // --- + + ProcessApi processApi = new ProcessApi(getApiClient()); + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*\"msg\":.*Hello!.*", ab); + assertLog(".*\"msg\":.*Bye-bye!.*", ab); + + // --- + + try (InputStream resp = processApi.downloadAttachment(spr.getInstanceId(), "ansible_stats_v2.json")) { + assertNotNull(resp); + + List> stats = fromJson(resp, List.class); + + assertEquals(2, stats.size()); + + assertEquals("playbook/hello.yml", stats.get(0).get("playbook")); + Collection oks = (Collection)ConfigurationUtils.get(stats.get(0), "stats", "ok"); + assertNotNull(oks); + assertEquals(1, oks.size()); + assertEquals("127.0.0.1", oks.iterator().next()); + } + } + + @Test + public void testWithForm() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleWithForm").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("archive", payload); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForStatus(getApiClient(), spr.getInstanceId(), ProcessEntry.StatusEnum.SUSPENDED); + + // --- + + ProcessFormsApi formsApi = new ProcessFormsApi(getApiClient()); + List forms = formsApi.listProcessForms(pir.getInstanceId()); + assertEquals(1, forms.size()); + + formsApi.submitForm(pir.getInstanceId(), forms.get(0).getName(), Collections.singletonMap("msg", "Hello!")); + + // --- + + pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*\"msg\":.*Hello!.*", ab); + } + + @Test + public void testWithFormSuspensionPostAnsible() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleWithPostFormSuspension/payload").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // -- + + URI playbookUri = AnsibleIT.class.getResource("ansibleWithPostFormSuspension/playbook/hello.yml").toURI(); + File playbookFileContent = new File(playbookUri); + InputStream playbookStream = Files.asByteSource(playbookFileContent).openStream(); + + // --- + + Map input = new HashMap<>(); + input.put("archive", payload); + input.put("playbook.yml", playbookStream); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForStatus(getApiClient(), spr.getInstanceId(), ProcessEntry.StatusEnum.SUSPENDED); + + // --- + + ProcessFormsApi formsApi = new ProcessFormsApi(getApiClient()); + List forms = formsApi.listProcessForms(pir.getInstanceId()); + assertEquals(1, forms.size()); + + formsApi.submitForm(pir.getInstanceId(), forms.get(0).getName(), Collections.singletonMap("msg", "Hello!")); + + // --- + + pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello!.*", ab); + } + + @Test + public void testExtenalPlaybook() throws Exception { + + URI dir = AnsibleIT.class.getResource("ansibleExternalPlaybook/payload").toURI(); + URL playbookUrl = AnsibleIT.class.getResource("ansibleExternalPlaybook/playbook/hello.yml"); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("archive", payload); + File playbook = Paths.get(playbookUrl.toURI()).toFile(); + input.put("myplaybook.yml", new FileInputStream(playbook)); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + } + + @Test + public void testMergeDefaults() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleMergeDefaults").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("archive", payload); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*_callbacks:myCallbackDir.*", ab); + } + + @Test + public void testGroupVars() throws Exception { + String orgName = "org_" + randomString(); + OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); + orgApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + // --- + + String secretName = "secret_" + randomString(); + addPlainSecret(orgName, secretName, false, null, "greetings: \"Hi there!\"".getBytes()); + + // --- + + URI dir = AnsibleIT.class.getResource("ansibleGroupVars").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("archive", payload); + input.put("arguments.myOrgName", orgName); + input.put("arguments.mySecretName", secretName); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*\"msg\":.*Hi there!.*", ab); + } + + @Test + public void testOutVars() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleOutVars").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*\"msg\":.*First hello from ansible.*", ab); + assertLog(".*\"msg\":.*Second message.*", ab); + } + + @Test + public void testStats() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleStats").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*OK:.*127.0.0.1.*", ab); + } + + @Test + public void testBadStrings() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleBadStrings").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*THIS TASK CONTAINS SENSITIVE INFORMATION.*", ab); + } + + @Test + public void testRawStrings() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleRawStrings").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*" + Pattern.quote("message '{{.lalala}}'") + ".*", ab); + assertLog(".*" + Pattern.quote("message {{.unsafe}}") + ".*", ab); + } + + @Test + @SuppressWarnings("unchecked") + public void testTemplateArgs() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleTemplateArgs").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*message iddqd.*", ab); + + // --- + ProcessEventsApi eventsApi = new ProcessEventsApi(getApiClient()); + List events = eventsApi.listProcessEvents(pir.getInstanceId(), "ANSIBLE", null, null, null, null, null, null); + assertNotNull(events); + // one pre and one post event + assertEquals(2, events.size()); + Map data = events.stream() + .filter(e -> "post".equals(e.getData().get("phase"))) + .findAny() + .orElseThrow(() -> new RuntimeException("post event not found")) + .getData(); + assertEquals("message iddqd", ((Map) data.get("result")).get("msg")); + } + + @Test + public void testExtraVarsFiles() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleExtraVarsFiles").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello from a JSON file!.*", ab); + assertLog(".*Hello from a YAML file!.*", ab); + } + + @Test + public void testMultiInventories() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleMultiInventory").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello aaa.*", ab); + assertLog(".*Hello bbb.*", ab); + } + + @Test + public void testMultiInventoryFiles() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleMultiInventoryFile").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello aaa.*", ab); + assertLog(".*Hello bbb.*", ab); + } + + @Test + public void testLimitWithMultipleHost() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLimitWithMultipleHost").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + byte[] ab = getLog(pir.getInstanceId()); + assertLogAtLeast(".*Hello aaa.*", 2, ab); + assertLogAtLeast(".*Hello ccc.*", 2, ab); + assertNoLog(".*Hello bbb.*", ab); + } + + @Test + public void testInventoryMixMatch() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleInventoryMix").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello!.*", ab); + } + + @Test + public void testInventoryNameInvalidChars() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleInventoryName").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + StartProcessResponse spr = start(payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello!.*", ab); + } + + @Test + public void testLogFiltering() throws Exception { + // run w/o filtering first + + URI dir = AnsibleIT.class.getResource("ansibleLogFiltering").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("arguments.doFilter", false); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Hello! my_password=.*", ab); + + // and then run with the filtering enabled + + input = new HashMap<>(); + input.put("arguments.doFilter", true); + input.put("archive", payload); + + spr = start(input); + + // --- + + pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + + ab = getLog(pir.getInstanceId()); + assertNoLog(".*Hello! my_password=.*", ab); + assertLog(".*SENSITIVE INFORMATION.*", ab); + } +} diff --git a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleLookupIT.java b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleLookupIT.java index 1895d47e3b..c4ab13f086 100644 --- a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleLookupIT.java +++ b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleLookupIT.java @@ -1,248 +1,243 @@ -//package com.walmartlabs.concord.it.server; -// -///*- -// * ***** -// * Concord -// * ----- -// * Copyright (C) 2017 - 2018 Walmart Inc. -// * ----- -// * 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. -// * ===== -// */ -// -//import com.walmartlabs.concord.client.*; -//import org.junit.jupiter.api.Test; -// -//import java.net.URI; -//import java.util.HashMap; -//import java.util.Map; -// -//import static com.walmartlabs.concord.it.common.ITUtils.archive; -//import static com.walmartlabs.concord.it.common.ServerClient.*; -//import static org.junit.jupiter.api.Assertions.assertEquals; -// -//public class AnsibleLookupIT extends AbstractServerIT { -// -// @Test -// public void testSecrets() throws Exception { -// String orgName = "org_" + randomString(); -// OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); -// orgApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// String secretName = "mySecret"; -// String secretValue = "value_" + randomString(); -// String secretPwd = randomPwd(); -// addPlainSecret(orgName, secretName, false, secretPwd, secretValue.getBytes()); -// -// String projectName = "project_" + randomString(); -// ProjectsApi projectsApi = new ProjectsApi(getApiClient()); -// projectsApi.createOrUpdateProject(orgName, new ProjectEntry() -// .setName(projectName) -// .setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); -// -// // --- -// -// URI dir = AnsibleLookupIT.class.getResource("ansibleLookupSecret").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("archive", payload); -// input.put("arguments.orgName", orgName); -// input.put("arguments.secretPwd", secretPwd); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertNoLog(".*Explicit org " + secretValue + ".*", ab); -// assertNoLog(".*Implicit org " + secretValue + ".*", ab); -// assertLogAtLeast(".*ENABLING NO_LOG.*", 2, ab); -// } -// -// @Test -// public void testSecretData() throws Exception { -// String orgName = "org_" + randomString(); -// OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); -// orgApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// String secretName = "mySecret"; -// String secretValue = "value_" + randomString(); -// String secretPwd = randomPwd(); -// addPlainSecret(orgName, secretName, false, secretPwd, secretValue.getBytes()); -// -// String projectName = "project_" + randomString(); -// ProjectsApi projectsApi = new ProjectsApi(getApiClient()); -// projectsApi.createOrUpdateProject(orgName, new ProjectEntry() -// .setName(projectName) -// .setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); -// -// // --- -// -// URI dir = AnsibleLookupIT.class.getResource("ansibleLookupSecretData").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("archive", payload); -// input.put("arguments.orgName", orgName); -// input.put("arguments.secretPwd", secretPwd); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertNoLog(".*Explicit org " + secretValue + ".*", ab); -// assertNoLog(".*Implicit org " + secretValue + ".*", ab); -// assertLogAtLeast(".*ENABLING NO_LOG.*", 2, ab); -// } -// -// @Test -// public void testSecretDataNoPassword() throws Exception { -// String orgName = "org_" + randomString(); -// OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); -// orgApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// String secretName = "mySecret"; -// String secretValue = "value_" + randomString(); -// addPlainSecret(orgName, secretName, false, null, secretValue.getBytes()); -// -// String projectName = "project_" + randomString(); -// ProjectsApi projectsApi = new ProjectsApi(getApiClient()); -// projectsApi.createOrUpdateProject(orgName, new ProjectEntry() -// .setName(projectName) -// .setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); -// -// // --- -// -// URI dir = AnsibleLookupIT.class.getResource("ansibleLookupSecretDataNoPassword").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("archive", payload); -// input.put("arguments.orgName", orgName); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertNoLog(".*Explicit org " + secretValue + ".*", ab); -// assertNoLog(".*Implicit org " + secretValue + ".*", ab); -// } -// -// @Test -// public void testPublickey() throws Exception { -// String orgName = "org_" + randomString(); -// OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); -// orgApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// String secretName = "mySecret_" + randomString(); -// generateKeyPair(orgName, secretName, false, null); -// -// String projectName = "project_" + randomString(); -// ProjectsApi projectsApi = new ProjectsApi(getApiClient()); -// projectsApi.createOrUpdateProject(orgName, new ProjectEntry() -// .setName(projectName) -// .setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); -// -// // --- -// -// URI dir = AnsibleLookupIT.class.getResource("ansibleLookupPublicKey").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("archive", payload); -// input.put("arguments.orgName", orgName); -// input.put("arguments.secretName", secretName); -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertNoLog(".*Explicit org: ssh-rsa" + ".*", ab); -// assertNoLog(".*Implicit org: ssh-rsa" + ".*", ab); -// assertLogAtLeast(".*ENABLING NO_LOG.*", 2, ab); -// } -// -// /** -// * Verify that {@code lookup('concord_data_secret', ...)} returns a valid value. -// */ -// @Test -// public void testSecretValue() throws Exception { -// String orgName = "org_" + randomString(); -// OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); -// orgApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// String secretName = "mySecret_" + randomString(); -// String secretValue = "hello_" + randomString(); -// addPlainSecret(orgName, secretName, false, null, secretValue.getBytes()); -// -// // --- -// -// byte[] payload = archive(AnsibleLookupIT.class.getResource("ansibleLookupSecretDataValue").toURI(), ITConstants.DEPENDENCIES_DIR); -// -// Map input = new HashMap<>(); -// input.put("archive", payload); -// input.put("arguments.orgName", orgName); -// input.put("arguments.secretName", secretName); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pe = waitForCompletion(processApi, spr.getInstanceId()); -// -// // --- -// -// byte[] ab = getLog(pe.getLogFileName()); -// assertLog(".*Value: " + secretValue + ".*", ab); -// } -//} +package com.walmartlabs.concord.it.server; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * 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. + * ===== + */ + +import com.walmartlabs.concord.client.*; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +import static com.walmartlabs.concord.it.common.ITUtils.archive; +import static com.walmartlabs.concord.it.common.ServerClient.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AnsibleLookupIT extends AbstractServerIT { + + @Test + public void testSecrets() throws Exception { + String orgName = "org_" + randomString(); + OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); + orgApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + String secretName = "mySecret"; + String secretValue = "value_" + randomString(); + String secretPwd = randomPwd(); + addPlainSecret(orgName, secretName, false, secretPwd, secretValue.getBytes()); + + String projectName = "project_" + randomString(); + ProjectsApi projectsApi = new ProjectsApi(getApiClient()); + projectsApi.createOrUpdateProject(orgName, new ProjectEntry() + .name(projectName) + .rawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); + + // --- + + URI dir = AnsibleLookupIT.class.getResource("ansibleLookupSecret").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("archive", payload); + input.put("arguments.orgName", orgName); + input.put("arguments.secretPwd", secretPwd); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertNoLog(".*Explicit org " + secretValue + ".*", ab); + assertNoLog(".*Implicit org " + secretValue + ".*", ab); + assertLogAtLeast(".*ENABLING NO_LOG.*", 2, ab); + } + + @Test + public void testSecretData() throws Exception { + String orgName = "org_" + randomString(); + OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); + orgApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + String secretName = "mySecret"; + String secretValue = "value_" + randomString(); + String secretPwd = randomPwd(); + addPlainSecret(orgName, secretName, false, secretPwd, secretValue.getBytes()); + + String projectName = "project_" + randomString(); + ProjectsApi projectsApi = new ProjectsApi(getApiClient()); + projectsApi.createOrUpdateProject(orgName, new ProjectEntry() + .name(projectName) + .rawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); + + // --- + + URI dir = AnsibleLookupIT.class.getResource("ansibleLookupSecretData").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("archive", payload); + input.put("arguments.orgName", orgName); + input.put("arguments.secretPwd", secretPwd); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertNoLog(".*Explicit org " + secretValue + ".*", ab); + assertNoLog(".*Implicit org " + secretValue + ".*", ab); + assertLogAtLeast(".*ENABLING NO_LOG.*", 2, ab); + } + + @Test + public void testSecretDataNoPassword() throws Exception { + String orgName = "org_" + randomString(); + OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); + orgApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + String secretName = "mySecret"; + String secretValue = "value_" + randomString(); + addPlainSecret(orgName, secretName, false, null, secretValue.getBytes()); + + String projectName = "project_" + randomString(); + ProjectsApi projectsApi = new ProjectsApi(getApiClient()); + projectsApi.createOrUpdateProject(orgName, new ProjectEntry() + .name(projectName) + .rawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); + + // --- + + URI dir = AnsibleLookupIT.class.getResource("ansibleLookupSecretDataNoPassword").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("archive", payload); + input.put("arguments.orgName", orgName); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertNoLog(".*Explicit org " + secretValue + ".*", ab); + assertNoLog(".*Implicit org " + secretValue + ".*", ab); + } + + @Test + public void testPublickey() throws Exception { + String orgName = "org_" + randomString(); + OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); + orgApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + String secretName = "mySecret_" + randomString(); + generateKeyPair(orgName, secretName, false, null); + + String projectName = "project_" + randomString(); + ProjectsApi projectsApi = new ProjectsApi(getApiClient()); + projectsApi.createOrUpdateProject(orgName, new ProjectEntry() + .name(projectName) + .rawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); + + // --- + + URI dir = AnsibleLookupIT.class.getResource("ansibleLookupPublicKey").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("archive", payload); + input.put("arguments.orgName", orgName); + input.put("arguments.secretName", secretName); + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertNoLog(".*Explicit org: ssh-rsa" + ".*", ab); + assertNoLog(".*Implicit org: ssh-rsa" + ".*", ab); + assertLogAtLeast(".*ENABLING NO_LOG.*", 2, ab); + } + + /** + * Verify that {@code lookup('concord_data_secret', ...)} returns a valid value. + */ + @Test + public void testSecretValue() throws Exception { + String orgName = "org_" + randomString(); + OrganizationsApi orgApi = new OrganizationsApi(getApiClient()); + orgApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + String secretName = "mySecret_" + randomString(); + String secretValue = "hello_" + randomString(); + addPlainSecret(orgName, secretName, false, null, secretValue.getBytes()); + + // --- + + byte[] payload = archive(AnsibleLookupIT.class.getResource("ansibleLookupSecretDataValue").toURI(), ITConstants.DEPENDENCIES_DIR); + + Map input = new HashMap<>(); + input.put("archive", payload); + input.put("arguments.orgName", orgName); + input.put("arguments.secretName", secretName); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pe = waitForCompletion(getApiClient(), spr.getInstanceId()); + + // --- + + byte[] ab = getLog(pe.getInstanceId()); + assertLog(".*Value: " + secretValue + ".*", ab); + } +} diff --git a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyIT.java b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyIT.java index 0d342e0762..9d05930a03 100644 --- a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyIT.java +++ b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyIT.java @@ -1,86 +1,86 @@ -//package com.walmartlabs.concord.it.server; -// -///*- -// * ***** -// * Concord -// * ----- -// * Copyright (C) 2017 - 2018 Walmart Inc. -// * ----- -// * 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. -// * ===== -// */ -// -//import com.walmartlabs.concord.client.*; -//import org.junit.jupiter.api.Test; -// -//import java.io.File; -//import java.net.URI; -//import java.net.URL; -//import java.util.Map; -// -//import static com.walmartlabs.concord.it.common.ITUtils.archive; -//import static com.walmartlabs.concord.it.common.ServerClient.assertLog; -//import static com.walmartlabs.concord.it.common.ServerClient.waitForCompletion; -//import static org.junit.jupiter.api.Assertions.assertEquals; -// -//public class AnsiblePolicyIT extends AbstractServerIT { -// -// @Test -// public void testTaskDeny() throws Exception { -// // --- -// -// String orgName = "Default"; -// String projectName = "project_" + randomString(); -// -// ProjectsApi projectsApi = new ProjectsApi(getApiClient()); -// projectsApi.createOrUpdateProject(orgName, new ProjectEntry() -// .setName(projectName) -// .setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); -// -// // --- -// -// String policyName = "test_policy_" + randomString(); -// PolicyEntry policy = new PolicyEntry() -// .setName(policyName) -// .setRules(readPolicy("ansiblePolicyTaskDeny/test-policy.json")); -// -// PolicyApi policyApi = new PolicyApi(getApiClient()); -// policyApi.createOrUpdateProject(policy); -// policyApi.link(policyName, new PolicyLinkEntry() -// .setOrgName(orgName) -// .setProjectName(projectName)); -// -// URI dir = AnsiblePolicyIT.class.getResource("ansiblePolicyTaskDeny").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(orgName, projectName, null, null, payload); -// -// // --- -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FAILED, pir.getStatus()); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Task 'Copy a local file \\(copy\\)' is forbidden by the task policy.*", ab); -// } -// -// private Map readPolicy(String file) throws Exception { -// URL url = AnsiblePolicyIT.class.getResource(file); -// return fromJson(new File(url.toURI())); -// } -//} +package com.walmartlabs.concord.it.server; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * 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. + * ===== + */ + +import com.walmartlabs.concord.client.*; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.Map; + +import static com.walmartlabs.concord.it.common.ITUtils.archive; +import static com.walmartlabs.concord.it.common.ServerClient.assertLog; +import static com.walmartlabs.concord.it.common.ServerClient.waitForCompletion; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AnsiblePolicyIT extends AbstractServerIT { + + @Test + public void testTaskDeny() throws Exception { + // --- + + String orgName = "Default"; + String projectName = "project_" + randomString(); + + ProjectsApi projectsApi = new ProjectsApi(getApiClient()); + projectsApi.createOrUpdateProject(orgName, new ProjectEntry() + .name(projectName) + .rawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); + + // --- + + String policyName = "test_policy_" + randomString(); + PolicyEntry policy = new PolicyEntry() + .name(policyName) + .rules(readPolicy("ansiblePolicyTaskDeny/test-policy.json")); + + PolicyApi policyApi = new PolicyApi(getApiClient()); + policyApi.createOrUpdatePolicy(policy); + policyApi.linkPolicy(policyName, new PolicyLinkEntry() + .orgName(orgName) + .projectName(projectName)); + + URI dir = AnsiblePolicyIT.class.getResource("ansiblePolicyTaskDeny").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + ProcessApi processApi = new ProcessApi(getApiClient()); + StartProcessResponse spr = start(orgName, projectName, null, null, payload); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FAILED, pir.getStatus()); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Task 'Copy a local file \\(copy\\)' is forbidden by the task policy.*", ab); + } + + private Map readPolicy(String file) throws Exception { + URL url = AnsiblePolicyIT.class.getResource(file); + return fromJson(new File(url.toURI())); + } +} diff --git a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyVerboseLimitIT.java b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyVerboseLimitIT.java index 02a1a947fa..cb513de069 100644 --- a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyVerboseLimitIT.java +++ b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsiblePolicyVerboseLimitIT.java @@ -1,256 +1,251 @@ -//package com.walmartlabs.concord.it.server; -// -///*- -// * ***** -// * Concord -// * ----- -// * Copyright (C) 2017 - 2021 Walmart Inc. -// * ----- -// * 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. -// * ===== -// */ -// -//import com.walmartlabs.concord.client.*; -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.Test; -// -//import java.net.URI; -//import java.util.HashMap; -//import java.util.Map; -// -//import static com.walmartlabs.concord.it.common.ITUtils.archive; -//import static com.walmartlabs.concord.it.common.ServerClient.assertLog; -//import static com.walmartlabs.concord.it.common.ServerClient.waitForCompletion; -//import static java.util.Collections.singletonMap; -//import static org.junit.jupiter.api.Assertions.assertEquals; -// -//public class AnsiblePolicyVerboseLimitIT extends AbstractServerIT { -// -// private String orgName; -// private String projectName; -// -// @BeforeEach -// public void setup() throws Exception { -// -// // -- Add policy to restrict verbose logging -// -// orgName = "org_" + randomString(); -// OrganizationsApi organizationsApi = new OrganizationsApi(getApiClient()); -// organizationsApi.createOrUpdateProject(new OrganizationEntry().setName(orgName)); -// -// projectName = "project_" + randomString(); -// ProjectsApi projectsApi = new ProjectsApi(getApiClient()); -// projectsApi.createOrUpdateProject(orgName, new ProjectEntry() -// .setName(projectName) -// .setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); -// -// Map ansibleVerboseLimits = new HashMap<>(); -// ansibleVerboseLimits.put("maxHosts", 1); -// ansibleVerboseLimits.put("maxTotalWork", 2); -// -// String policyName = "policy_" + randomString(); -// PolicyApi policyApi = new PolicyApi(getApiClient()); -// policyApi.createOrUpdateProject(new PolicyEntry() -// .setName(policyName) -// .setRules(singletonMap("processCfg", -// singletonMap("arguments", -// singletonMap("ansibleVerboseLimits", -// ansibleVerboseLimits))))); -// -// policyApi.link(policyName, new PolicyLinkEntry() -// .setOrgName(orgName) -// .setProjectName(projectName)); -// } -// -// @Test -// public void testLargeInventoryLimitedToGroup() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("arguments.playbook", "playbook_single.yml"); -// input.put("arguments.verboseLevel", "1"); -// input.put("arguments.invFile", "inventory_limit.ini"); -// input.put("arguments.groupLimit", "dev"); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), "Large inventory limited to small group must FINISH"); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*ansible completed successfully.*", ab); -// } -// -// @Test -// public void testVerboseTooManyImportedTasks() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("arguments.playbook", "playbook_include.yml"); -// input.put("arguments.verboseLevel", "4"); -// input.put("arguments.invFile", "inventory_small.ini"); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), -// "Imported tasks exceeding max work must FINISH"); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Disabling verbose output. Too much work.*", ab); -// } -// -// @Test -// public void testVerboseTooManyHosts() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("arguments.playbook", "playbook_single.yml"); -// input.put("arguments.verboseLevel", "1"); -// input.put("arguments.invFile", "inventory_large.ini"); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), -// "Large inventory with verbose logging must FINISH"); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Disabling verbose output. Too many hosts.*", ab); -// } -// -// @Test -// public void testVerboseTooMuchWork() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("arguments.playbook", "playbook_multi.yml"); -// input.put("arguments.verboseLevel", "1"); -// input.put("arguments.invFile", "inventory_small.ini"); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), -// "Small inventory with many calls and verbose logging must FINISH"); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*Disabling verbose output. Too much work.*", ab); -// } -// -// @Test -// public void testNoVerboseLargeInventory() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("arguments.playbook", "playbook_single.yml"); -// input.put("arguments.verboseLevel", "0"); -// input.put("arguments.invFile", "inventory_large.ini"); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), -// "Large inventory with standard logging must FINISH"); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// assertLog(".*ansible completed successfully.*", ab); -// } -// -// @Test -// public void testVerboseSmallInventory() throws Exception { -// URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); -// byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); -// -// // --- -// -// Map input = new HashMap<>(); -// input.put("org", orgName); -// input.put("project", projectName); -// input.put("arguments.playbook", "playbook_single.yml"); -// input.put("arguments.verboseLevel", "3"); -// input.put("arguments.invFile", "inventory_small.ini"); -// input.put("archive", payload); -// -// StartProcessResponse spr = start(input); -// -// // --- -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), -// "Small inventory with verbose logging must FINISH"); -// -// // --- -// -// byte[] ab = getLog(pir.getLogFileName()); -// // only shows with verbose logging enabled -// // TODO may be flaky? no guarantee it'll *always* be in every ansible version -// assertLog(".*Using .* as config file.*", ab); -// } -//} +package com.walmartlabs.concord.it.server; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2021 Walmart Inc. + * ----- + * 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. + * ===== + */ + +import com.walmartlabs.concord.client.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +import static com.walmartlabs.concord.it.common.ITUtils.archive; +import static com.walmartlabs.concord.it.common.ServerClient.assertLog; +import static com.walmartlabs.concord.it.common.ServerClient.waitForCompletion; +import static java.util.Collections.singletonMap; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AnsiblePolicyVerboseLimitIT extends AbstractServerIT { + + private String orgName; + private String projectName; + + @BeforeEach + public void setup() throws Exception { + + // -- Add policy to restrict verbose logging + + orgName = "org_" + randomString(); + OrganizationsApi organizationsApi = new OrganizationsApi(getApiClient()); + organizationsApi.createOrUpdateOrg(new OrganizationEntry().name(orgName)); + + projectName = "project_" + randomString(); + ProjectsApi projectsApi = new ProjectsApi(getApiClient()); + projectsApi.createOrUpdateProject(orgName, new ProjectEntry() + .name(projectName) + .rawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)); + + Map ansibleVerboseLimits = new HashMap<>(); + ansibleVerboseLimits.put("maxHosts", 1); + ansibleVerboseLimits.put("maxTotalWork", 2); + + String policyName = "policy_" + randomString(); + PolicyApi policyApi = new PolicyApi(getApiClient()); + policyApi.createOrUpdatePolicy(new PolicyEntry() + .name(policyName) + .rules(singletonMap("processCfg", + singletonMap("arguments", + singletonMap("ansibleVerboseLimits", + ansibleVerboseLimits))))); + + policyApi.linkPolicy(policyName, new PolicyLinkEntry() + .orgName(orgName) + .projectName(projectName)); + } + + @Test + public void testLargeInventoryLimitedToGroup() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("arguments.playbook", "playbook_single.yml"); + input.put("arguments.verboseLevel", "1"); + input.put("arguments.invFile", "inventory_limit.ini"); + input.put("arguments.groupLimit", "dev"); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), "Large inventory limited to small group must FINISH"); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*ansible completed successfully.*", ab); + } + + @Test + public void testVerboseTooManyImportedTasks() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("arguments.playbook", "playbook_include.yml"); + input.put("arguments.verboseLevel", "4"); + input.put("arguments.invFile", "inventory_small.ini"); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), + "Imported tasks exceeding max work must FINISH"); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Disabling verbose output. Too much work.*", ab); + } + + @Test + public void testVerboseTooManyHosts() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("arguments.playbook", "playbook_single.yml"); + input.put("arguments.verboseLevel", "1"); + input.put("arguments.invFile", "inventory_large.ini"); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), + "Large inventory with verbose logging must FINISH"); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Disabling verbose output. Too many hosts.*", ab); + } + + @Test + public void testVerboseTooMuchWork() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("arguments.playbook", "playbook_multi.yml"); + input.put("arguments.verboseLevel", "1"); + input.put("arguments.invFile", "inventory_small.ini"); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), + "Small inventory with many calls and verbose logging must FINISH"); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*Disabling verbose output. Too much work.*", ab); + } + + @Test + public void testNoVerboseLargeInventory() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("arguments.playbook", "playbook_single.yml"); + input.put("arguments.verboseLevel", "0"); + input.put("arguments.invFile", "inventory_large.ini"); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), + "Large inventory with standard logging must FINISH"); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + assertLog(".*ansible completed successfully.*", ab); + } + + @Test + public void testVerboseSmallInventory() throws Exception { + URI dir = AnsibleIT.class.getResource("ansibleLargeVerbose").toURI(); + byte[] payload = archive(dir, ITConstants.DEPENDENCIES_DIR); + + // --- + + Map input = new HashMap<>(); + input.put("org", orgName); + input.put("project", projectName); + input.put("arguments.playbook", "playbook_single.yml"); + input.put("arguments.verboseLevel", "3"); + input.put("arguments.invFile", "inventory_small.ini"); + input.put("archive", payload); + + StartProcessResponse spr = start(input); + + // --- + + ProcessApi processApi = new ProcessApi(getApiClient()); + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FINISHED, pir.getStatus(), + "Small inventory with verbose logging must FINISH"); + + // --- + + byte[] ab = getLog(pir.getInstanceId()); + // only shows with verbose logging enabled + // TODO may be flaky? no guarantee it'll *always* be in every ansible version + assertLog(".*Using .* as config file.*", ab); + } +} diff --git a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleRetryIT.java b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleRetryIT.java index e8ab1a9fe5..0c9214facc 100644 --- a/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleRetryIT.java +++ b/it/server/src/test/java/com/walmartlabs/concord/it/server/AnsibleRetryIT.java @@ -1,58 +1,60 @@ -//package com.walmartlabs.concord.it.server; -// -///*- -// * ***** -// * Concord -// * ----- -// * Copyright (C) 2017 - 2018 Walmart Inc. -// * ----- -// * 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. -// * ===== -// */ -// -//import com.walmartlabs.concord.client.ProcessApi; -//import com.walmartlabs.concord.client.ProcessEntry; -//import com.walmartlabs.concord.client.StartProcessResponse; -//import org.junit.jupiter.api.Test; -// -//import java.io.File; -//import java.net.URI; -// -//import static com.walmartlabs.concord.it.common.ITUtils.archive; -//import static com.walmartlabs.concord.it.common.ServerClient.waitForCompletion; -//import static org.junit.jupiter.api.Assertions.assertEquals; -//import static org.junit.jupiter.api.Assertions.assertNotNull; -// -//public class AnsibleRetryIT extends AbstractServerIT { -// -// @Test -// public void testSaveRetry() throws Exception { -// URI uri = ProcessIT.class.getResource("ansibleSaveRetry").toURI(); -// byte[] payload = archive(uri, ITConstants.DEPENDENCIES_DIR); -// -// // start the process -// -// ProcessApi processApi = new ProcessApi(getApiClient()); -// StartProcessResponse spr = start(payload); -// -// // wait for completion -// -// ProcessEntry pir = waitForCompletion(processApi, spr.getInstanceId()); -// assertEquals(ProcessEntry.StatusEnum.FAILED, pir.getStatus()); -// -// // retrieve the retry file -// -// File r = processApi.downloadAttachment(pir.getInstanceId(), "hello.retry"); -// assertNotNull(r); -// } -//} +package com.walmartlabs.concord.it.server; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * 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. + * ===== + */ + +import com.walmartlabs.concord.client.ProcessApi; +import com.walmartlabs.concord.client.ProcessEntry; +import com.walmartlabs.concord.client.StartProcessResponse; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.InputStream; +import java.net.URI; + +import static com.walmartlabs.concord.it.common.ITUtils.archive; +import static com.walmartlabs.concord.it.common.ServerClient.waitForCompletion; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class AnsibleRetryIT extends AbstractServerIT { + + @Test + public void testSaveRetry() throws Exception { + URI uri = ProcessIT.class.getResource("ansibleSaveRetry").toURI(); + byte[] payload = archive(uri, ITConstants.DEPENDENCIES_DIR); + + // start the process + + ProcessApi processApi = new ProcessApi(getApiClient()); + StartProcessResponse spr = start(payload); + + // wait for completion + + ProcessEntry pir = waitForCompletion(getApiClient(), spr.getInstanceId()); + assertEquals(ProcessEntry.StatusEnum.FAILED, pir.getStatus()); + + // retrieve the retry file + + try (InputStream is = processApi.downloadAttachment(pir.getInstanceId(), "hello.retry")) { + assertNotNull(is); + } + } +}