Skip to content

Commit 97ca98d

Browse files
Initial set of changes to allow control of whether we generate output variables for S3 commands
1 parent 9bd1711 commit 97ca98d

3 files changed

Lines changed: 121 additions & 14 deletions

File tree

source/Calamari.Aws/Commands/UploadAwsS3Command.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class UploadAwsS3Command : Command
3131
PathToPackage pathToPackage;
3232
string bucket;
3333
string targetMode;
34+
bool includeOutputVariables = true;
3435

3536
public UploadAwsS3Command(
3637
ILog log,
@@ -50,6 +51,7 @@ IStructuredConfigVariablesService structuredConfigVariablesService
5051
Options.Add("package=", "Path to the package to extract that contains the package.", v => pathToPackage = new PathToPackage(Path.GetFullPath(v)));
5152
Options.Add("bucket=", "The bucket to use", v => bucket = v);
5253
Options.Add("targetMode=", "Whether the entire package or files within the package should be uploaded to the s3 bucket", v => targetMode = v);
54+
Options.Add("includeOutputVariables=", "True to generate output variables for uploaded files (default), False to skip output variable generation.", v => includeOutputVariables = !bool.FalseString.Equals(v, StringComparison.OrdinalIgnoreCase));
5355
}
5456

5557
public override int Execute(string[] commandLineArguments)
@@ -82,7 +84,8 @@ public override int Execute(string[] commandLineArguments)
8284
new VariableS3TargetOptionsProvider(variables),
8385
bucketKeyProvider,
8486
substituteInFiles,
85-
structuredConfigVariablesService
87+
structuredConfigVariablesService,
88+
includeOutputVariables
8689
)
8790
};
8891

source/Calamari.Aws/Deployment/Conventions/UploadAwsS3Convention.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class UploadAwsS3Convention : IInstallConvention
4444
readonly ISubstituteInFiles substituteInFiles;
4545
readonly IStructuredConfigVariablesService structuredConfigVariablesService;
4646
private readonly bool md5HashSupported;
47+
readonly bool includeOutputVariables;
4748

4849
private static readonly HashSet<S3CannedACL> CannedAcls = new HashSet<S3CannedACL>(ConstantHelpers.GetConstantValues<S3CannedACL>());
4950

@@ -56,7 +57,8 @@ public UploadAwsS3Convention(
5657
IProvideS3TargetOptions optionsProvider,
5758
IBucketKeyProvider bucketKeyProvider,
5859
ISubstituteInFiles substituteInFiles,
59-
IStructuredConfigVariablesService structuredConfigVariablesService
60+
IStructuredConfigVariablesService structuredConfigVariablesService,
61+
bool includeOutputVariables
6062
)
6163
{
6264
this.log = log;
@@ -69,6 +71,7 @@ IStructuredConfigVariablesService structuredConfigVariablesService
6971
this.substituteInFiles = substituteInFiles;
7072
this.structuredConfigVariablesService = structuredConfigVariablesService;
7173
this.md5HashSupported = HashCalculator.IsAvailableHashingAlgorithm(MD5.Create);
74+
this.includeOutputVariables = includeOutputVariables;
7275
}
7376

