Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
156 changes: 152 additions & 4 deletions source/Calamari.Tests/ArgoCD/ArgoCDFilesUpdatedReporterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void ReportDeployments_WithNoUpdatedApplications_WritesNoServiceMessages(
new("gateway1", new ApplicationName("app1"), 2, 2, [], [], [])
};

reporter.ReportDeployments(applicationResults);
reporter.ReportFilesUpdated(applicationResults);

var messages = log.ServiceMessages;
messages.Should().BeEmpty();
Expand All @@ -38,7 +38,7 @@ public void ReportDeployments_WithSingleUpdatedApplication_WritesOneServiceMessa
new("gateway1", new ApplicationName("app1"), 2, 2, [new UpdatedSourceDetail("abc123", 0, [], [])], [], [])
};

reporter.ReportDeployments(applicationResults);
reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Expand All @@ -64,7 +64,7 @@ public void ReportDeployments_WithMultipleUpdatedApplications_WritesMultipleServ
new("gateway2", new ApplicationName("app2"), 1, 1, [new UpdatedSourceDetail("def456", 0, [], [])], [], [])
};

reporter.ReportDeployments(applicationResults);
reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().BeEquivalentTo([
new
Expand All @@ -90,6 +90,154 @@ public void ReportDeployments_WithMultipleUpdatedApplications_WritesMultipleServ
]);
}

[Test]
public void ReportDeployments_WithReplacedFiles_IncludesReplacedFilesInSources()
{
var log = new InMemoryLog();
var reporter = new ArgoCDFilesUpdatedReporter(log);

var applicationResults = new List<ProcessApplicationResult>
{
new("gateway1", new ApplicationName("app1"), 2, 2,
[new UpdatedSourceDetail("abc123", 0, [new FilePathContent("values.yaml", "image: nginx:latest")], [])],
[], [])
};

reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Name = "argocd-files-updated",
Properties = new Dictionary<string, string>
{
["gatewayId"] = "gateway1",
["applicationName"] = "app1",
["sources"] = "[{\"CommitSha\":\"abc123\",\"SourceIndex\":0,\"ReplacedFiles\":[{\"FilePath\":\"values.yaml\",\"Content\":\"image: nginx:latest\"}],\"PatchedFiles\":[]}]"
}
});
}

[Test]
public void ReportDeployments_WithPatchedFiles_IncludesPatchedFilesInSources()
{
var log = new InMemoryLog();
var reporter = new ArgoCDFilesUpdatedReporter(log);

var applicationResults = new List<ProcessApplicationResult>
{
new("gateway1", new ApplicationName("app1"), 1, 1,
[new UpdatedSourceDetail("def456", 0, [], [new FilePathContent("kustomization.yaml", "images:\n- name: nginx")])],
[], [])
};

reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Name = "argocd-files-updated",
Properties = new Dictionary<string, string>
{
["gatewayId"] = "gateway1",
["applicationName"] = "app1",
["sources"] = "[{\"CommitSha\":\"def456\",\"SourceIndex\":0,\"ReplacedFiles\":[],\"PatchedFiles\":[{\"FilePath\":\"kustomization.yaml\",\"Content\":\"images:\\n- name: nginx\"}]}]"
}
});
}

[Test]
public void ReportDeployments_WithBothReplacedAndPatchedFiles_IncludesBothInSources()
{
var log = new InMemoryLog();
var reporter = new ArgoCDFilesUpdatedReporter(log);

var applicationResults = new List<ProcessApplicationResult>
{
new("gateway1", new ApplicationName("app1"), 2, 2,
[new UpdatedSourceDetail("abc123", 0,
[new FilePathContent("values.yaml", "image: nginx:latest")],
[new FilePathContent("kustomization.yaml", "images:\n- name: nginx")])],
[], [])
};

reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Name = "argocd-files-updated",
Properties = new Dictionary<string, string>
{
["gatewayId"] = "gateway1",
["applicationName"] = "app1",
["sources"] = "[{\"CommitSha\":\"abc123\",\"SourceIndex\":0,\"ReplacedFiles\":[{\"FilePath\":\"values.yaml\",\"Content\":\"image: nginx:latest\"}],\"PatchedFiles\":[{\"FilePath\":\"kustomization.yaml\",\"Content\":\"images:\\n- name: nginx\"}]}]"
}
});
}

