Skip to content

Commit 2dedeba

Browse files
authored
feat: exclude unchanged resources from plan file (#37)
1 parent 99dd5e6 commit 2dedeba

18 files changed

+420
-110
lines changed

src/main/java/com/devshawn/kafka/gitops/cli/AccountCommand.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import com.devshawn.kafka.gitops.MainCommand;
44
import com.devshawn.kafka.gitops.StateManager;
55
import com.devshawn.kafka.gitops.config.ManagerConfig;
6-
import com.devshawn.kafka.gitops.exception.*;
6+
import com.devshawn.kafka.gitops.exception.ConfluentCloudException;
7+
import com.devshawn.kafka.gitops.exception.KafkaExecutionException;
8+
import com.devshawn.kafka.gitops.exception.MissingConfigurationException;
9+
import com.devshawn.kafka.gitops.exception.ValidationException;
10+
import com.devshawn.kafka.gitops.exception.WritePlanOutputException;
711
import com.devshawn.kafka.gitops.service.ParserService;
812
import com.devshawn.kafka.gitops.util.LogUtil;
913
import picocli.CommandLine;
@@ -39,6 +43,7 @@ private ManagerConfig generateStateManagerConfig() {
3943
return new ManagerConfig.Builder()
4044
.setVerboseRequested(parent.isVerboseRequested())
4145
.setDeleteDisabled(parent.isDeleteDisabled())
46+
.setIncludeUnchangedEnabled(false)
4247
.setStateFile(parent.getFile())
4348
.build();
4449
}

src/main/java/com/devshawn/kafka/gitops/cli/ApplyCommand.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ private ManagerConfig generateStateManagerConfig() {
5353
return new ManagerConfig.Builder()
5454
.setVerboseRequested(parent.isVerboseRequested())
5555
.setDeleteDisabled(parent.isDeleteDisabled())
56+
.setIncludeUnchangedEnabled(false)
5657
.setStateFile(parent.getFile())
5758
.setNullablePlanFile(planFile)
5859
.build();

src/main/java/com/devshawn/kafka/gitops/cli/PlanCommand.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public class PlanCommand implements Callable<Integer> {
2323
description = "Specify the output file for the plan.")
2424
private File outputFile;
2525

26+
@CommandLine.Option(names = {"--include-unchanged"}, description = "Include unchanged resources in the plan file.")
27+
private boolean includeUnchanged = false;
28+
2629
@CommandLine.ParentCommand
2730
private MainCommand parent;
2831

@@ -54,6 +57,7 @@ private ManagerConfig generateStateManagerConfig() {
5457
return new ManagerConfig.Builder()
5558
.setVerboseRequested(parent.isVerboseRequested())
5659
.setDeleteDisabled(parent.isDeleteDisabled())
60+
.setIncludeUnchangedEnabled(includeUnchanged)
5761
.setStateFile(parent.getFile())
5862
.setNullablePlanFile(outputFile)
5963
.build();

src/main/java/com/devshawn/kafka/gitops/cli/ValidateCommand.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ private ManagerConfig generateStateManagerConfig() {
3636
return new ManagerConfig.Builder()
3737
.setVerboseRequested(parent.isVerboseRequested())
3838
.setDeleteDisabled(parent.isDeleteDisabled())
39+
.setIncludeUnchangedEnabled(false)
3940
.setStateFile(parent.getFile())
4041
.build();
4142
}

src/main/java/com/devshawn/kafka/gitops/config/ManagerConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public interface ManagerConfig {
1414

1515
boolean isDeleteDisabled();
1616

17+
boolean isIncludeUnchangedEnabled();
18+
1719
File getStateFile();
1820

1921
Optional<File> getPlanFile();

src/main/java/com/devshawn/kafka/gitops/domain/plan/DesiredPlan.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.devshawn.kafka.gitops.domain.plan;
22

3+
import com.devshawn.kafka.gitops.enums.PlanAction;
34
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
45
import org.inferred.freebuilder.FreeBuilder;
56

@@ -13,6 +14,13 @@ public interface DesiredPlan {
1314

1415
List<AclPlan> getAclPlans();
1516

17+
default DesiredPlan toChangesOnlyPlan() {
18+
DesiredPlan.Builder builder = new DesiredPlan.Builder();
19+
getTopicPlans().stream().filter(it -> !it.getAction().equals(PlanAction.NO_CHANGE)).map(TopicPlan::toChangesOnlyPlan).forEach(builder::addTopicPlans);
20+
getAclPlans().stream().filter(it -> !it.getAction().equals(PlanAction.NO_CHANGE)).forEach(builder::addAclPlans);
21+
return builder.build();
22+
}
23+
1624
class Builder extends DesiredPlan_Builder {
1725
}
1826
}

src/main/java/com/devshawn/kafka/gitops/domain/plan/TopicPlan.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ public interface TopicPlan {
2020

2121
List<TopicConfigPlan> getTopicConfigPlans();
2222

23+
default TopicPlan toChangesOnlyPlan() {
24+
TopicPlan.Builder builder = new TopicPlan.Builder().setName(getName()).setAction(getAction()).setTopicDetails(getTopicDetails());
25+
getTopicConfigPlans().stream().filter(it -> !it.getAction().equals(PlanAction.NO_CHANGE)).forEach(builder::addTopicConfigPlans);
26+
return builder.build();
27+
}
28+
2329
class Builder extends TopicPlan_Builder {
2430
}
2531
}

src/main/java/com/devshawn/kafka/gitops/manager/PlanManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,9 @@ public void writePlanToFile(DesiredPlan desiredPlan) {
198198
if (managerConfig.getPlanFile().isPresent()) {
199199
try {
200200
managerConfig.getPlanFile().get().createNewFile();
201+
DesiredPlan outputPlan = managerConfig.isIncludeUnchangedEnabled() ? desiredPlan : desiredPlan.toChangesOnlyPlan();
201202
FileWriter writer = new FileWriter(managerConfig.getPlanFile().get());
202-
writer.write(objectMapper.writeValueAsString(desiredPlan));
203+
writer.write(objectMapper.writeValueAsString(outputPlan));
203204
writer.close();
204205
} catch (IOException ex) {
205206
throw new WritePlanOutputException(ex.getMessage());

src/test/groovy/com/devshawn/kafka/gitops/ApplyCommandIntegrationSpec.groovy

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,14 @@ class ApplyCommandIntegrationSpec extends Specification {
9292
System.setOut(oldOut)
9393

9494
where:
95-
planFile | deleteDisabled
96-
"seed-topic-modification" | true
97-
"seed-topic-modification" | false
98-
"seed-topic-modification-3" | true
99-
"seed-topic-modification-3" | false
100-
"seed-acl-exists" | false
101-
"no-changes" | false
95+
planFile | deleteDisabled
96+
"seed-topic-modification" | true
97+
"seed-topic-modification" | false
98+
"seed-topic-modification-3" | true
99+
"seed-topic-modification-3" | false
100+
"seed-acl-exists" | false
101+
"no-changes" | false
102+
"no-changes-include-unchanged" | false
102103
}
103104

104105
void 'test reading missing file throws ReadPlanInputException'() {

src/test/groovy/com/devshawn/kafka/gitops/PlanCommandIntegrationSpec.groovy

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,40 @@ class PlanCommandIntegrationSpec extends Specification {
108108
"seed-blacklist-topics" | false
109109
}
110110

111+
void 'test include unchanged flag - #planNam #includeUnchanged'() {
112+
setup:
113+
TestUtils.cleanUpCluster()
114+
TestUtils.seedCluster()
115+
String planOutputFile = "/tmp/plan.json"
116+
String file = TestUtils.getResourceFilePath("plans/${planName}.yaml")
117+
MainCommand mainCommand = new MainCommand()
118+
CommandLine cmd = new CommandLine(mainCommand)
119+
120+
when:
121+
int exitCode = -1
122+
if (includeUnchanged) {
123+
exitCode = cmd.execute("-f", file, "plan", "--include-unchanged", "-o", planOutputFile)
124+
} else {
125+
exitCode = cmd.execute("-f", file, "plan", "-o", planOutputFile)
126+
}
127+
128+
then:
129+
exitCode == 0
130+
131+
when:
132+
String expected = includeUnchanged ? "${planName}-include-unchanged" : planName
133+
String actualPlan = TestUtils.getFileContent(planOutputFile)
134+
String expectedPlan = TestUtils.getResourceFileContent("plans/${expected}-plan.json")
135+
136+
then:
137+
JSONAssert.assertEquals(expectedPlan, actualPlan, true)
138+
139+
where:
140+
planName | includeUnchanged
141+
"seed-basic" | false
142+
"seed-basic" | true
143+
}
144+
111145
void 'test invalid plans - #planName'() {
112146
setup:
113147
ByteArrayOutputStream err = new ByteArrayOutputStream()
@@ -187,7 +221,7 @@ class PlanCommandIntegrationSpec extends Specification {
187221
System.setOut(oldOut)
188222
}
189223

190-
void 'test plan that has no changes'() {
224+
void 'test plan that has no changes - #includeUnchanged'() {
191225
setup:
192226
TestUtils.cleanUpCluster()
193227
TestUtils.seedCluster()
@@ -200,15 +234,21 @@ class PlanCommandIntegrationSpec extends Specification {
200234
CommandLine cmd = new CommandLine(mainCommand)
201235

202236
when:
203-
int exitCode = cmd.execute("-f", file, "plan", "-o", planOutputFile)
237+
int exitCode = -1
238+
if (includeUnchanged) {
239+
exitCode = cmd.execute("-f", file, "plan", "--include-unchanged", "-o", planOutputFile)
240+
} else {
241+
exitCode = cmd.execute("-f", file, "plan", "-o", planOutputFile)
242+
}
204243

205244
then:
206245
exitCode == 0
207246
out.toString() == TestUtils.getResourceFileContent("plans/no-changes-output.txt")
208247

209248
when:
249+
String expected = includeUnchanged ? "${planName}-include-unchanged" : planName
210250
String actualPlan = TestUtils.getFileContent(planOutputFile)
211-
String expectedPlan = TestUtils.getResourceFileContent("plans/${planName}-plan.json")
251+
String expectedPlan = TestUtils.getResourceFileContent("plans/${expected}-plan.json")
212252

213253
then:
214254
JSONAssert.assertEquals(expectedPlan, actualPlan, true)
@@ -217,6 +257,8 @@ class PlanCommandIntegrationSpec extends Specification {
217257
System.setOut(oldOut)
218258

219259
where:
220-
planName << ["no-changes"]
260+
planName | includeUnchanged
261+
"no-changes" | false
262+
"no-changes" | true
221263
}
222264
}

0 commit comments

Comments
 (0)