From 03a64e3ed382c15468ae3333870d7e431210949b Mon Sep 17 00:00:00 2001 From: Shawn Seymour Date: Thu, 13 Aug 2020 21:20:25 -0500 Subject: [PATCH] fix: apply should not fail on no changes --- .../devshawn/kafka/gitops/StateManager.java | 2 +- .../kafka/gitops/cli/ApplyCommand.java | 4 + .../gitops/ApplyCommandIntegrationSpec.groovy | 1 + .../gitops/PlanCommandIntegrationSpec.groovy | 10 ++- .../plans/no-changes-apply-output.txt | 3 + src/test/resources/plans/no-changes-plan.json | 81 +++++++++++++++++++ 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/plans/no-changes-apply-output.txt create mode 100644 src/test/resources/plans/no-changes-plan.json diff --git a/src/main/java/com/devshawn/kafka/gitops/StateManager.java b/src/main/java/com/devshawn/kafka/gitops/StateManager.java index 07df7ce7..2a6cc927 100644 --- a/src/main/java/com/devshawn/kafka/gitops/StateManager.java +++ b/src/main/java/com/devshawn/kafka/gitops/StateManager.java @@ -71,8 +71,8 @@ public DesiredStateFile getAndValidateStateFile() { public DesiredPlan plan() { DesiredPlan desiredPlan = generatePlan(); - planManager.validatePlanHasChanges(desiredPlan, managerConfig.isDeleteDisabled()); planManager.writePlanToFile(desiredPlan); + planManager.validatePlanHasChanges(desiredPlan, managerConfig.isDeleteDisabled()); return desiredPlan; } diff --git a/src/main/java/com/devshawn/kafka/gitops/cli/ApplyCommand.java b/src/main/java/com/devshawn/kafka/gitops/cli/ApplyCommand.java index f2e7a46c..2493e8e8 100644 --- a/src/main/java/com/devshawn/kafka/gitops/cli/ApplyCommand.java +++ b/src/main/java/com/devshawn/kafka/gitops/cli/ApplyCommand.java @@ -6,6 +6,7 @@ import com.devshawn.kafka.gitops.domain.plan.DesiredPlan; import com.devshawn.kafka.gitops.exception.KafkaExecutionException; import com.devshawn.kafka.gitops.exception.MissingConfigurationException; +import com.devshawn.kafka.gitops.exception.PlanIsUpToDateException; import com.devshawn.kafka.gitops.exception.ReadPlanInputException; import com.devshawn.kafka.gitops.exception.ValidationException; import com.devshawn.kafka.gitops.service.ParserService; @@ -35,6 +36,9 @@ public Integer call() { DesiredPlan desiredPlan = stateManager.apply(); LogUtil.printApplyOverview(PlanUtil.getOverview(desiredPlan, parent.isDeleteDisabled())); return 0; + } catch (PlanIsUpToDateException ex) { + LogUtil.printNoChangesMessage(); + return 0; } catch (MissingConfigurationException | ReadPlanInputException ex) { LogUtil.printGenericError(ex, true); } catch (ValidationException ex) { diff --git a/src/test/groovy/com/devshawn/kafka/gitops/ApplyCommandIntegrationSpec.groovy b/src/test/groovy/com/devshawn/kafka/gitops/ApplyCommandIntegrationSpec.groovy index 8b90cb78..85d86a13 100644 --- a/src/test/groovy/com/devshawn/kafka/gitops/ApplyCommandIntegrationSpec.groovy +++ b/src/test/groovy/com/devshawn/kafka/gitops/ApplyCommandIntegrationSpec.groovy @@ -98,6 +98,7 @@ class ApplyCommandIntegrationSpec extends Specification { "seed-topic-modification-3" | true "seed-topic-modification-3" | false "seed-acl-exists" | false + "no-changes" | false } void 'test reading missing file throws ReadPlanInputException'() { diff --git a/src/test/groovy/com/devshawn/kafka/gitops/PlanCommandIntegrationSpec.groovy b/src/test/groovy/com/devshawn/kafka/gitops/PlanCommandIntegrationSpec.groovy index ed0f59b0..f261935d 100644 --- a/src/test/groovy/com/devshawn/kafka/gitops/PlanCommandIntegrationSpec.groovy +++ b/src/test/groovy/com/devshawn/kafka/gitops/PlanCommandIntegrationSpec.groovy @@ -187,17 +187,25 @@ class PlanCommandIntegrationSpec extends Specification { ByteArrayOutputStream out = new ByteArrayOutputStream() PrintStream oldOut = System.out System.setOut(new PrintStream(out)) + String planOutputFile = "/tmp/plan.json" String file = TestUtils.getResourceFilePath("plans/${planName}.yaml") MainCommand mainCommand = new MainCommand() CommandLine cmd = new CommandLine(mainCommand) when: - int exitCode = cmd.execute("-f", file, "plan") + int exitCode = cmd.execute("-f", file, "plan", "-o", planOutputFile) then: exitCode == 0 out.toString() == TestUtils.getResourceFileContent("plans/no-changes-output.txt") + when: + String actualPlan = TestUtils.getFileContent(planOutputFile) + String expectedPlan = TestUtils.getResourceFileContent("plans/${planName}-plan.json") + + then: + JSONAssert.assertEquals(expectedPlan, actualPlan, true) + cleanup: System.setOut(oldOut) diff --git a/src/test/resources/plans/no-changes-apply-output.txt b/src/test/resources/plans/no-changes-apply-output.txt new file mode 100644 index 00000000..37ab0dcc --- /dev/null +++ b/src/test/resources/plans/no-changes-apply-output.txt @@ -0,0 +1,3 @@ +Executing apply... + +[SUCCESS] There are no necessary changes; the actual state matches the desired state. diff --git a/src/test/resources/plans/no-changes-plan.json b/src/test/resources/plans/no-changes-plan.json new file mode 100644 index 00000000..1f542019 --- /dev/null +++ b/src/test/resources/plans/no-changes-plan.json @@ -0,0 +1,81 @@ +{ + "topicPlans": [ + { + "name": "delete-topic", + "action": "NO_CHANGE", + "topicDetails": { + "partitions": 1, + "replication": 1, + "configs": {} + }, + "topicConfigPlans": [] + }, + { + "name": "test-topic", + "action": "NO_CHANGE", + "topicDetails": { + "partitions": 1, + "replication": 1, + "configs": {} + }, + "topicConfigPlans": [] + }, + { + "name": "topic-with-configs-1", + "action": "NO_CHANGE", + "topicDetails": { + "partitions": 3, + "replication": 1, + "configs": { + "cleanup.policy": "compact", + "segment.bytes": "100000" + } + }, + "topicConfigPlans": [ + { + "key": "cleanup.policy", + "value": "compact", + "action": "NO_CHANGE" + }, + { + "key": "segment.bytes", + "value": "100000", + "action": "NO_CHANGE" + } + ] + }, + { + "name": "topic-with-configs-2", + "action": "NO_CHANGE", + "topicDetails": { + "partitions": 6, + "replication": 1, + "configs": { + "retention.ms": "60000" + } + }, + "topicConfigPlans": [ + { + "key": "retention.ms", + "value": "60000", + "action": "NO_CHANGE" + } + ] + } + ], + "aclPlans": [ + { + "name": "test-service-0", + "aclDetails": { + "name": "test-topic", + "type": "TOPIC", + "pattern": "LITERAL", + "principal": "User:test", + "host": "*", + "operation": "READ", + "permission": "ALLOW" + }, + "action": "NO_CHANGE" + } + ] +} \ No newline at end of file