public DockerEngineClient( ISshClient sshClient, ILogger logger) { this.sshClient = sshClient; this.logger = logger; }
/// <summary> /// These sets of commands are taken from https://docs.docker.com/install/linux/docker-ce/ubuntu/. /// </summary> private async Task InstallDockerAsync(ISshClient sshClient) { this.description = "Installing Docker Engine"; //SET UP THE REPOSITORY await RunCommandsAsync( sshClient, SshRetryPolicy.AllowRetries, new[] { "sudo apt-get update", "echo '* libraries/restart-without-asking boolean true' | sudo debconf-set-selections", "sudo apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common", "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -", "sudo add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\"" }); //INSTALL DOCKER ENGINE - COMMUNITY await RunCommandsAsync( sshClient, SshRetryPolicy.AllowRetries, new[] { "sudo apt-get update", "sudo apt-get -y install docker-ce docker-ce-cli containerd.io" }); }
private async Task OpenExposedFirewallPortsOnInstanceAsync(ISshClient sshClient) { if (this.InstanceName == null) { throw new InvalidOperationException("No instance name was found."); } this.description = "Opening firewall for exposed ports and protocols"; var mergedDockerComposeYmlContents = await GetMergedDockerComposeYmlFileContentsAsync(sshClient); var dockerComposeParser = this.dockerComposeParserFactory.Create(mergedDockerComposeYmlContents); var portsToOpen = new HashSet <ExposedPortRange>() { GetSshPort() }; var ports = dockerComposeParser.GetExposedHostPorts(); foreach (var port in ports) { portsToOpen.Add(port); } await this.mediator.Send(new OpenFirewallPortsCommand( this.InstanceName, portsToOpen)); }
private async Task AuthenticateDockerAsync(ISshClient sshClient) { var authenticationArguments = this.Authentication; if (authenticationArguments == null) { return; } foreach (var authenticationArgument in authenticationArguments) { await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, "echo @password | docker login -u @username --password-stdin @registryHostName", new Dictionary <string, string?>() { { "username", authenticationArgument.Username }, { "password", authenticationArgument.Password }, { "registryHostName", authenticationArgument.RegistryHostName } }); } }
private static async Task EnsureDirectoryAsync(ISshClient sshClient, string path) { await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"mkdir -m 777 -p ./{path}"); await SetUserPermissionsOnPathAsync(sshClient, path); }
//private async Task InstallKubernetesOnNodeAsync( // ISshClient sshClient, // InstanceType instanceType) //{ // await InstallKubernetesToolsAsync(sshClient); // switch (instanceType) // { // case InstanceType.KubernetesControlPlane: // await InitializeKubernetesControlPlaneNodeAsync(sshClient); // break; // case InstanceType.KubernetesWorker: // await InitializeKubernetesWorkerNodeAsync(sshClient); // break; // default: // throw new InvalidOperationException("Unknown instance type."); // } //} //private async Task InitializeKubernetesWorkerNodeAsync(ISshClient sshClient) //{ // throw new NotImplementedException("Kubernetes worker support has not been created yet."); //} private async Task ConfigureDockerDaemonAsync(ISshClient sshClient) { this.description = "Configuring Docker Daemon"; await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, "sudo systemctl enable docker"); }
private async Task <string> GetMergedDockerComposeYmlFileContentsAsync(ISshClient sshClient) { var dockerComposeYmlFilePathArguments = GetDockerComposeFilesCommandLineArgumentString(); var environmentVariablesPrefix = GetEnvironmentVariablesCommandLinePrefixString(); return(await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"cd dogger && {environmentVariablesPrefix} docker-compose {dockerComposeYmlFilePathArguments} config")); }
public SshStep( ListAsk listAsk, ListResources listResources, ISshClient sshClient) { this.listResources = listResources; this.sshClient = sshClient; this.listAsk = listAsk; }
public VBoxInfrastructure( VBoxHelper vBoxHelper, ISshClient sshClient) { this.vBoxHelper = vBoxHelper; this.sshClient = sshClient; //this.vmPilote.PrivateRegistryPort = 5443; //this.vmPilote.PrivateRegistryDomain = "privateregistry.mynetwork.local"; }
public InfraWebServerCreateVm( ListAsk listAsk, ListResources listResources, IInfrastructure infrastructure, ISshClient sshClient) { this.listAsk = listAsk; this.infrastructure = infrastructure; this.listResources = listResources; this.sshClient = sshClient; }
public PiloteStep( ListAsk listAsk, ListResources listResources, CiExeCommands ciExeCommands, ISshClient sshClient) { this.listResources = listResources; this.ciExeCommands = ciExeCommands; this.sshClient = sshClient; this.listAsk = listAsk; }
private async Task RunContainersAsync(ISshClient sshClient) { if (InstanceName == null) { throw new InvalidOperationException("Could not find instance name."); } await AuthenticateDockerAsync(sshClient); var filesArgument = GetDockerComposeFilesCommandLineArgumentString(); var buildArgumentsArgument = PrependArgumentNameToStrings("--build-arg", GetBuildArgumentAssignments()); var environmentVariablesPrefix = GetEnvironmentVariablesCommandLinePrefixString(); try { await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"cd dogger && {environmentVariablesPrefix} docker-compose {filesArgument} down --rmi all --volumes --remove-orphans"); await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"cd dogger && {environmentVariablesPrefix} docker-compose {filesArgument} pull --include-deps"); await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"cd dogger && {environmentVariablesPrefix} docker-compose {filesArgument} build --force-rm --parallel --no-cache {buildArgumentsArgument}"); await sshClient.ExecuteCommandAsync( SshRetryPolicy.ProhibitRetries, $"cd dogger && {environmentVariablesPrefix} docker-compose {filesArgument} --compatibility up --detach --remove-orphans --always-recreate-deps --force-recreate --renew-anon-volumes"); } catch (SshCommandExecutionException ex) when(ex.Result.ExitCode == 1) { var listFilesDump = await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, "cd dogger && ls -R"); await this.mediator.Send(new ServerDeploymentFailedEvent( InstanceName, ex.Result.Text, listFilesDump)); throw new StateUpdateException( "Could not run containers: " + ex.Result.Text, ex, new BadRequestObjectResult( new ValidationProblemDetails() { Type = "DOCKER_COMPOSE_UP_FAIL", Title = ex.Result.Text })); } }
private static async Task RunCommandsAsync( ISshClient sshClient, SshRetryPolicy retryPolicy, string[] commands) { foreach (var command in commands) { await sshClient.ExecuteCommandAsync( retryPolicy, command); } }
//private async Task InstallKubernetesToolsAsync(ISshClient sshClient) //{ // this.description = "Installing Kubernetes"; // await RunCommandsAsync( // sshClient, // SshRetryPolicy.AllowRetries, // new[] // { // "sudo apt-get update", // "sudo apt-get install -y apt-transport-https curl", // "sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -", // "sudo cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list\ndeb https://apt.kubernetes.io/ kubernetes-xenial main\nEOF", // "sudo apt-get update", // "sudo apt-get install -y kubelet kubeadm kubectl", // "sudo apt-mark hold kubelet kubeadm kubectl" // }); //} ///// <summary> ///// From: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#installing-kubeadm-on-your-hosts ///// </summary> //private async Task InitializeKubernetesControlPlaneNodeAsync(ISshClient sshClient) //{ // throw new NotImplementedException("Kubernetes control plane support has not been created yet."); //} /// <summary> /// These sets of commands are taken from https://docs.docker.com/compose/install/ /// </summary> private async Task InstallDockerComposeAsync(ISshClient sshClient) { this.description = "Installing Docker Compose"; await RunCommandsAsync( sshClient, SshRetryPolicy.AllowRetries, new[] { "sudo curl -L \"https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose", "sudo chmod +x /usr/local/bin/docker-compose" }); }
/// <summary> /// These sets of commands are taken from https://docs.docker.com/engine/install/linux-postinstall/ /// </summary> private async Task ConfigurePostInstallAsync(ISshClient sshClient) { this.description = "Configuring Docker permissions"; await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, "sudo usermod -aG docker $USER"); //verify that we can run docker without root access. await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, "docker --version"); }
private static async Task SetSystemConfigurationValueAsync( ISshClient sshClient, string key, string value) { await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"sudo sysctl -w {key}={value}"); await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"sudo bash -c \"echo '{key}={value}' >> /etc/sysctl.conf\""); }
protected override async Task <ProvisioningStateUpdateResult> OnUpdateAsync(ISshClient sshClient) { if (this.IpAddress == null) { throw new InvalidOperationException($"Must provide IP address to {nameof(InstallSoftwareOnInstanceState)}"); } await InstallDockerAsync(sshClient); await InstallDockerComposeAsync(sshClient); await ConfigureDockerDaemonAsync(sshClient); await ConfigurePostInstallAsync(sshClient); await SetSystemConfigurationValueAsync(sshClient, "vm.max_map_count", "262144"); return(ProvisioningStateUpdateResult.Succeeded); }
protected override async Task <ProvisioningStateUpdateResult> OnUpdateAsync(ISshClient sshClient) { if (this.InstanceName == null) { throw new InvalidOperationException("Instance name has not been set."); } await this.mediator.Send( new RegisterInstanceAsProvisionedCommand( this.InstanceName) { UserId = this.UserId }); return(ProvisioningStateUpdateResult.Succeeded); }
protected override async Task <ProvisioningStateUpdateResult> OnUpdateAsync(ISshClient sshClient) { if (this.DockerComposeYmlFilePaths == null) { throw new InvalidOperationException("Docker Compose file paths must be set."); } await ClearExistingDoggerFilesAsync(sshClient); await CreateFilesOnServerAsync(sshClient); await OpenExposedFirewallPortsOnInstanceAsync(sshClient); await RunContainersAsync(sshClient); await SendServerDeploymentCompletedEventAsync(); return(ProvisioningStateUpdateResult.Succeeded); }
private async Task CreateFilesOnServerAsync(ISshClient sshClient) { var files = this.Files; if (files == null) { return; } foreach (var file in files) { await CreateSensitiveFileOnServerAsync( sshClient, file.Path, file.Contents); } }
private static async Task CreateSensitiveFileOnServerAsync( ISshClient sshClient, string filePath, byte[] contents) { filePath = SanitizeRelativePath(filePath); if (filePath.Contains("/", StringComparison.InvariantCulture)) { var folderPath = filePath.Substring(0, filePath.LastIndexOf('/')); await EnsureDirectoryAsync(sshClient, $"./dogger/{folderPath}"); } await sshClient.TransferFileAsync( SshRetryPolicy.AllowRetries, $"dogger/{filePath}", contents); await SetUserPermissionsOnPathAsync(sshClient, $"dogger/{filePath}"); }
public CiExeCommands( InstallCA installCA, InstallRegistry installRegistry, InstallVault installVault, BuildWebApp1 buildWebApp1, // WebServer InstallTraefik installTraefik, InstallWebApp installWebApp, ISshClient sshClient ) { volume1 = "--volume /var/run/docker.sock:/var/run/docker.sock "; volume2 = "--volume " + "/cidata" + ":/cidata "; this.InstallCA = Create <InstallCA>("install-ca", async() => await installCA.Install()); this.CleanCA = Create <InstallCA>("clean-ca", async() => await installCA.Clean()); this.InstallRegistry = Create <InstallRegistry>("install-registry", async() => await installRegistry.Install()); this.CleanRegistry = Create <InstallRegistry>("clean-registry", async() => await installRegistry.Clean()); this.InstallVault = Create <InstallVault>("install-vault", async() => await installVault.Init()); this.BuildWebApp1 = Create <BuildWebApp1>("build-webapp1", async() => await buildWebApp1.Build()); this.CleanWebApp1 = Create <BuildWebApp1>("clean-webapp1", async() => await buildWebApp1.CleanBuild()); this.PublishWebApp1 = Create <BuildWebApp1>("publish-webapp1", async() => await buildWebApp1.Publish()); this.UnpublishWebApp1 = Create <BuildWebApp1>("cleanpublish-webapp1", async() => await buildWebApp1.CleanPublish()); // Webserver this.InstallTraefik = Create <InstallTraefik>("webserver-install-webapp1", async() => await installTraefik.Install()); this.CleanTraefik = Create <InstallTraefik>("clean-webapp1", async() => await installTraefik.Clean()); this.InstallWebApp1 = Create <InstallWebApp>("webserver-install-webapp1", async() => await installWebApp.Install()); this.CleanInstallWebApp1 = Create <InstallWebApp>("clean-webapp1", async() => await installWebApp.CleanInstall()); this.sshClient = sshClient; }
protected abstract Task <ProvisioningStateUpdateResult> OnUpdateAsync(ISshClient sshClient);
public SshMirrorRegistry(ISshClient sshClient) { this.sshClient = sshClient; }
private static async Task RemoveDirectoryAsync(ISshClient sshClient, string path) { await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"sudo rm ./{path} -rf"); }
private static async Task ClearExistingDoggerFilesAsync(ISshClient sshClient) { await RemoveDirectoryAsync(sshClient, "dogger"); await EnsureDirectoryAsync(sshClient, "dogger"); }
private static async Task SetUserPermissionsOnPathAsync(ISshClient sshClient, string fileName) { await sshClient.ExecuteCommandAsync( SshRetryPolicy.AllowRetries, $"sudo chmod 777 ./{fileName}"); }
public SshCiexe(ISshClient sshClient) { this.sshClient = sshClient; }
private IDockerEngineClient CreateForSshClient(ISshClient sshClient) { return(new DockerEngineClient( sshClient, logger)); }