Class/UpdateContainersDefinition.Class.psm1
## Namespaces. using namespace System.Collections.Generic; using namespace System.Text.Json; using namespace System.Text.Json.Serialization; ## Custom Modules. using module '..\Enum\UpdateContainersEngine.Enum.psm1'; using module '.\UpdateContainersContainerDefinition.Class.psm1'; using module '.\UpdateContainersNetworkDefinition.Class.psm1'; using module '.\UpdateContainersReplacementDefinition.Class.psm1'; ## Definition Class. class UpdateContainersDefinition { <# .NAME UpdateContainersDefinition .SYNOPSIS Class defining a container engine definition. .DESCRIPTION This class represents a container engine definition that includes configurations for containers, networks, and other related settings. It supports both Docker and Podman as container engines. .PROPERTIES AnyRemoved A boolean indicating whether any containers were removed during the operation. Command The container engine command to use (Docker or Podman). Containers A list of container definitions to be created and managed. DebugEnabled A boolean indicating whether debug mode is enabled. DnsServers A list of DNS server IP addresses to use for the containers. DryRunEnabled A boolean indicating whether dry-run mode is enabled. Networks A list of network definitions to be created and managed. NoStartContainers A boolean indicating whether to create containers without starting them. OnlyCreateContainers An array of container names to create; if empty, all containers are created. PurgeImagesEnabled A boolean indicating whether to purge unused images after operations. Replacements A list of definition replacements to apply to paths and strings. #> ## AnyRemoved Property. [JsonIgnore()] [Boolean] $AnyRemoved = $false; ## Command Property. [JsonPropertyName('command')] [JsonRequired()] [UpdateContainersEngineEnum] $Command; ## Containers Property. [JsonPropertyName('container')] [JsonRequired()] [List[UpdateContainersContainerDefinition]] $Containers = [List[UpdateContainersContainerDefinition]]::new(); ## Debug Property. [JsonPropertyName('debug')] [Boolean] $DebugEnabled = $false; ## DNS Servers Property. [JsonPropertyName('dns')] [List[String]] $DnsServers = [List[String]]::new(); ## Dry-Run Property. [JsonPropertyName('dryRun')] [Boolean] $DryRunEnabled = $false; ## Networks Property. [JsonPropertyName('network')] [List[UpdateContainersNetworkDefinition]] $Networks = [List[UpdateContainersNetworkDefinition]]::new(); ## No Start Containers Property. [JsonPropertyName('noStart')] [Boolean] $NoStartContainers = $false; ## Only Create Containers Property. [JsonPropertyName('only')] [String[]] $OnlyCreateContainers = @(); ## Purge Images Property. [JsonPropertyName('purgeImages')] [Boolean] $PurgeImagesEnabled = $false; ## Replacements Property [JsonPropertyName('replacement')] [List[UpdateContainersReplacementDefinition]] $Replacements = [List[UpdateContainersReplacementDefinition]]::new(); ## Create Containers Method. [Void] CreateContainers() { <# .NAME CreateContainers .SYNOPSIS Creates containers based on the definitions provided. .DESCRIPTION This method iterates over the container definitions and creates each container if it does not already exist. It uses the specified container engine command (Docker or Podman) to perform the creation. If dry-run mode is enabled, it will only simulate the creation without actually executing the commands. #> ## Iterate over the containers. foreach ($container in $this.Containers | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim() }) { ## Reconcile the engine command between the definition and the container. [String] $engine = $($null -ne $container.Command -and "" -ne $container.Command.Trim() ? ` $container.Command.ToString() : $this.Command.ToString()).ToLower().Trim(); ## Localize the existence of the container. [Int32] $exists = (& "${engine}" ps -a --filter "Name=$($container.Name.Trim())" --format "{{.Names}}" ` | Where-Object { $_ -eq "$($container.Name.Trim())" }).Length; ## Check if the container exists. if (0 -eq $exists -or $true -eq $this.DryRunEnabled) { ## Create the container. Write-Host "Creating container '$($container.Name.Trim())'." -ForegroundColor Green; ## Create the container in the local registry. $this.ExecuteCommand("${engine} $($container.ToCommandLine($this.Command, $this.DnsServers, ` $this.Replacements, $this.DryRunEnabled))"); } } } ## Create Networks Method. [Void] CreateNetworks() { <# .NAME CreateNetworks .SYNOPSIS Creates networks based on the definitions provided. .DESCRIPTION This method iterates over the network definitions and creates each network if it does not already exist. It uses the specified container engine command (Docker or Podman) to perform the creation. If dry-run mode is enabled, it will only simulate the creation without actually executing the commands. #> ## Iterate over the distinct networks. foreach ($network in ($this.Networks | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or ($this.Containers | Where-Object { $this.OnlyCreateContainers -contains $_.Name.Trim() -and ($_.Networks | Where-Object { $_.Name.ToLower().Trim() -eq $network.Name.ToLower().Trim() }).Count -gt 0 }).Count -gt 0 } | Group-Object -Property 'Name' | ForEach-Object { $_.Group | Select-Object -First 1 })) { ## Reconcile the engine command between the definition and the network. [String] $engine = $($null -ne $network.Command -and "" -ne $network.Command.Trim() ? ` $network.Command : $this.Command).ToString().ToLower().Trim(); ## Localize the existence of the network. [Int32] $exists = (& "${engine}" network ls --filter "Name=$($network.Name.Trim())" --format "{{.Name}}" ` | Where-Object { $_ -eq "$($network.Name.Trim())" }).Length; ## Check if the network exists. if (0 -eq $exists -or $true -eq $this.DryRunEnabled) { ## Create the network. Write-Host "Creating network '$($network.Name.Trim())'." -ForegroundColor Green; ## Create the network in the local registry. $this.ExecuteCommand("${engine} $($network.ToCommandLine())"); } } } ## Execute Command Method. [Void] ExecuteCommand([String] $command) { <# .NAME ExecuteCommand .SYNOPSIS Executes a command line string using Invoke-Expression. .DESCRIPTION This method takes a command line string as input and executes it using the Invoke-Expression cmdlet. It supports dry-run and debug modes, where the command is only displayed without execution. .PARAMETERS command The command line string to be executed. #> ## Check for a dry-run. if ($this.DebugEnabled -or $this.DryRunEnabled) { ## Output the command that would be executed. Write-Host "Invoke-Expression -Command `"$($command.Trim());`" | Out-Null;" -ForegroundColor Yellow; ## Write our buffer line. Write-Host "" -ForegroundColor Yellow; } ## Check to see if we should execute the command then execute it. if ($false -eq $this.DryRunEnabled) { Invoke-Expression -Command "${command};" | Out-Null; } } ## Link Containers to Routes Method. [Void] LinkContainersToRoutes() { <# .NAME LinkContainersToRoutes .SYNOPSIS Links containers to their defined networks based on the definitions provided. .DESCRIPTION This method iterates over the network definitions and links each container to its defined networks if it is not already linked. It uses the specified container engine command (Docker or Podman) to perform the linking. If dry-run mode is enabled, it will only simulate the linking without actually executing the commands. #> ## Iterate over the containers whose network(s) contain routes. foreach ($container in ($this.Containers | Where-Object { $null -ne $_.Networks -and $_.Networks.Count -gt 0 -and ($_.Networks | Where-Object { ($this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim()) ` -and $null -ne $_.Routes -and $_.Routes.Count -gt 0 }).Count -gt 0 })) { ## Reconcile the engine command between the definition and the container. [String] $engine = ($null -ne $container.Command ? ` $container.Command : $this.Command).ToString().ToLower().Trim(); ## Check for the existence of the container. [Int32] $exists = (& "${engine}" ps -a --filter "Name=$($container.Name.Trim())" --format "{{.Names}}" ` | Where-Object { $_ -eq "$($container.Name.Trim())" }).Length; ## Ensure the container exists. if (0 -eq $exists) { ## Write the message to the host, letting them know we're skipping it. Write-Host "Container '$($container.Name.Trim())' does not exist, skipping route link(s)." -ForegroundColor Gray; ## We're done with this iteration. continue; } ## Define our interface iterator. [Int32] $interface = 0; ## Iterate over the networks for the container that contain routes. foreach ($network in ($container.Networks | Where-Object { $null -ne $_.Routes -and $_.Routes.Count -gt 0 })) { ## Check for the existence of the network. $exists = (& "${engine}" network ls --filter "Name=$($network.Name.Trim())" --format "{{.Name}}" ` | Where-Object { $_ -eq "$($network.Name.Trim())" }).Length; ## Ensure the network exists. if (0 -eq $exists) { ## Write the message to the host, letting them know we're skipping it. Write-Host "Network '$($network.Name.Trim())' does not exist, skipping route link(s) for container '$($container.Name.Trim())'." -ForegroundColor Gray; ## Increment the interface iterator. ++$interface; ## We're done with this iteration. if (-not $this.DebugEnabled) { continue; }; } ## Iterate over the routes for the network. foreach ($route in $network.Routes) { ## Write the message to the host, letting them know we're linking it. Write-Host -ForegroundColor Green ` "Routing container '$($container.Name.Trim())' to '$($route.Destination.Trim())' via '$($route.Gateway.Trim())' on 'eth$($interface)'."; ## Execute the command to link the container to the physical network if necessary. $this.ExecuteCommand("${engine} exec --privileged '$($container.Name.Trim())' ```n`t$($route.ToCommandLine("eth${interface}"))"); } } } } ## Link Containers to Physical Network Method. [Void] LinkContainersToSecondaryNetworks() { <# .NAME LinkContainersToSecondaryNetworks .SYNOPSIS Links containers to their secondary networks based on the definitions provided. .DESCRIPTION This method iterates over the container definitions and links each container to its secondary networks if it is not already linked. It uses the specified container engine command (Docker or Podman) to perform the linking. If dry-run mode is enabled, it will only simulate the linking without actually executing the commands. #> ## Iterate over the containers. foreach ($container in $this.Containers | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim() }) { ## Reconcile the engine command between the definition and the container. [String] $engine = ($null -ne $container.Command ? ` $container.Command : $this.Command).ToString().ToLower().Trim(); ## Iterate over the networks for the container, skipping the first one as it's the primary network. foreach ($network in ($container.Networks | Select-Object -Skip 1)) { ## Check to see if the container is already linked to the network. [Int32] $exists = (& "${engine}" network inspect "$($network.Name.Trim())" ` --format "{{range .Containers}}{{.Name}} {{end}}" | Where-Object { $_ -eq "$($container.Name.Trim())" }).Length; ## Check if the container is already linked to the network. if (0 -ne $exists) { ## Write the message to the host, letting them know we're skipping it. Write-Host "Container '$($container.Name.Trim())' is already linked to network '$($network.Name.Trim())', skipping." -ForegroundColor Gray; ## We're done with this iteration. if ($false -eq $this.DryRunEnabled) { continue; }; } ## Write the message to the host, letting them know we're linking it. Write-Host "Linking container '$($container.Name.Trim())' to network '$($network.Name.Trim())'." -ForegroundColor Green; ## Generate and execute the command to link the container to the physical network if necessary. $this.ExecuteCommand("${engine} $($network.ToCommandLine($engine, $true, $container, $this.DryRunEnabled))"); } } } ## Prune Method. [Void] Prune() { <# .NAME Prune .SYNOPSIS Prunes unused containers, images, networks, and volumes. .DESCRIPTION This method prunes unused containers, images, networks, and volumes from the container engine's local registry. It uses the specified container engine command (Docker or Podman) to perform the pruning. If dry-run mode is enabled, it will only simulate the pruning without actually executing the commands. #> ## Write the message to the host, letting them know we're pruning containers. Write-Host "Pruning containers." -ForegroundColor Gray; ## Prune any stopped containers. $this.ExecuteCommand("$($this.Command.ToString().ToLower()) container prune -f"); ## Write the message to the host, letting them know we're pruning images. Write-Host "Pruning images." -ForegroundColor Gray; ## Prune any dangling images. $this.ExecuteCommand("$($this.Command.ToString().ToLower()) image prune -a -f"); ## Write the message to the host, letting them know we're pruning networks. Write-Host "Pruning networks." -ForegroundColor Gray; ## Prune any unused networks. $this.ExecuteCommand("$($this.Command.ToString().ToLower()) network prune -f"); ## Write the message to the host, letting them know we're pruning volumes. Write-Host "Pruning volumes." -ForegroundColor Gray; ## Prune any unused volumes. $this.ExecuteCommand("$($this.Command.ToString().ToLower()) volume prune -f"); } ## Pull Images Method. [Void] PullImages() { <# .NAME PullImages .SYNOPSIS Pulls the latest images for the defined containers. .DESCRIPTION This method iterates over the unique container images defined in the container definitions and pulls the latest version of each image from the remote registry. It uses the specified container engine command (Docker or Podman) to perform the pull operation. If dry-run mode is enabled, it will only simulate the pull without actually executing the commands. #> ## Iterate over the unique container images. foreach ($container in ($this.Containers | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim() } | Select-Object -Property Image -Unique)) { ## Reconcile the engine command between the definition and the container. [String] $engine = $($null -ne $container.Command -and "" -ne $container.Command.Trim() ? ` $container.Command.ToString() : $this.Command.ToString()).ToLower().Trim(); ## Pull the image from the remote registry. Write-Host "Pulling image '$($container.Image.Trim())'." -ForegroundColor Cyan; ## Pull the latest image into the local registry. $this.ExecuteCommand("${engine} pull --quiet '$($container.Image.Trim())'"); } } ## Purge Containers Method. [Void] PurgeContainers() { <# .NAME PurgeContainers .SYNOPSIS Purges containers based on the definitions provided. .DESCRIPTION This method iterates over the container definitions and removes each container if it exists. It uses the specified container engine command (Docker or Podman) to perform the removal. If dry-run mode is enabled, it will only simulate the removal without actually executing the commands. #> ## Iterate over the containers. foreach ($container in $this.Containers | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim() }) { ## Reconcile the engine command between the definition and the container. [String] $engine = $($null -ne $container.Command -and "" -ne $container.Command.Trim() ? ` $container.Command.ToString() : $this.Command.ToString()).ToLower().Trim(); ## Localize the existence of the container. [Int32] $exists = (& "${engine}" ps -a --filter "Name=$($container.Name.Trim())" --format "{{.Names}}" ` | Where-Object { $_ -eq "$($container.Name.Trim())" }).Length; ## Check if the container exists. if (0 -ne $exists -or $true -eq $this.DryRunEnabled) { ## Stop the container. Write-Host "Stopping container '$($container.Name.Trim())'." -ForegroundColor Gray; ## Stop the container if it's running. $this.ExecuteCommand("${engine} container stop '$($container.Name.Trim())'"); ## Remove the container. Write-Host "Removing container '$($container.Name.Trim())'." -ForegroundColor Gray; ## Remove the container from the local registry. $this.ExecuteCommand("${engine} container rm -f '$($container.Name.Trim())'"); ## Reset the AnyRemoved flag. $this.AnyRemoved = $true; } } } ## Purge Images Method. [Void] PurgeImages() { <# .NAME PurgeImages .SYNOPSIS Purges images based on the definitions provided. .DESCRIPTION This method iterates over the unique container images defined in the container definitions and removes each image if it exists. It uses the specified container engine command (Docker or Podman) to perform the removal. #> ## Iterate over the distinct container images. foreach ($container in ($this.Containers | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim() } | Select-Object -Property Image -Unique)) { ## Reconcile the engine command between the definition and the container. [String] $engine = $($null -ne $container.Command -and "" -ne $container.Command.Trim() ? ` $container.Command.ToString() : $this.Command.ToString()).ToLower().Trim(); ## Localize the existence of the image. [Int32] $exists = (& "${engine}" image ls --filter "Reference=$($container.Image.Trim())" ` --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq "$($container.Image.Trim())" }).Length; ## Check if the image exists. if (0 -ne $exists -or $true -eq $this.DryRunEnabled) { ## Remove the image. Write-Host "Removing image '$($container.Image.Trim())'." -ForegroundColor Gray; ## Remove the image from the local registry. $this.ExecuteCommand("${engine} image rm -f '$($container.Image.Trim())'"); ## Reset the AnyRemoved flag. $this.AnyRemoved = $true; } } } ## Purge Networks Method. [Void] PurgeNetworks() { <# .NAME PurgeNetworks .SYNOPSIS Purges networks based on the definitions provided. .DESCRIPTION This method iterates over the network definitions and removes each network if it exists. It uses the specified container engine command (Docker or Podman) to perform the removal. If dry-run mode is enabled, it will only simulate the removal without actually executing the commands. #> ## Iterate over the networks. foreach ($network in $this.Networks | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or ($this.Containers | Where-Object { $this.OnlyCreateContainers -contains $_.Name.Trim() -and ($_.Networks | Where-Object { $_.Name.ToLower().Trim() -eq $network.Name.ToLower().Trim() }).Count -gt 0 }).Count -gt 0 } | Group-Object -Property 'Name' | ForEach-Object { $_.Group | Select-Object -First 1 }) { ## Reconcile the engine command between the definition and the network. [String] $engine = $($null -ne $network.Command -and "" -ne $network.Command.Trim() ? ` $network.Command.ToString() : $this.Command.ToString()).ToLower().Trim(); ## Localize the existence of the network. [Int32] $exists = (& "${engine}" network ls --filter "Name=$($network.Name.Trim())" --format "{{.Name}}" ` | Where-Object { $_ -eq "$($network.Name.Trim())" }).Length; ## Check if the network exists. if (0 -ne $exists -or $true -eq $this.DryRunEnabled) { ## Remove the network. Write-Host "Removing network '$($network.Name.Trim())'." -ForegroundColor Gray; ## Remove the network from the local registry. $this.ExecuteCommand("${engine} network rm '$($network.Name.Trim())'"); ## Reset the AnyRemoved flag. $this.AnyRemoved = $true; } } } ## Run Method. [Void] Run([Boolean] $dryRun, [Boolean] $noStart, [String[]] $only, [Boolean] $printCommands, [Boolean] $purgeImages, [HashTable] $replacements) { <# .NAME Run .SYNOPSIS Executes the container engine definition to manage containers and networks. .DESCRIPTION This method orchestrates the entire process of managing containers and networks based on the definitions provided. It handles purging existing resources, pulling images, creating networks and containers, linking containers to networks, and starting containers. It also supports dry-run and debug modes, as well as path replacements. .PARAMETERS dryRun A boolean indicating whether to perform a dry-run (no actual changes). noStart A boolean indicating whether to skip starting the containers after creation. only An array of container names to limit the operation to specific containers. printCommands A boolean indicating whether to print the commands that would be executed. purgeImages A boolean indicating whether to purge unused images after operations. replacements A hashtable of key-value pairs for path and string replacements. #> ## Reconcile the debug flag between the definition file and the command line parameter. $this.DebugEnabled = ($printCommands -or $this.DebugEnabled); ## Reconcile the dry-run flag between the definition file and the command line parameter. $this.DryRunEnabled = ($dryRun -or $this.DryRunEnabled); ## Reconcile the no-start flag between the definition file and the command line parameter. $this.NoStartContainers = ($noStart -or $this.NoStartContainers); ## Reconcile the only-create flag between the definition file and the command line parameter. $this.OnlyCreateContainers += $only; ## Reconcile the purge-images flag between the definition file and the command line parameter. $this.PurgeImagesEnabled = ($purgeImages -or $this.PurgeImagesEnabled); ## Check the only list for a single element with a csv. if ($this.OnlyCreateContainers.Count -eq 1 -and $this.OnlyCreateContainers[0].Contains(",")) { ## Split the single element into multiple elements. $this.OnlyCreateContainers = $this.OnlyCreateContainers[0].Split(",") | Where-Object { $null -ne $_ -and "" -ne $_.Trim() }; } ## Sort and trim the only list and ensure uniqueness. if ($Only.Count -gt 0) { ## Sort and trim the only list and ensure uniqueness. $Only = $Only | ForEach-Object { $_.Trim() } | Sort-Object -Unique; } ## Check for dry-run or debug mode. if ($this.DryRunEnabled -or ($this.OnlyCreateContainers.Count -gt 0) -or $this.DebugEnabled -or $this.PurgeImagesEnabled) { ## Write the buffer space. Write-Host "`n" -ForegroundColor Magenta; } ## Check for a dry run then write the message to the host. if ($this.DryRunEnabled) { Write-Host "[DRY-RUN]: No changes will be made." -ForegroundColor Magenta; } ## Check for no container start then write the message to the host. if ($this.NoStartContainers) { Write-Host "[NO-START]: Containers will not be started after creation nor will routes be linked to them." ` -ForegroundColor Magenta; } ## Check for only creating specific containers then write the message to the host. if ($this.OnlyCreateContainers.Count -gt 0) { Write-Host "[ONLY]: Only the following containers will be processed: `n`t`t`t - $($this.OnlyCreateContainers -join "`n`t`t`t - ")`n" ` -ForegroundColor Magenta; } ## Check for debug mode then write the message to the host. if ($this.DebugEnabled) { Write-Host "[PRINT-CMD]: Commands will be printed before execution." -ForegroundColor Magenta; } ## Check for image purging then write the message to the host. if ($this.PurgeImagesEnabled) { Write-Host "[PURGE-IMG]: All images will be removed before pulling new ones." -ForegroundColor Magenta; } ## Check for dry-run or debug mode. if ($this.DryRunEnabled -or ($this.OnlyCreateContainers.Count -gt 0) -or $this.DebugEnabled -or $this.PurgeImagesEnabled) { ## Write the buffer space. Write-Host "`n" -ForegroundColor Magenta; } ## Iterate over the replacements from the command line parameter. foreach ($key in $Replacements.Keys) { ## Add the replacement to the definition replacements. $this.Replacements[$key.Trim()] = $replacements[$key].Trim(); } ## Purge the containers. $this.PurgeContainers(); ## Purge the networks. $this.PurgeNetworks(); ## Check for image purging. if ($this.PurgeImagesEnabled -or $this.DryRunEnabled) { ## Purge the images. $this.PurgeImages(); } ## Check for any removed resources. #if ($this.AnyRemoved) #{ # ## Write the message to the host, letting them know we're waiting for the engine to stabilize. # Write-Host "" -ForegroundColor Gray; # Write-Host "Waiting [15s] for the engine(s) to stabilize." -ForegroundColor Gray; # Write-Host "" -ForegroundColor Gray; # ## Wait for a few seconds to allow the engine to stabilize. # Start-Sleep -Seconds 15; #} ## Pull the images. $this.PullImages(); ## Create the networks. $this.CreateNetworks(); ## Create the containers. $this.CreateContainers(); ## Link the containers to their secondary networks. $this.LinkContainersToSecondaryNetworks(); ## Check to see if we should start the containers. if (-not $this.NoStartContainers -or $this.DryRunEnabled) { ## Start the containers. $this.StartContainers(); ## Link the containers to their routes. $this.LinkContainersToRoutes(); } ## Cleanup any dangling resources. $this.Prune(); } ## StartContainers Method. [Void] StartContainers() { <# .NAME StartContainers .SYNOPSIS Starts containers based on the definitions provided. .DESCRIPTION This method iterates over the container definitions and starts each container if it exists. It uses the specified container engine command (Docker or Podman) to perform the start operation. If dry-run mode is enabled, it will only simulate the start without actually executing the commands. #> ## Iterate over the containers. foreach ($container in $this.Containers | Where-Object { $this.OnlyCreateContainers.Count -eq 0 -or $this.OnlyCreateContainers -contains $_.Name.Trim() }) { ## Reconcile the engine command between the definition and the container. [String] $engine = $($null -ne $container.Command -and "" -ne $container.Command.Trim() ? ` $container.Command.ToString() : $this.Command.ToString()).ToLower().Trim(); ## Localize the existence of the container. [Int32] $exists = (& "${engine}" ps -a --filter "Name=$($container.Name.Trim())" --format "{{.Names}}" ` | Where-Object { $_ -eq "$($container.Name.Trim())" }).Length; ## Check if the container exists. if (0 -ne $exists -or $true -eq $this.DryRunEnabled) { ## Start the container. Write-Host "Starting container '$($container.Name.Trim())'." -ForegroundColor Green; ## Start the container in the local registry. $this.ExecuteCommand("${engine} container start '$($container.Name.Trim())'"); } } } }; |