Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#313 baton migration for argocd template changes #317

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.boozallen.aissemble.upgrade.migration.v1_9_0;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/

import com.boozallen.aissemble.upgrade.migration.AbstractAissembleMigration;
import com.boozallen.aissemble.upgrade.util.YamlUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.boozallen.aissemble.upgrade.util.YamlUtils.indent;
import static org.technologybrewery.baton.util.FileUtils.readAllFileLines;
import static org.technologybrewery.baton.util.FileUtils.writeFile;

/**
* This migration is responsible for updating the ArgoCD values file to include the syncPolicy in order to enable
* ArgoCD automatically sync an application ability. Ultimately, this enables the ArgoCD sync wave feature to function properly.
*/
public class ArgocdTemplateSyncPolicyMigration extends AbstractAissembleMigration {

protected static final Logger logger = LoggerFactory.getLogger(ArgocdTemplateSyncPolicyMigration.class);
private static final String SYNC_POLICY = "syncPolicy:";
private static final String SPEC = "spec:";

@Override
protected boolean shouldExecuteOnFile(File file) {
boolean shouldExecute = true;
if (file != null && file.exists()) {
try {
List<String> content = readAllFileLines(file);
if (isApplication(content)) {
for (String line: content) {
if (line.trim().equals(SYNC_POLICY)) {
shouldExecute = false;
break;
}
}
} else {
shouldExecute = false;
}
} catch (IOException e) {
logger.error("Failed to check content of file: {}", file.getPath(), e);
}
}
return shouldExecute;
}

@Override
protected boolean performMigration(File file) {
try {
List<String> content = readAllFileLines(file);
List<String> updatedContent = new ArrayList<>();
boolean startSpecConfig = false;
int counter = 0;
int size = content.size();
int indentSpaces = 0;
String specIndent = null;
for (String line: content) {
counter++;
boolean lastItem = counter == size;

line = line.stripTrailing();
if (line.equals(SPEC)) {
startSpecConfig = true;
updatedContent.add(line);

// get the indentSpaces spaces
indentSpaces = YamlUtils.getIndentSpaces(content, counter);
specIndent = indent(1, indentSpaces);
continue;
}

if (startSpecConfig && !StringUtils.isBlank(line) && !line.startsWith(specIndent)) {
updatedContent.addAll(getSyncPolicyHelmFunc(indentSpaces));
startSpecConfig = false;
}
updatedContent.add(line);

if (startSpecConfig && lastItem) {
updatedContent.addAll(getSyncPolicyHelmFunc(indentSpaces));
}
}

writeFile(file, updatedContent);
} catch (Exception e) {
logger.error("Failed to migrate ArgoCD syncPolicy to the template file: {}", file.getPath(), e);
}
return false;
}

private List<String> getSyncPolicyHelmFunc(int indentSpaces) {
ArrayList<String> syncPolicy = new ArrayList();
syncPolicy.add(indent(1, indentSpaces) + "{{- with .Values.spec.syncPolicy }}");
syncPolicy.add(indent(1, indentSpaces) + "syncPolicy:");
syncPolicy.add(indent(2, indentSpaces) + String.format("{{- toYaml . | nindent %d }}", 2 * indentSpaces));
syncPolicy.add(indent(1, indentSpaces) + "{{- end }}");
return syncPolicy;
}

private boolean isApplication(List<String> content) {
final String kindApplication = "kind:application";
String line = "";
for (int i=0; i<content.size(); i++) {
line = content.get(i);
if (line.toLowerCase().startsWith("kind")) {
break;
}
}
line = line.replaceAll("\\s", "");
return line.equalsIgnoreCase(kindApplication);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package com.boozallen.aissemble.upgrade.migration.v1_9_0;

/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/

import com.boozallen.aissemble.upgrade.migration.AbstractAissembleMigration;
import com.boozallen.aissemble.upgrade.util.YamlUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.technologybrewery.baton.util.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import static com.boozallen.aissemble.upgrade.util.YamlUtils.indent;
/**
* This migration is responsible for updating the ArgoCD template file to include the syncPolicy helm function in order to enable
* ArgoCD automatically sync an application ability. Ultimately, this enables the ArgoCD sync wave feature to function properly.
*/
public class ArgocdValueFileSyncPolicyMigration extends AbstractAissembleMigration {

protected static final Logger logger = LoggerFactory.getLogger(ArgocdValueFileSyncPolicyMigration.class);
private static final String CREATE_NAMESPACE_OPTION = "CreateNamespace";
private static final String APPLY_OUT_OF_SYNC_OPTION = "ApplyOutOfSyncOnly";
private static final String AUTOMATED = "automated";
private static final String SPEC = "spec:";

@Override
protected boolean shouldExecuteOnFile(File file) {
try {
return getMigratedSyncPolicyContent(file, 2).size() > 0;
} catch (IOException e) {
logger.error("Failed to check content of file: {}", file.getPath(), e);
}
return false;
}

@Override
protected boolean performMigration(File file) {
try {
List<String> content = FileUtils.readAllFileLines(file);
List<String> updatedContent = new ArrayList<>();

String syncPolicy = null;
String syncPolicyIndent = null;
String specIndent = null;
String line;
boolean inSpecConfig = false;
boolean inSyncPolicyConfig = false;
boolean skip;
boolean lastItem;
int size = content.size();
int indentSpaces = 0;

for (int i=0; i<size; i++) {
line = content.get(i);
lastItem = i == size -1;
line = line.stripTrailing();

if (line.equals(SPEC)) {
inSpecConfig = true;
// get the indentSpaces spaces
indentSpaces = YamlUtils.getIndentSpaces(content, i + 1);
syncPolicy = indent(1, indentSpaces) + "syncPolicy:";
syncPolicyIndent = indent(2, indentSpaces);
specIndent = indent(1, indentSpaces);
}

if (inSpecConfig && line.equals(syncPolicy)) {
inSyncPolicyConfig = true;
skip = true;
} else {
skip = inSyncPolicyConfig && line.startsWith(syncPolicyIndent);
}

if (inSpecConfig && !line.startsWith(specIndent) && !line.equals(SPEC) && !StringUtils.isBlank(line)) {
updatedContent.addAll(getMigratedSyncPolicyContent(file, indentSpaces));
inSpecConfig = false;
}

if (!skip) {
updatedContent.add(line);
}

if (inSpecConfig && lastItem) {
updatedContent.addAll(getMigratedSyncPolicyContent(file, indentSpaces));
}
}
// this is set for empty values file
if (!updatedContent.contains(SPEC)) {
updatedContent.addAll(getMigratedSyncPolicyContent(file, 2));
}
FileUtils.writeFile(file, updatedContent);
} catch (Exception e) {
logger.error("Failed to migrate ArgoCD syncPolicy to the value file: {}", file.getPath(), e);
}
return false;
}

private List<String> getMigratedSyncPolicyContent(File file, int indentSpace) throws IOException {

YamlUtils.YamlObject yaml = YamlUtils.loadYaml(file);
if (!yaml.isEmpty() && yaml.containsKey("spec")) {
YamlUtils.YamlObject spec = yaml.getObject("spec");
if (spec.containsKey("syncPolicy")) {
YamlUtils.YamlObject syncPolicy = spec.getObject("syncPolicy");
if (syncPolicy.containsKey("syncOptions")) {
List<String> syncOptions = syncPolicy.getListOfStrings("syncOptions");

if (containsExpectedSyncOptions(syncOptions) && syncPolicy.containsKey(AUTOMATED)) {
return new ArrayList<>();
}

return generateSyncPolicyContent(syncOptions, syncPolicy, indentSpace);
}
}
return generateSyncPolicyContent(new ArrayList<>(), new YamlUtils.YamlObject(new HashMap<>()), indentSpace);
}
List<String> syncPolicyContent = generateSyncPolicyContent(new ArrayList<>(), new YamlUtils.YamlObject(new HashMap<>()), indentSpace);
syncPolicyContent.add(0, SPEC);
return syncPolicyContent;
}

private boolean containsExpectedSyncOptions(List<String> options) {
return options.stream().filter(line -> (line.contains(CREATE_NAMESPACE_OPTION) || line.contains(APPLY_OUT_OF_SYNC_OPTION))).count() >=2;
}

private List<String> generateSyncPolicyContent(List<String> options, YamlUtils.YamlObject syncPolicy, int indentSpaces) {
List<String> content = new ArrayList<>();
content.add(indent(1, indentSpaces) + "syncPolicy:");
content.add(indent(2, indentSpaces) + "syncOptions:");
content.add(indent(3, indentSpaces) + "- CreateNamespace=true");
content.add(indent(3, indentSpaces) + "- ApplyOutOfSyncOnly=true");
for (String option: options) {
if (!option.contains(CREATE_NAMESPACE_OPTION) && !option.contains(APPLY_OUT_OF_SYNC_OPTION)) {
content.add(String.format("%s- %s", indent(3, indentSpaces), option));
}
}
content.addAll(generateAutomatedSyncPolicy(syncPolicy, indentSpaces));
return content;
}

private List<String> generateAutomatedSyncPolicy(YamlUtils.YamlObject syncPolicy, int indentSpaces) {
List<String> automated = new ArrayList<>();
if (syncPolicy.containsKey(AUTOMATED)) {
YamlUtils.YamlObject automatedYaml = syncPolicy.getObject(AUTOMATED);
Set<String> keys = automatedYaml.keySet();
if (keys != null && keys.size() > 0) {
automated.add(indent(2, indentSpaces) + "automated:");
for (String key : keys) {
automated.add(String.format("%s%s: %s", indent(3, indentSpaces), key, automatedYaml.get(key)));
}
return automated;
}
}

automated.add(indent(2, indentSpaces) + "automated: {}");
return automated;
}

}
Loading