protected async Task <ContainerId> PullAsync(IOperationExecutionContext context, ContainerId containerId) { if (string.IsNullOrEmpty(containerId.Source)) { throw new InvalidOperationException("cannot pull a container with no associated source"); } var escapeArg = GetEscapeArg(context); var exitCode = await this.ExecuteCommandLineAsync(context, new RemoteProcessStartInfo { FileName = this.DockerExePath, Arguments = "pull " + escapeArg(containerId.FullName), WorkingDirectory = context.WorkingDirectory }); if (exitCode != 0) { throw new ExecutionFailureException($"docker pull returned code {exitCode}"); } var digest = await this.ExecuteGetDigest(context, containerId.FullName); return(containerId.WithDigest(digest)); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { await this.LoginAsync(context, this.ContainerSource); try { var procExec = await context.Agent.GetServiceAsync <IRemoteProcessExecuter>(); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); await fileOps.CreateDirectoryAsync(context.WorkingDirectory); var sourcePath = context.ResolvePath(this.SourceDirectory); await fileOps.CreateDirectoryAsync(sourcePath); var dockerfilePath = fileOps.CombinePath(sourcePath, "Dockerfile"); if (!string.IsNullOrWhiteSpace(this.DockerfileTemplate)) { var item = SDK.GetRaftItem(RaftItemType.TextTemplate, this.DockerfileTemplate, context); if (item == null) { this.LogError($"Text template \"{this.DockerfileTemplate}\" not found."); return; } var dockerfileText = await context.ApplyTextTemplateAsync(item.Content, this.TemplateArguments != null?new Dictionary <string, RuntimeValue>(this.TemplateArguments) : null); await fileOps.WriteAllTextAsync(dockerfilePath, dockerfileText, InedoLib.UTF8Encoding); } var containerSource = (ContainerSource)SecureResource.Create(this.ContainerSource, (IResourceResolutionContext)context); var containerId = new ContainerId(this.ContainerSource, containerSource?.RegistryPrefix, this.RepositoryName, this.Tag); var escapeArg = GetEscapeArg(context); var args = $"build --force-rm --progress=plain --tag={escapeArg(containerId.FullName)} {this.AdditionalArguments} {escapeArg(sourcePath)}"; this.LogDebug("Executing docker " + args); var startInfo = new RemoteProcessStartInfo { FileName = this.DockerExePath, Arguments = args, WorkingDirectory = sourcePath }; using (var process = procExec.CreateProcess(startInfo)) { process.OutputDataReceived += (s, e) => this.LogInformation(e.Data); process.ErrorDataReceived += (s, e) => this.LogBuildError(context, e.Data); process.Start(); await process.WaitAsync(context.CancellationToken); if (process.ExitCode != 0) { this.LogError($"exit code: {process.ExitCode ?? -1}"); return; } } var digest = await this.ExecuteGetDigest(context, containerId.FullName); containerId = containerId.WithDigest(digest); if (!string.IsNullOrEmpty(this.ContainerSource)) { await this.PushAsync(context, containerId); if (this.RemoveAfterPush) { this.LogDebug("Removing local image after successful push..."); await this.RemoveAsync(context, containerId); } } if (this.AttachToBuild) { await this.AttachToBuildAsync(context, containerId); } } finally { await this.LogoutAsync(context, this.ContainerSource); } }
public override async Task ExecuteAsync(IOperationExecutionContext context) { await this.LoginAsync(context, this.ContainerSource); try { var procExec = await context.Agent.GetServiceAsync <IRemoteProcessExecuter>(); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); await fileOps.CreateDirectoryAsync(context.WorkingDirectory); var sourcePath = context.ResolvePath(this.SourceDirectory); await fileOps.CreateDirectoryAsync(sourcePath); var baseContainerSource = (ContainerSource)SecureResource.Create(this.BaseContainerSource, (IResourceResolutionContext)context); var baseId = new ContainerId(this.BaseContainerSource, baseContainerSource?.RegistryPrefix, this.BaseRepositoryName, this.BaseTag); if (!string.IsNullOrEmpty(this.ContainerSource)) { baseId = await this.PullAsync(context, baseId); } else { baseId = baseId.WithDigest(await this.ExecuteGetDigest(context, baseId.FullName)); } using (var stream = await fileOps.OpenFileAsync(fileOps.CombinePath(sourcePath, "Dockerfile"), FileMode.Create, FileAccess.Write)) using (var writer = new StreamWriter(stream, InedoLib.UTF8Encoding, 8192, true)) { writer.NewLine = "\n"; await writer.WriteLineAsync($"FROM {baseId.FullName}"); foreach (var kv in this.EnvironmentVariables ?? new Dictionary <string, string>()) { await writer.WriteLineAsync($"ENV {kv.Key} {kv.Value}"); } foreach (var vol in this.Volumes ?? new List <string>()) { await writer.WriteLineAsync($"VOLUME {vol}"); } if (!string.IsNullOrWhiteSpace(this.DestinationDirectory)) { await writer.WriteLineAsync($"COPY . {this.DestinationDirectory}"); await writer.WriteLineAsync($"WORKDIR {this.DestinationDirectory}"); } if (!string.IsNullOrWhiteSpace(this.Command)) { await writer.WriteLineAsync($"CMD {this.Command}"); } await writer.FlushAsync(); } var containerSource = (ContainerSource)SecureResource.Create(this.ContainerSource, (IResourceResolutionContext)context); var containerId = new ContainerId(this.ContainerSource, containerSource?.RegistryPrefix, this.RepositoryName, this.Tag); var escapeArg = GetEscapeArg(context); var args = $"build --force-rm --progress=plain --tag={escapeArg(containerId.FullName)} {this.AdditionalArguments} {escapeArg(sourcePath)}"; this.LogDebug("Executing docker " + args); using (var process = procExec.CreateProcess(new RemoteProcessStartInfo { FileName = this.DockerExePath, Arguments = args, WorkingDirectory = sourcePath, EnvironmentVariables = { // ["DOCKER_BUILDKIT"] = "1" } })) { process.OutputDataReceived += (s, e) => this.LogInformation(e.Data); process.ErrorDataReceived += (s, e) => this.LogBuildError(context, e.Data); process.Start(); await process.WaitAsync(context.CancellationToken); if (process.ExitCode != 0) { this.LogError($"exit code: {process.ExitCode ?? -1}"); return; } } var digest = await this.ExecuteGetDigest(context, containerId.FullName); containerId = containerId.WithDigest(digest); if (!string.IsNullOrEmpty(this.ContainerSource)) { await this.PushAsync(context, containerId); } if (this.AttachToBuild) { await this.AttachToBuildAsync(context, containerId); } } finally { await this.LogoutAsync(context, this.ContainerSource); } }
public override async Task ExecuteAsync(IOperationExecutionContext context) { await this.LoginAsync(context, this.ContainerSource); try { var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); await fileOps.CreateDirectoryAsync(context.WorkingDirectory); this.NewRepositoryName = AH.CoalesceString(this.NewRepositoryName, this.RepositoryName); if (string.IsNullOrWhiteSpace(this.NewContainerSource)) { if (this.NewContainerSource == null) { this.NewContainerSource = this.ContainerSource; } else { this.NewContainerSource = null; } } var containerSource = (ContainerSource)SecureResource.Create(this.ContainerSource, (IResourceResolutionContext)context); var oldContainerId = new ContainerId(this.ContainerSource, containerSource?.RegistryPrefix, this.RepositoryName, this.OriginalTag); var newContainerSource = (ContainerSource)SecureResource.Create(this.NewContainerSource, (IResourceResolutionContext)context); var newContainerId = new ContainerId(this.NewContainerSource, newContainerSource?.RegistryPrefix, this.NewRepositoryName, this.NewTag); if (!string.IsNullOrEmpty(this.ContainerSource)) { oldContainerId = await this.PullAsync(context, oldContainerId); } else { oldContainerId = oldContainerId.WithDigest(await this.ExecuteGetDigest(context, oldContainerId.FullName)); } newContainerId = newContainerId.WithDigest(oldContainerId.Digest); var escapeArg = GetEscapeArg(context); int result = await this.ExecuteCommandLineAsync( context, new RemoteProcessStartInfo { FileName = this.DockerExePath, Arguments = $"tag {escapeArg(oldContainerId.FullName)} {escapeArg(newContainerId.FullName)}" } ); if (result != 0) { this.LogError("Docker exited with code " + result); return; } if (!string.IsNullOrEmpty(this.NewContainerSource)) { await this.PushAsync(context, newContainerId); } if (this.AttachToBuild) { await this.AttachToBuildAsync(context, newContainerId); } if (this.DeactivateOriginalTag) { await this.DeactivateAttachedAsync(context, oldContainerId); } } finally { await this.LogoutAsync(context, this.ContainerSource); } }