Skip to content
Draft
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
Expand Up @@ -67,7 +67,8 @@ StartKubernetesScriptCommandV1 Map(ExecuteScriptCommand command)
kubernetesScriptCommand.Files.ToArray(),
kubernetesScriptCommand.IsRawScript,
kubernetesScriptCommand.AuthContext,
kubernetesScriptCommand.ScriptPodPlatform);
kubernetesScriptCommand.ScriptPodPlatform,
kubernetesScriptCommand.CalamariImageConfiguration);
}

static ScriptOperationExecutionResult Map(KubernetesScriptStatusResponseV1 scriptStatusResponse)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using System;
using Octopus.Tentacle.Contracts;
using Octopus.Tentacle.Contracts.KubernetesScriptServiceV1;

namespace Octopus.Tentacle.Client.Scripts.Models.Builders
{
public class ExecuteKubernetesScriptCommandBuilder : ExecuteScriptCommandBuilder
{
KubernetesImageConfiguration? configuration;
KubernetesImageConfiguration? imageConfiguration;
string? scriptPodServiceAccountName;
string? scriptPodPlatform;
bool isRawScript;
KubernetesAgentAuthContext? authContext;
CalamariImageConfiguration? calamariImageConfiguration;

public ExecuteKubernetesScriptCommandBuilder(string taskId)
: base(taskId, ScriptIsolationLevel.NoIsolation) //Kubernetes Agents don't need isolation since the scripts won't clash with each other (it won't clash more than Workers anyway)
Expand All @@ -18,7 +20,7 @@ public ExecuteKubernetesScriptCommandBuilder(string taskId)

public ExecuteKubernetesScriptCommandBuilder WithKubernetesImageConfiguration(KubernetesImageConfiguration configuration)
{
this.configuration = configuration;
this.imageConfiguration = configuration;
return this;
}

Expand Down Expand Up @@ -46,6 +48,12 @@ public ExecuteKubernetesScriptCommandBuilder WithScriptPodPlatform(string script
return this;
}

public ExecuteKubernetesScriptCommandBuilder WithCalamariImageConfiguration(CalamariImageConfiguration configuration)
{
calamariImageConfiguration = configuration;
return this;
}

public override ExecuteScriptCommand Build()
=> new ExecuteKubernetesScriptCommand(
ScriptTicket,
Expand All @@ -55,11 +63,12 @@ public override ExecuteScriptCommand Build()
IsolationConfiguration,
AdditionalScripts,
Files.ToArray(),
configuration,
imageConfiguration,
scriptPodServiceAccountName,
isRawScript,
authContext,
scriptPodPlatform
scriptPodPlatform,
calamariImageConfiguration
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Octopus.Tentacle.Contracts;
using Octopus.Tentacle.Contracts.KubernetesScriptServiceV1;

namespace Octopus.Tentacle.Client.Scripts.Models
{
Expand All @@ -15,6 +16,7 @@ public class ExecuteKubernetesScriptCommand : ExecuteScriptCommand
public bool IsRawScript { get; }

public KubernetesAgentAuthContext? AuthContext { get; }
public CalamariImageConfiguration? CalamariImageConfiguration { get; }

public ExecuteKubernetesScriptCommand(
ScriptTicket scriptTicket,
Expand All @@ -28,14 +30,16 @@ public ExecuteKubernetesScriptCommand(
string? scriptPodServiceAccountName,
bool isRawScript,
KubernetesAgentAuthContext? authContext,
string? scriptPodPlatform)
string? scriptPodPlatform,
CalamariImageConfiguration? calamariImageConfiguration)
: base(scriptTicket, taskId, scriptBody, arguments, isolationConfiguration, additionalScripts, additionalFiles)
{
ImageConfiguration = imageConfiguration;
ScriptPodServiceAccountName = scriptPodServiceAccountName;
IsRawScript = isRawScript;
AuthContext = authContext;
ScriptPodPlatform = scriptPodPlatform;
CalamariImageConfiguration = calamariImageConfiguration;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Newtonsoft.Json;

namespace Octopus.Tentacle.Contracts.KubernetesScriptServiceV1
{
public class CalamariImageConfiguration
{
[JsonConstructor]
public CalamariImageConfiguration(string name, string version)
{
Name = name;
Version = version;
}

public string Name { get; }
public string Version { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public StartKubernetesScriptCommandV1(
ScriptFile[]? additionalFiles,
bool isRawScript,
KubernetesAgentAuthContext? authContext,
string? scriptPodPlatform)
string? scriptPodPlatform,
CalamariImageConfiguration? calamariImageConfiguration)
{
Arguments = arguments;
TaskId = taskId;
Expand All @@ -34,6 +35,7 @@ public StartKubernetesScriptCommandV1(
IsRawScript = isRawScript;
AuthContext = authContext;
ScriptPodPlatform = scriptPodPlatform;
CalamariImageConfiguration = calamariImageConfiguration;

if (additionalFiles != null)
Files.AddRange(additionalFiles);
Expand Down Expand Up @@ -66,5 +68,6 @@ public StartKubernetesScriptCommandV1(
public KubernetesAgentAuthContext? AuthContext { get; }

public string? ScriptPodPlatform { get; }
public CalamariImageConfiguration? CalamariImageConfiguration { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,12 @@ async Task CreatePod(StartKubernetesScriptCommandV1 command, IScriptWorkspace wo

LogVerboseToBothLogs($"Creating Kubernetes Pod '{podName}'.", tentacleScriptLog);

foreach(var file in kubernetesPhysicalFileSystem.EnumerateFiles(KubernetesConfig.BootstrapRunnerExecutableDirectory))
foreach (var file in kubernetesPhysicalFileSystem.EnumerateFiles(KubernetesConfig.BootstrapRunnerExecutableDirectory))
{
var baseName = Path.GetFileName(file);
workspace.CopyFile(file, baseName, true);
workspace.CopyFile(file, baseName, true);
}

var scriptName = Path.GetFileName(workspace.BootstrapScriptFilePath);
var workspacePath = Path.Combine("Work", workspace.ScriptTicket.TaskId);

Expand Down Expand Up @@ -257,7 +257,7 @@ protected virtual async Task<IList<V1Container>> CreateInitContainers(StartKuber

protected virtual IList<V1Volume> CreateVolumes(StartKubernetesScriptCommandV1 command)
{
return new List<V1Volume>
var volumes = new List<V1Volume>
{
new()
{
Expand All @@ -269,6 +269,21 @@ protected virtual IList<V1Volume> CreateVolumes(StartKubernetesScriptCommandV1 c
},
CreateAgentUpgradeSecretVolume(),
};

if (command.CalamariImageConfiguration is not null)
{
volumes.Add(new V1Volume
{
Name = "calamari",
Image = new V1ImageVolumeSource
{
Reference = $"octopusdeploy/{command.CalamariImageConfiguration.Name}:{command.CalamariImageConfiguration.Version}",
PullPolicy = "IfNotPresent"
}
});
}

return volumes;
}

protected V1Volume CreateAgentUpgradeSecretVolume()
Expand Down Expand Up @@ -301,7 +316,7 @@ void LogVerboseToBothLogs(string message, InMemoryTentacleScriptLog tentacleScri
protected async Task<V1Container> CreateScriptContainer(StartKubernetesScriptCommandV1 command, string podName, string scriptName, string homeDir, string workspacePath, string[]? scriptArguments, InMemoryTentacleScriptLog tentacleScriptLog, V1Container? containerSpec)
{
var spaceInformation = kubernetesPhysicalFileSystem.GetStorageInformation();

var commandString = string.Join(" ", new[]
{
$"{homeDir}/Work/{command.ScriptTicket.TaskId}/execute-bootstrapRunner.sh",
Expand Down Expand Up @@ -385,6 +400,19 @@ protected async Task<V1Container> CreateScriptContainer(StartKubernetesScriptCom
//We intentionally exclude setting "TentacleJournal" since it doesn't make sense to keep a Deployment Journal for Kubernetes deployments
});

//if the image is configured, add that flag
if (command.CalamariImageConfiguration is not null)
{
container.VolumeMounts.Add(new V1VolumeMount
{
MountPath = "/calamari",
Name = "calamari",
SubPath = "Calamari" //Calamari is always at the subpath of the app name
});

container.Env.Add(new V1EnvVar { Name = "CalamariImageDirectoryPath", Value = "/calamari" });
}

container.EnvFrom = Merge(container.EnvFrom, envFrom);
return container;
}
Expand Down