Example #1
0
        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);
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
            }
        }