Convert-DockerInspectToCompose.psm1

function Convert-DockerInspectToCompose {
    <#
    .SYNOPSIS
        Converts docker inspect JSON into docker-compose YAML.
 
    .DESCRIPTION
        Reads docker inspect JSON (from a file or pipeline), extracts container
        configuration, and outputs a valid docker-compose YAML definition.
 
    .PARAMETER Path
        Path to a docker inspect JSON file.
 
    .EXAMPLE
        Convert-DockerInspectToCompose -Path "portainer.json"
 
    .EXAMPLE
        docker inspect portainer | Convert-DockerInspectToCompose
    #>


    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true)]
        [string]$Path,

        [Parameter(ValueFromPipeline = $true)]
        $InputObject
    )

    begin {
        $json = $null
    }

    process {
        if ($Path) {
            $json = Get-Content -Path $Path -Raw
        }
        elseif ($InputObject) {
            if ($InputObject -is [string]) {
                $json += $InputObject
            }
            else {
                $json = $InputObject
            }
        }
    }

    end {
        if (-not $json) {
            Write-Error "No JSON input provided."
            return
        }

        $inspect = $json | ConvertFrom-Json
        $container = $inspect[0]

        $name       = $container.Name.TrimStart("/")
        $image      = $container.Config.Image
        $entrypoint = $container.Config.Entrypoint
        $cmd        = $container.Config.Cmd
        $env        = $container.Config.Env
        $restart    = $container.HostConfig.RestartPolicy.Name

        # Ports
        $ports = @{}
        if ($container.HostConfig.PortBindings) {
            foreach ($key in $container.HostConfig.PortBindings.PSObject.Properties.Name) {
                foreach ($binding in $container.HostConfig.PortBindings.$key) {
                    $ports[$key] += "$($binding.HostPort):$key"
                }
            }
        }

        # Volumes
        $volumes = @()
        foreach ($mount in $container.Mounts) {
            if ($mount.Type -eq "bind") {
                $volumes += "$($mount.Source):$($mount.Destination)"
            }
        }

        # Networks
        $networks = @()
        foreach ($net in $container.NetworkSettings.Networks.PSObject.Properties.Name) {
            $networks += $net
        }

        # YAML Output
        Write-Output "version: '3.9'"
        Write-Output "services:"
        Write-Output " ${name}:"
        Write-Output " image: '$image'"

        if ($entrypoint) {
            Write-Output " entrypoint:"
            foreach ($e in $entrypoint) {
                Write-Output " - '$e'"
            }
        }

        if ($cmd) {
            Write-Output " command:"
            foreach ($c in $cmd) {
                Write-Output " - '$c'"
            }
        }

        if ($env) {
            Write-Output " environment:"
            foreach ($e in $env) {
                Write-Output " - '$e'"
            }
        }

        if ($ports.Count -gt 0) {
            Write-Output " ports:"
            foreach ($p in $ports.Values) {
                foreach ($mapping in $p) {
                    Write-Output " - '$mapping'"
                }
            }
        }

        if ($volumes.Count -gt 0) {
            Write-Output " volumes:"
            foreach ($v in $volumes) {
                Write-Output " - '$v'"
            }
        }

        if ($networks.Count -gt 0) {
            Write-Output " networks:"
            foreach ($n in $networks) {
                Write-Output " - $n"
            }
        }

        if ($restart -and $restart -ne "no") {
            Write-Output " restart: '$restart'"
        }

        if ($networks.Count -gt 0) {
            Write-Output ""
            Write-Output "networks:"
            foreach ($n in $networks) {
                Write-Output " ${n}:"
                Write-Output " external: true"
            }
        }
    }
}

Export-ModuleMember -Function Convert-DockerInspectToCompose