351 lines
12 KiB
PowerShell
351 lines
12 KiB
PowerShell
<#
|
|
run.ps1 executes the agent
|
|
#>
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$WarningPreference = 'SilentlyContinue'
|
|
$VerbosePreference = 'SilentlyContinue'
|
|
$DebugPreference = 'SilentlyContinue'
|
|
$InformationPreference = 'SilentlyContinue'
|
|
|
|
Import-Module -WarningAction Ignore -Name "$PSScriptRoot\utils.psm1"
|
|
|
|
function Get-Address
|
|
{
|
|
param(
|
|
[parameter(Mandatory = $false)] [string]$Addr
|
|
)
|
|
|
|
if (-not $Addr) {
|
|
return ""
|
|
}
|
|
|
|
# If given address is a network interface on the system, retrieve configured IP on that interface (only the first configured IP is taken)
|
|
try {
|
|
$getAdapterJson = wins.exe cli net get --name $Addr
|
|
if ($?) {
|
|
$namedNetwork = $getAdapterJson | ConvertTo-JsonObj
|
|
if ($namedNetwork) {
|
|
return $namedNetwork.AddressCIDR -replace "/32",""
|
|
}
|
|
}
|
|
} catch {}
|
|
|
|
# Repair the container route for `169.254.169.254` before cloud provider query
|
|
$actualGateway = $(route.exe print 0.0.0.0 | Where-Object {$_ -match '0\.0\.0\.0.*[a-z]'} | Select-Object -First 1 | ForEach-Object {($_ -replace '0\.0\.0\.0|[a-z]|\s+',' ').Trim() -split ' '} | Select-Object -First 1)
|
|
$expectedGateway = $(route.exe print 169.254.169.254 | Where-Object {$_ -match '169\.254\.169\.254'} | Select-Object -First 1 | ForEach-Object {($_ -replace '169\.254\.169\.254|255\.255\.255\.255|[a-z]|\s+',' ').Trim() -split ' '} | Select-Object -First 1)
|
|
if ($actualGateway -ne $expectedGateway) {
|
|
$errMsg = $(route.exe add 169.254.169.254 MASK 255.255.255.255 $actualGateway METRIC 1)
|
|
if (-not $?) {
|
|
Log-Error "Could not repair contain route for using cloud provider"
|
|
}
|
|
}
|
|
|
|
# Loop through cloud provider options to get IP from metadata, if not found return given value
|
|
switch ($Addr)
|
|
{
|
|
"awslocal" {
|
|
return $(curl.exe -s "http://169.254.169.254/latest/meta-data/local-ipv4")
|
|
}
|
|
"awspublic" {
|
|
return $(curl.exe -s "http://169.254.169.254/latest/meta-data/public-ipv4")
|
|
}
|
|
"doprivate" {
|
|
return $(curl.exe -s "http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address")
|
|
}
|
|
"dopublic" {
|
|
return $(curl.exe -s "http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address")
|
|
}
|
|
"azprivate" {
|
|
return $(curl.exe -s -H "Metadata:true" "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/privateIpAddress?api-version=2017-08-01&format=text")
|
|
}
|
|
"azpublic" {
|
|
return $(curl.exe -s -H "Metadata:true" "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-08-01&format=text")
|
|
}
|
|
"gceinternal" {
|
|
return $(curl.exe -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip?alt=json")
|
|
}
|
|
"gceexternal" {
|
|
return $(curl.exe -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip?alt=json")
|
|
}
|
|
"packetlocal" {
|
|
return $(curl.exe -s "https://metadata.packet.net/2009-04-04/meta-data/local-ipv4")
|
|
}
|
|
"packetpublic" {
|
|
return $(curl.exe -s "https://metadata.packet.net/2009-04-04/meta-data/public-ipv4")
|
|
}
|
|
"ipify" {
|
|
return $(curl.exe -s "https://api.ipify.org")
|
|
}
|
|
}
|
|
|
|
return $Addr
|
|
}
|
|
|
|
# required envs
|
|
Set-Env -Key "DOCKER_HOST" -Value "npipe:////./pipe/docker_engine"
|
|
Set-Env -Key "CATTLE_ROLE" -Value "worker"
|
|
|
|
# clean up
|
|
$CLUSTER_CLEANUP = Get-Env -Key "CLUSTER_CLEANUP"
|
|
if ($CLUSTER_CLEANUP -eq "true")
|
|
{
|
|
Start-Process -NoNewWindow -Wait -FilePath "c:\etc\rancher\agent.exe"
|
|
exit 0
|
|
}
|
|
|
|
# init parameters
|
|
$CATTLE_SERVER = Get-Env -Key "CATTLE_SERVER"
|
|
$CATTLE_TOKEN = Get-Env -Key "CATTLE_TOKEN"
|
|
$CATTLE_NODE_NAME = Get-Env -Key "CATTLE_NODE_NAME"
|
|
$CATTLE_ADDRESS = Get-Env -Key "CATTLE_ADDRESS"
|
|
$CATTLE_INTERNAL_ADDRESS = Get-Env -Key "CATTLE_INTERNAL_ADDRESS"
|
|
$CATTLE_CA_CHECKSUM = Get-Env -Key "CATTLE_CA_CHECKSUM"
|
|
$CATTLE_NODE_LABEL = @()
|
|
$CATTLE_NODE_TAINTS = @()
|
|
|
|
# parse arguments
|
|
$vals = $null
|
|
for ($i = $args.Length; $i -ge 0; $i--)
|
|
{
|
|
$arg = $args[$i]
|
|
switch -regex ($arg)
|
|
{
|
|
'^(-d|--debug)$' {
|
|
Set-Env -Key "CATTLE_DEBUG" -Value "true"
|
|
$vals = $null
|
|
}
|
|
'^(-s|--server)$' {
|
|
$CATTLE_SERVER = ($vals | Select-Object -First 1)
|
|
$vals = $null
|
|
}
|
|
'^(-t|--token)$' {
|
|
$CATTLE_TOKEN = ($vals | Select-Object -First 1)
|
|
$vals = $null
|
|
}
|
|
'^(-c|--ca-checksum)$' {
|
|
$CATTLE_CA_CHECKSUM = ($vals | Select-Object -First 1)
|
|
$vals = $null
|
|
}
|
|
'^(-all|--all-roles)$' {
|
|
$vals = $null
|
|
}
|
|
'^(-e|--etcd)$' {
|
|
$vals = $null
|
|
}
|
|
'^(-w|--worker)$' {
|
|
$vals = $null
|
|
}
|
|
'^(-p|--controlplane)$' {
|
|
$vals = $null
|
|
}
|
|
'^(-r|--node-name)$' {
|
|
$CATTLE_NODE_NAME = ($vals | Select-Object -First 1)
|
|
$vals = $null
|
|
}
|
|
'^(-n|--no-register)$' {
|
|
Set-Env -Key "CATTLE_AGENT_CONNECT" -Value "true"
|
|
$vals = $null
|
|
}
|
|
'^(-a|--address)$' {
|
|
$CATTLE_ADDRESS = ($vals | Select-Object -First 1)
|
|
$vals = $null
|
|
}
|
|
'^(-i|--internal-address)$' {
|
|
$CATTLE_INTERNAL_ADDRESS = ($vals | Select-Object -First 1)
|
|
$vals = $null
|
|
}
|
|
'^(-l|--label)$' {
|
|
if ($vals) {
|
|
$CATTLE_NODE_LABEL += $vals
|
|
}
|
|
$vals = $null
|
|
}
|
|
'^(-o|--only-write-certs)$' {
|
|
Set-Env -Key "CATTLE_WRITE_CERT_ONLY" -Value "true"
|
|
$vals = $null
|
|
}
|
|
'^--taints$' {
|
|
if ($vals) {
|
|
$CATTLE_NODE_TAINTS += $vals
|
|
}
|
|
$vals = $null
|
|
}
|
|
default {
|
|
if ($vals) {
|
|
$vals = ,$arg + $vals
|
|
} else {
|
|
$vals = @($arg)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# use the register token to request wins server
|
|
if (Test-Path -PathType Leaf -Path "c:\cattle-credentials\token")
|
|
{
|
|
$token = Get-Content -Path "c:\cattle-credentials\token" -Raw -ErrorAction Ignore
|
|
Set-Env -Key "WINS_AUTH_TOKEN" -Value $token
|
|
}
|
|
|
|
# check docker npipe
|
|
$CATTLE_CLUSTER = Get-Env -Key "CATTLE_CLUSTER"
|
|
if ($CATTLE_CLUSTER -ne "true")
|
|
{
|
|
$dockerNPipe = Get-ChildItem //./pipe/ -ErrorAction Ignore | ? Name -eq "docker_engine"
|
|
if (-not $dockerNPipe) {
|
|
Log-Warn "Default docker named pipe is not found"
|
|
Log-Warn "Please bind mount in the docker named pipe to //./pipe/docker_engine if docker errors occur"
|
|
Log-Warn "example: docker run -v //./pipe/custom_docker_named_pipe://./pipe/docker_engine ..."
|
|
}
|
|
}
|
|
|
|
# get address
|
|
$CATTLE_ADDRESS = Get-Address -Addr $CATTLE_ADDRESS
|
|
$CATTLE_INTERNAL_ADDRESS = Get-Address -Addr $CATTLE_INTERNAL_ADDRESS
|
|
|
|
# get default network metadata when nodeName or address is blank
|
|
if ((-not $CATTLE_NODE_NAME) -or (-not $CATTLE_ADDRESS))
|
|
{
|
|
$getAdapterJson = wins.exe cli net get
|
|
if ($?) {
|
|
$defaultNetwork = $getAdapterJson | ConvertTo-JsonObj
|
|
if ($defaultNetwork) {
|
|
if (-not $CATTLE_NODE_NAME) {
|
|
$CATTLE_NODE_NAME = $defaultNetwork.HostName
|
|
$CATTLE_NODE_NAME = $CATTLE_NODE_NAME.ToLower()
|
|
}
|
|
|
|
if (-not $CATTLE_ADDRESS) {
|
|
$CATTLE_ADDRESS = $defaultNetwork.AddressCIDR -replace "/32",""
|
|
}
|
|
} else {
|
|
Log-Warn "Could not convert '$getAdapterJson' to json object"
|
|
}
|
|
} else {
|
|
Log-Warn "Could not get host network metadata: $getAdapterJson"
|
|
}
|
|
}
|
|
|
|
# check token and address
|
|
$CATTLE_K8S_MANAGED = Get-Env -Key "CATTLE_K8S_MANAGED"
|
|
if ($CATTLE_K8S_MANAGED -ne "true")
|
|
{
|
|
if (-not $CATTLE_TOKEN) {
|
|
Log-Fatal "--token is a required option"
|
|
}
|
|
if (-not $CATTLE_ADDRESS) {
|
|
Log-Fatal "--address is a required option"
|
|
}
|
|
}
|
|
|
|
# check rancher server address
|
|
if (-not $CATTLE_SERVER)
|
|
{
|
|
Log-Fatal "--server is a required option"
|
|
}
|
|
|
|
# check rancher server
|
|
try
|
|
{
|
|
curl.exe --insecure -s -fL "$CATTLE_SERVER/ping" | Out-Null
|
|
if ($?) {
|
|
Log-Info "$CATTLE_SERVER is accessible"
|
|
} else {
|
|
Log-Fatal "$CATTLE_SERVER is not accessible"
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Log-Fatal "$CATTLE_SERVER is not accessible: $($_.Exception.Message)"
|
|
}
|
|
|
|
# download cattle server CA
|
|
if ($CATTLE_CA_CHECKSUM)
|
|
{
|
|
$sslCertDir = Get-Env -Key "SSL_CERT_DIR"
|
|
$server = $CATTLE_SERVER
|
|
$caChecksum = $CATTLE_CA_CHECKSUM
|
|
$temp = New-TemporaryFile
|
|
$cacerts = $null
|
|
try {
|
|
$cacerts = $(curl.exe --insecure -s -fL "$server/v3/settings/cacerts" | ConvertTo-JsonObj).value
|
|
} catch {}
|
|
if (-not $cacerts) {
|
|
Log-Fatal "Could not get cattle server CA from $server"
|
|
}
|
|
|
|
$cacerts + "`n" | Out-File -NoNewline -Encoding ascii -FilePath $temp.FullName
|
|
$tempHasher = Get-FileHash -LiteralPath $temp.FullName -Algorithm SHA256
|
|
if ($tempHasher.Hash.ToLower() -ne $caChecksum.ToLower()) {
|
|
$temp.Delete()
|
|
Log-Fatal "Actual cattle server CA checksum is $($tempHasher.Hash.ToLower()), $server/v3/settings/cacerts does not match $($caChecksum.ToLower())"
|
|
}
|
|
Remove-Item -Force -Recurse -Path "$sslCertDir\serverca" -ErrorAction Ignore
|
|
New-Item -Force -ItemType Directory -Path $sslCertDir -ErrorAction Ignore | Out-Null
|
|
$temp.MoveTo("$sslCertDir\serverca")
|
|
|
|
# import the self-signed certificate
|
|
$caBytes = $null
|
|
Get-Content "$sslCertDir\serverca" | % {
|
|
if ($_ -match '-+BEGIN CERTIFICATE-+') {
|
|
$caBytes = @()
|
|
} elseif ($_ -match '-+END CERTIFICATE-+') {
|
|
$caTemp = New-TemporaryFile
|
|
$caString = [Convert]::ToBase64String($caBytes)
|
|
Set-Content -Value $caString -Path $caTemp.FullName
|
|
certoc.exe -addstore root $caTemp.FullName | Out-Null
|
|
if (-not $?) {
|
|
$caTemp.Delete()
|
|
Log-Fatal "Failed to import rancher server certificates to Root"
|
|
}
|
|
$caTemp.Delete()
|
|
} else {
|
|
$caBytes += [Convert]::FromBase64String($_)
|
|
}
|
|
}
|
|
|
|
$CATTLE_SERVER_HOSTNAME = ([System.Uri]"$server").Host
|
|
$CATTLE_SERVER_HOSTNAME_WITH_PORT = ([System.Uri]"$server").Authority
|
|
|
|
# windows path could not allow colons
|
|
$CATTLE_SERVER_HOSTNAME_WITH_PORT = $CATTLE_SERVER_HOSTNAME_WITH_PORT -replace ":", ""
|
|
|
|
$dockerCertsPath = "c:\etc\docker\certs.d\$CATTLE_SERVER_HOSTNAME_WITH_PORT"
|
|
New-Item -Force -ItemType Directory -Path $dockerCertsPath -ErrorAction Ignore | Out-Null
|
|
Copy-Item -Force -Path "$sslCertDir\serverca" -Destination "$dockerCertsPath\ca.crt" -ErrorAction Ignore
|
|
}
|
|
|
|
# add labels
|
|
$getVersionJson = wins.exe cli host get-version
|
|
if ($?) {
|
|
$windowsCurrentVersion = $getVersionJson | ConvertTo-JsonObj
|
|
if ($windowsCurrentVersion) {
|
|
$versionTag = "$($windowsCurrentVersion.CurrentMajorVersionNumber).$($windowsCurrentVersion.CurrentMinorVersionNumber).$($windowsCurrentVersion.CurrentBuildNumber).$($windowsCurrentVersion.UBR)"
|
|
$CATTLE_NODE_LABEL += @("rke.cattle.io/windows-version=$versionTag")
|
|
$CATTLE_NODE_LABEL += @("rke.cattle.io/windows-release-id=$($windowsCurrentVersion.ReleaseId)")
|
|
$CATTLE_NODE_LABEL += @("rke.cattle.io/windows-major-version=$($windowsCurrentVersion.CurrentMajorVersionNumber)")
|
|
$CATTLE_NODE_LABEL += @("rke.cattle.io/windows-minor-version=$($windowsCurrentVersion.CurrentMinorVersionNumber)")
|
|
$CATTLE_NODE_LABEL += @("rke.cattle.io/windows-kernel-version=$($windowsCurrentVersion.BuildLabEx)")
|
|
$CATTLE_NODE_LABEL += @("rke.cattle.io/windows-build=$($windowsCurrentVersion.CurrentBuild)")
|
|
} else {
|
|
Log-Warn "Could not convert Windows Current Version JSON '$getVersionJson' to object"
|
|
}
|
|
} else {
|
|
Log-Warn "Could not get host version: $getVersionJson"
|
|
}
|
|
|
|
# set environment variables
|
|
Set-Env -Key "CATTLE_SERVER" -Value $CATTLE_SERVER
|
|
Set-Env -Key "CATTLE_TOKEN" -Value $CATTLE_TOKEN
|
|
Set-Env -Key "CATTLE_ADDRESS" -Val $CATTLE_ADDRESS
|
|
Set-Env -Key "CATTLE_INTERNAL_ADDRESS" -Val $CATTLE_INTERNAL_ADDRESS
|
|
Set-Env -Key "CATTLE_NODE_NAME" -Value $CATTLE_NODE_NAME
|
|
Set-Env -Key "CATTLE_NODE_LABEL" -Value $($CATTLE_NODE_LABEL -join ",")
|
|
Set-Env -Key "CATTLE_NODE_TAINTS" -Value $($CATTLE_NODE_TAINTS -join ",")
|
|
|
|
# upgrade wins.exe
|
|
Transfer-File -Src c:\Windows\wins.exe -Dst c:\etc\rancher\wins\wins.exe
|
|
|
|
Start-Process -NoNewWindow -Wait -FilePath "c:\etc\rancher\agent.exe"
|