7477
private static string ExceptionMessageWithFilePath(PutObjectRequest request, Exception exception)
@@ -121,9 +124,15 @@ private async Task InstallAsync(RunningDeployment deployment)
121124
(await UploadAll(options, Factory, deployment)).Tee(responses =>
122125
{
123126
var results = responses.Where(z => z.IsSuccess()).ToArray();
127+
128+
if (!includeOutputVariables)
129+
{
130+
return;
131+
}
132+
124133
if (targetMode == S3TargetMode.EntirePackage && results.FirstOrDefault() != null)
125134
{
126-
SetOutputVariables(deployment, results.FirstOrDefault());
135+
SetOutputVariables(deployment, results.FirstOrDefault(), "");
127136
}
128137
else if (targetMode == S3TargetMode.FileSelections)
129138
{

source/Calamari.Tests/AWS/UploadAwsS3CommandFixture.cs

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public async Task UploadPackage1()
8585
}
8686
};
8787

88-
var prefix = await Upload("Package1", fileSelections);
88+
var (prefix, _) = await Upload("Package1", fileSelections);
8989

9090
await Validate(async client =>
9191
{
@@ -95,6 +95,93 @@ await Validate(async client =>
9595
});
9696
}
9797

98+
[Test]
99+
public async Task UploadPackageWithIncludeOutputVariablesEnabled()
100+
{
101+
var packageOptions = new List<S3TargetPropertiesBase>
102+
{
103+
new S3PackageOptions
104+
{
105+
StorageClass = "STANDARD",
106+
CannedAcl = "private",
107+
BucketKeyBehaviour = BucketKeyBehaviourType.Filename,
108+
}
109+
};
110+
111+
var (prefix, log) = await Upload("Package3", packageOptions, null, S3TargetMode.EntirePackage, true);
112+
113+
// Verify S3-specific output variables ARE set
114+
var logMessages = log.Messages.Select(m => m.FormattedMessage).ToList();
115+
logMessages.Should().Contain(m => m.Contains("Saving object version id to variable"));
116+
logMessages.Should().Contain(m => m.Contains("Saving bucket key to variable"));
117+
logMessages.Should().Contain(m => m.Contains("Saving object S3 URI to variable"));
118+
logMessages.Should().Contain(m => m.Contains("Saving object URI to variable"));
119+
logMessages.Should().Contain(m => m.Contains("Saving object ARN to variable"));
120+
121+
await Validate(async client =>
122+
{
123+
await client.GetObjectAsync(bucketName, $"{prefix}Package3.1.0.0.zip");
124+
});
125+
}
126+
127+
[Test]
128+
public async Task UploadPackageWithIncludeOutputVariablesDisabled()
129+
{
130+
var packageOptions = new List<S3TargetPropertiesBase>
131+
{
132+
new S3PackageOptions
133+
{
134+
StorageClass = "STANDARD",
135+
CannedAcl = "private",
136+
BucketKeyBehaviour = BucketKeyBehaviourType.Filename,
137+
}
138+
};
139+
140+
var (prefix, log) = await Upload("Package3", packageOptions, null, S3TargetMode.EntirePackage, false);
141+
142+
// Verify S3-specific output variables are NOT set
143+
var logMessages = log.Messages.Select(m => m.FormattedMessage).ToList();
144+
logMessages.Should().NotContain(m => m.Contains("Saving object version id to variable"));
145+
logMessages.Should().NotContain(m => m.Contains("Saving bucket key to variable"));
146+
logMessages.Should().NotContain(m => m.Contains("Saving object S3 URI to variable"));
147+
logMessages.Should().NotContain(m => m.Contains("Saving object URI to variable"));
148+
logMessages.Should().NotContain(m => m.Contains("Saving object ARN to variable"));
149+
150+
await Validate(async client =>
151+
{
152+
await client.GetObjectAsync(bucketName, $"{prefix}Package3.1.0.0.zip");
153+
});
154+
}
155+
156+
[Test]
157+
public async Task UploadPackageWithIncludeOutputVariablesDefaultBehavior()
158+
{
159+
var packageOptions = new List<S3TargetPropertiesBase>
160+
{
161+
new S3PackageOptions
162+
{
163+
StorageClass = "STANDARD",
164+
CannedAcl = "private",
165+
BucketKeyBehaviour = BucketKeyBehaviourType.Filename,
166+
}
167+
};
168+
169+
var (prefix, log) = await Upload("Package3", packageOptions, null, S3TargetMode.EntirePackage);
170+
171+
// Verify default behavior generates all output variables (backward compatible)
172+
var logMessages = log.Messages.Select(m => m.FormattedMessage).ToList();
173+
logMessages.Should().Contain(m => m.Contains("Saving object version id to variable"));
174+
logMessages.Should().Contain(m => m.Contains("Saving bucket key to variable"));
175+
logMessages.Should().Contain(m => m.Contains("Saving object S3 URI to variable"));
176+
logMessages.Should().Contain(m => m.Contains("Saving object URI to variable"));
177+
logMessages.Should().Contain(m => m.Contains("Saving object ARN to variable"));
178+
179+
await Validate(async client =>
180+
{
181+
await client.GetObjectAsync(bucketName, $"{prefix}Package3.1.0.0.zip");
182+
});
183+
}
184+
98185
[Test]
99186
public async Task UploadPackage2()
100187
{
@@ -109,7 +196,7 @@ public async Task UploadPackage2()
109196
}
110197
};
111198