[Test]
public void ReportDeployments_WithMultipleReplacedAndPatchedFiles_IncludesAllFilesInSources()
{
var log = new InMemoryLog();
var reporter = new ArgoCDFilesUpdatedReporter(log);

var applicationResults = new List<ProcessApplicationResult>
{
new("gateway1", new ApplicationName("app1"), 2, 2,
[new UpdatedSourceDetail("abc123", 0,
[
new FilePathContent("values.yaml", "image: nginx:latest"),
new FilePathContent("values-prod.yaml", "replicas: 3")
],
[
new FilePathContent("kustomization.yaml", "images:\n- name: nginx"),
new FilePathContent("patch.yaml", "spec:\n replicas: 3")
])],
[], [])
};

reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Name = "argocd-files-updated",
Properties = new Dictionary<string, string>
{
["gatewayId"] = "gateway1",
["applicationName"] = "app1",
["sources"] = "[{\"CommitSha\":\"abc123\",\"SourceIndex\":0,\"ReplacedFiles\":[{\"FilePath\":\"values.yaml\",\"Content\":\"image: nginx:latest\"},{\"FilePath\":\"values-prod.yaml\",\"Content\":\"replicas: 3\"}],\"PatchedFiles\":[{\"FilePath\":\"kustomization.yaml\",\"Content\":\"images:\\n- name: nginx\"},{\"FilePath\":\"patch.yaml\",\"Content\":\"spec:\\n replicas: 3\"}]}]"
}
});
}

[Test]
public void ReportDeployments_WithMultipleSourcesWithFiles_IncludesAllSourcesInSources()
{
var log = new InMemoryLog();
var reporter = new ArgoCDFilesUpdatedReporter(log);

var applicationResults = new List<ProcessApplicationResult>
{
new("gateway1", new ApplicationName("app1"), 2, 2,
[
new UpdatedSourceDetail("abc123", 0, [new FilePathContent("values.yaml", "image: nginx:latest")], []),
new UpdatedSourceDetail("abc123", 1, [], [new FilePathContent("kustomization.yaml", "images:\n- name: redis")])
],
[], [])
};

reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Name = "argocd-files-updated",
Properties = new Dictionary<string, string>
{
["gatewayId"] = "gateway1",
["applicationName"] = "app1",
["sources"] = "[{\"CommitSha\":\"abc123\",\"SourceIndex\":0,\"ReplacedFiles\":[{\"FilePath\":\"values.yaml\",\"Content\":\"image: nginx:latest\"}],\"PatchedFiles\":[]},{\"CommitSha\":\"abc123\",\"SourceIndex\":1,\"ReplacedFiles\":[],\"PatchedFiles\":[{\"FilePath\":\"kustomization.yaml\",\"Content\":\"images:\\n- name: redis\"}]}]"
}
});
}

[Test]
public void ReportDeployments_WithMixedUpdatedAndNonUpdatedApplications_WritesOnlyUpdatedMessages()
{
Expand All @@ -103,7 +251,7 @@ public void ReportDeployments_WithMixedUpdatedAndNonUpdatedApplications_WritesOn
new("gateway3", new ApplicationName("app3"), 1, 1, [], [], [])
};

reporter.ReportDeployments(applicationResults);
reporter.ReportFilesUpdated(applicationResults);

log.ServiceMessages.Should().ContainSingle().Which.Should().BeEquivalentTo(new
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class UpdateArgoCDAppImagesInstallConventionHelmTests
";

const string GatewayId = "Gateway1";
IArgoCDFilesUpdatedReporter deploymentReporter;

UpdateArgoCDAppImagesInstallConvention CreateConvention()
{
Expand All @@ -63,14 +64,15 @@ UpdateArgoCDAppImagesInstallConvention CreateConvention()
argoCdApplicationManifestParser,
Substitute.For<IGitVendorAgnosticApiAdapterFactory>(),
new SystemClock(),
Substitute.For<IArgoCDFilesUpdatedReporter>(),
deploymentReporter,
new ArgoCDOutputVariablesWriter(log, nonSensitiveCalamariVariables));
}

