Hi all,
I am attempting to programmatically register polling tentacles with the server using the Octopus.Client.Model or by going directly at the Web API. The two methods I have used are below:
Via the Web API:
let octopusHeaders = [ "X-Octopus-ApiKey", octopusAPIKey ]
let mutable tenantEditor = repository.Tenants.CreateOrModify(tentacleName)
let alphaNums = Seq.toList "abcdefghijklmnopqrstuvwxyz0123456789"
let random = new Random()
let tentacleURL = sprintf "poll://%s/" (new String(Array.map ( fun _ -> alphaNums.[random.Next(36)] ) [| 0..20 |]))
let tentacleRoles = [ "web-server"; "transient" ] // Transient to allow asynchronous updates
let registrationTemplate = """
{
"Endpoint": { "CommunicationStyle": "TentacleActive",
"Thumbprint": "%s",
"Address": "%s:10943",
"Squid": "",
"SubscriptionId": "%s",
"Uri": "%s" },
"EnvironmentIDs": [ "%s" ],
"TenantedDeploymentParticipation": "Tenanted",
"TenantIds": [ "%s" ],
"Name": "%s",
"Roles": %A,
"Status": "Unknown",
"IsDisabled": false
}
"""
let sprintfPayload = Printf.StringFormat<string->string->string->string->string->string->string->string list->string>(registrationTemplate)
let registrationPayloadWithSemicolons = sprintf sprintfPayload tentacleThumbprint octopusURL tentacleURL tentacleURL environment.Id tenantEditor.Instance.Id tentacleName tentacleRoles
let registrationPayload = registrationPayloadWithSemicolons.Replace(";", ",")
let registerURL = sprintf "%s/api/machines" octopusURL
let registerQuery = Register.Registration (Register.Parse registrationPayload).JsonValue
// Synchronous call
let registerData =
try
registerQuery.JsonValue.Request(registerURL, "POST", octopusHeaders) // Synchronous call
with
| :? System.Net.WebException as webEx ->
let matches = Regex("([0-9]{3})").Matches(webEx.Message)
let statusCode = match matches.Count with
| 0 -> 404
| _ -> int (matches.Item(0).Value)
log "ERROR" (sprintf "Registration of the machine with Octopus failed. HTTP response code: %i" statusCode)
logex "ERROR" webEx
{ Body = HttpResponseBody.Text (webEx.Message)
StatusCode = statusCode //int webEx.Response.StatusCode
ResponseUrl = webEx.Response.ResponseUri.OriginalString //HelpLink
Headers = (Map.empty, webEx.Response.Headers.AllKeys)
||> Array.fold ( fun map key -> let value = webEx.Response.Headers.[key]
Map.add key value map )
Cookies = Map.empty }
log "INFO" "Process complete."
registerData.StatusCode // Return HTTP response code.
Via the Octopus.Client.Model:
let tentacleEndpoint = new PollingTentacleEndpointResource()
tentacleEndpoint.Thumbprint <- tentacleThumbprint // The certificate thumbprint of the tentacle
tentacleEndpoint.Uri <- tentacleURL // A 20-character random alpha-numeric string becomes the mailbox to poll from
let tentacle = new MachineResource()
tentacle.Endpoint <- tentacleEndpoint
tentacle.Name <- tentacleName
tentacle.Uri <- tentacleURL
tentacle.EnvironmentIds.Add environment.Id |> ignore
tentacleRoles |> Seq.iter ( fun p -> tentacle.Roles.Add p |> ignore )
tentacle.TenantIds.Add tenantEditor.Instance.Id |> ignore
tentacle.MachinePolicyId <- (repository.MachinePolicies.FindByName "On-Premise").Id
let returnCode = try
repository.Machines.Create tentacle |> ignore
200
with
| :? System.Net.WebException as webEx ->
let statusCode = int (webEx.Response :?> HttpWebResponse).StatusCode
log "ERROR" ( sprintf "Registration of the machine with Octopus failed: %s \r\n\r\nHTTP response code: %i" webEx.Message statusCode )
statusCode
log "INFO" "Process complete."
returnCode
Both of these methods successfully register the tentacle with the server. However, this is the resulting TrustedOctopusServers key in Tentacle.config:
<set key="Tentacle.Communication.TrustedOctopusServers">[{"Thumbprint":"8491ADFBAE10FD7A9CAAABEE37D6103AFE474400","CommunicationStyle":1,"Address":null,"Squid":null,"SubscriptionId":null}]</set>
Thus, the tentacle does not pass the health check. The above code samples do not modify the local Tentacle.config like the Tentacle.exe does:
"C:\Program Files\Octopus Deploy\Tentacle\Tentacle.exe" register-with --instance "Tentacle" --server "https://octopus.server.com" --name "HOSTNAME" --comms-style "TentacleActive" --server-comms-port "10943" --force --apiKey "API-KEY" --environment "On-Premise" --tenanttag "Purpose/Cluster-Unaware" --tenant "TENANTNAME" --role "web-server" --role "transient" --policy "On-Premise"
Resulting in:
<set key="Tentacle.Communication.TrustedOctopusServers">[{"Thumbprint":"8491ADFBAE10FD7A9CAAABEE37D6103AFE474400","CommunicationStyle":2,"Address":"https://octopus.server.com:10943","Squid":null,"SubscriptionId":"poll://4fluhrprrh56dvhqebw6/"}]</set>
Am I missing something? Do I need to manually modify the Tentacle.config, or look for and fire off the Tentacle.exe?
Regards,
Vern