112-
var prefix = await Upload("Package2", fileSelections);
199+
var (prefix, _) = await Upload("Package2", fileSelections);
113200

114201
await Validate(async client =>
115202
{
@@ -146,7 +233,7 @@ public async Task UploadPackage3()
146233
var variables = new CalamariVariables();
147234
variables.Set("Property1:Property2:Value", "InjectedValue");
148235

149-
var prefix = await Upload("Package3", fileSelections, variables);
236+
var (prefix, _) = await Upload("Package3", fileSelections, variables);
150237

151238
await Validate(async client =>
152239
{
@@ -173,7 +260,7 @@ public async Task UploadPackage3Complete()
173260
var variables = new CalamariVariables();
174261
variables.Set("Property1:Property2:Value", "InjectedValue");
175262

176-
var prefix = await Upload("Package3", packageOptions, variables, S3TargetMode.EntirePackage);
263+
var (prefix, _) = await Upload("Package3", packageOptions, variables, S3TargetMode.EntirePackage);
177264

178265
await Validate(async client =>
179266
{
@@ -275,7 +362,7 @@ public async Task UploadPackageWithMetadata()
275362
}
276363
};
277364

278-
var prefix = await Upload("Package1", fileSelections);
365+
var (prefix, _) = await Upload("Package1", fileSelections);
279366

280367
await Validate(async client =>
281368
{
@@ -546,7 +633,7 @@ public async Task UploadPackage1()
546633
}
547634
};
548635

549-
var prefix = await Upload("Package1", fileSelections);
636+
var (prefix, _) = await Upload("Package1", fileSelections);
550637

551638
await DoSafelyWithRetries(async () =>
552639
{
@@ -632,7 +719,7 @@ await ExternalVariables.Get(ExternalVariable.AwsCloudFormationAndS3AccessKey, ca
632719
}
633720
}
634721

635-
protected async Task<string> Upload(string packageName, List<S3TargetPropertiesBase> propertiesList, VariableDictionary customVariables = null, S3TargetMode s3TargetMode = S3TargetMode.FileSelections)
722+
protected async Task<(string bucketKeyPrefix, InMemoryLog log)> Upload(string packageName, List<S3TargetPropertiesBase> propertiesList, VariableDictionary customVariables = null, S3TargetMode s3TargetMode = S3TargetMode.FileSelections, bool? includeOutputVariables = null)
636723
{
637724
const string packageVersion = "1.0.0";
638725
var bucketKeyPrefix = $"calamaritest/{Guid.NewGuid():N}/";
@@ -659,6 +746,7 @@ protected async Task<string> Upload(string packageName, List<S3TargetPropertiesB
659746
}
660747
});
661748

749+
var log = new InMemoryLog();
662750
var variablesFile = Path.GetTempFileName();
663751

664752
variables.Set("Octopus.Action.AwsAccount.Variable", "AWSAccount");
@@ -675,7 +763,6 @@ protected async Task<string> Upload(string packageName, List<S3TargetPropertiesB
675763
using (var package = new TemporaryFile(PackageBuilder.BuildSimpleZip(packageName, packageVersion, packageDirectory)))
676764
using (new TemporaryFile(variablesFile))
677765
{
678-
var log = new InMemoryLog();
679766
var fileSystem = CalamariPhysicalFileSystem.GetPhysicalFileSystem();
680767

681768
var command = new UploadAwsS3Command(
@@ -696,18 +783,26 @@ protected async Task<string> Upload(string packageName, List<S3TargetPropertiesB
696783
log)
697784
);
698785

699-
var result = command.Execute(new[]
786+
var args = new List<string>
700787
{
701788
"--package", $"{package.FilePath}",
702789
"--variables", $"{variablesFile}",
703790
"--bucket", bucketName,
704791
"--targetMode", s3TargetMode.ToString()
705-
});
792+
};
793+
794+
if (includeOutputVariables.HasValue)
795+
{
796+
args.Add("--includeOutputVariables");
797+
args.Add(includeOutputVariables.Value.ToString());
798+
}
799+
800+
var result = command.Execute(args.ToArray());
706801

707802
result.Should().Be(0);
708803
}
709804

710-
return bucketKeyPrefix;
805+
return (bucketKeyPrefix, log);
711806
}
712807

713808
protected async Task<string> UploadEntireCompressedPackage(string packageFilePath,

0 commit comments

Comments
 (0)