[SetUp]
public void Init()
{
log = new InMemoryLog();
deploymentReporter = Substitute.For<IArgoCDFilesUpdatedReporter>();
tempDirectory = fileSystem.CreateTemporaryDirectory();

originRepo = RepositoryHelpers.CreateBareRepository(OriginPath);
Expand Down Expand Up @@ -1319,6 +1321,71 @@ public void RefSourceWithHelmImageMatchesAndPath_IgnoresFilesUnderPath()
AssertOutputVariables(matchingApplicationTotalSourceCounts: "2");
}

[Test]
public void DirectorySource_ImageMatches_ReportsDeploymentWithNonEmptyCommitSha()
{
//Arrange
const string multiImageValuesFile = """
image1:
name: nginx:1.22
image2:
name: alpine
tag: latest
""";
originRepo.AddFilesToBranch(argoCDBranchName, ("files/values.yml", multiImageValuesFile));

argoCdApplicationFromYaml.Metadata.Annotations[ArgoCDConstants.Annotations.OctopusImageReplacementPathsKey(null)] = "{{ .Values.image1.name }}, {{ .Values.image2.name }}:{{ .Values.image2.tag }}";

var updater = CreateConvention();
var variables = new CalamariVariables
{
[ProjectVariables.Slug] = ProjectSlug,
[DeploymentEnvironment.Slug] = EnvironmentSlug,
[PackageVariables.IndexedImage("nginx")] = "nginx:1.27.1",
[PackageVariables.IndexedPackagePurpose("nginx")] = "DockerImageReference",
[PackageVariables.IndexedImage("alpine")] = "alpine:2.2",
[PackageVariables.IndexedPackagePurpose("alpine")] = "DockerImageReference",
};

//Act
var runningDeployment = new RunningDeployment(null, variables);
runningDeployment.CurrentDirectoryProvider = DeploymentWorkingDirectory.StagingDirectory;
runningDeployment.StagingDirectory = tempDirectory;

IReadOnlyList<ProcessApplicationResult> capturedResults = null;
deploymentReporter.ReportFilesUpdated(Arg.Do<IReadOnlyList<ProcessApplicationResult>>(x => capturedResults = x));

updater.Install(runningDeployment);

//Assert
var updatedValuesFile = """
image1:
name: nginx:1.27.1
image2:
name: alpine
tag: 2.2
""";

var resultRepo = RepositoryHelpers.CloneOrigin(tempDirectory, OriginPath, argoCDBranchName);
AssertFileContents(resultRepo, "files/values.yml", updatedValuesFile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to assert the file looks as we expected? I would have thought this would be handled by another test already and this could focus on the jsonpatch info.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a good call out for a copy and paste job. I'll scope down those assertions


AssertOutputVariables(updatedImages: 2);

// Assert
using var scope = new AssertionScope();
capturedResults.Should().NotBeNull();
var actual = capturedResults.Single();
actual.UpdatedImages.Should().BeEquivalentTo(["{ Reference = nginx:1.27.1, Comparison = ContainerImageComparison { RegistryMatch = True, ImageNameMatch = True, TagMatch = False } }", "{ Reference = alpine:2.2, Comparison = ContainerImageComparison { RegistryMatch = True, ImageNameMatch = True, TagMatch = False } }"]);
actual.GitReposUpdated.Should().HaveCount(1);
actual.UpdatedSourceDetails.Should().HaveCount(1);

var sourceDetails = actual.UpdatedSourceDetails.First();
sourceDetails.CommitSha.Should().HaveLength(40);
sourceDetails.ReplacedFiles.Should().BeEmpty();
// TODO: fill in with json patch
// sourceDetails.PatchedFiles.Should().BeEquivalentTo([new FilePathContent("", "")]);
}

void AssertFileContents(string clonedRepoPath, string relativeFilePath, string expectedContent)
{
var absolutePath = Path.Combine(clonedRepoPath, relativeFilePath);
Expand Down
Loading