160 lines
6.3 KiB
YAML
160 lines
6.3 KiB
YAML
---
|
|
- name: Determine if Tailscale operator is enabled
|
|
set_fact:
|
|
tailscale_operator_enabled: "{{ (tailscale_oauth_client_id | default('') | length) > 0 and (tailscale_oauth_client_secret | default('') | length) > 0 }}"
|
|
tailscale_operator_ready: false
|
|
changed_when: false
|
|
|
|
- name: Skip Tailscale operator when OAuth credentials are missing
|
|
debug:
|
|
msg: "Skipping Tailscale Kubernetes Operator: set TAILSCALE_OAUTH_CLIENT_ID and TAILSCALE_OAUTH_CLIENT_SECRET to enable it."
|
|
when: not tailscale_operator_enabled
|
|
|
|
- name: End Tailscale operator role when disabled
|
|
meta: end_host
|
|
when: not tailscale_operator_enabled
|
|
|
|
- name: Check if Helm is installed
|
|
command: helm version --short
|
|
register: helm_check
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Install Helm
|
|
shell: curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
|
when: helm_check.rc != 0
|
|
changed_when: true
|
|
|
|
- name: Create Tailscale operator namespace
|
|
command: kubectl create namespace {{ tailscale_operator_namespace }}
|
|
register: create_ns
|
|
failed_when: create_ns.rc != 0 and "AlreadyExists" not in create_ns.stderr
|
|
changed_when: create_ns.rc == 0
|
|
|
|
- name: Add Tailscale Helm repo
|
|
command: helm repo add tailscale https://pkgs.tailscale.com/unstable/helmcharts
|
|
register: add_repo
|
|
failed_when: add_repo.rc != 0 and "already exists" not in add_repo.stderr
|
|
changed_when: add_repo.rc == 0
|
|
|
|
- name: Update Helm repos
|
|
command: helm repo update
|
|
changed_when: false
|
|
|
|
- name: Write Tailscale operator values
|
|
template:
|
|
src: operator-values.yaml.j2
|
|
dest: /tmp/tailscale-operator-values.yaml
|
|
mode: "0644"
|
|
|
|
- name: Create or update Tailscale operator OAuth secret
|
|
shell: >-
|
|
kubectl -n {{ tailscale_operator_namespace }} create secret generic operator-oauth
|
|
--from-literal=client_id='{{ tailscale_oauth_client_id }}'
|
|
--from-literal=client_secret='{{ tailscale_oauth_client_secret }}'
|
|
--dry-run=client -o yaml | kubectl apply -f -
|
|
register: oauth_secret_result
|
|
changed_when: "'created' in oauth_secret_result.stdout or 'configured' in oauth_secret_result.stdout"
|
|
|
|
- name: Install Tailscale Kubernetes Operator
|
|
command: >-
|
|
helm upgrade --install tailscale-operator tailscale/tailscale-operator
|
|
--namespace {{ tailscale_operator_namespace }}
|
|
--version {{ tailscale_operator_version }}
|
|
--values /tmp/tailscale-operator-values.yaml
|
|
--timeout 5m
|
|
register: tailscale_install
|
|
failed_when: false
|
|
changed_when: true
|
|
|
|
- name: Show Tailscale operator pods on install failure
|
|
command: kubectl -n {{ tailscale_operator_namespace }} get pods -o wide
|
|
register: tailscale_pods
|
|
changed_when: false
|
|
failed_when: false
|
|
when: tailscale_install.rc != 0
|
|
|
|
- name: Show Tailscale operator events on install failure
|
|
command: kubectl -n {{ tailscale_operator_namespace }} get events --sort-by=.lastTimestamp
|
|
register: tailscale_events
|
|
changed_when: false
|
|
failed_when: false
|
|
when: tailscale_install.rc != 0
|
|
|
|
- name: Fail with Tailscale operator diagnostics
|
|
fail:
|
|
msg: |
|
|
Tailscale operator install failed.
|
|
Helm stderr:
|
|
{{ tailscale_install.stderr | default('') }}
|
|
|
|
Pods:
|
|
{{ tailscale_pods.stdout | default('n/a') }}
|
|
|
|
Events:
|
|
{{ tailscale_events.stdout | default('n/a') }}
|
|
when: tailscale_install.rc != 0
|
|
|
|
- name: Wait for Tailscale operator to be ready
|
|
command: kubectl -n {{ tailscale_operator_namespace }} rollout status deployment/operator --timeout=5m
|
|
register: tailscale_rollout
|
|
failed_when: false
|
|
changed_when: false
|
|
|
|
- name: Show Tailscale operator deployment status
|
|
command: kubectl -n {{ tailscale_operator_namespace }} get deployment operator -o wide
|
|
register: tailscale_deploy
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Get Tailscale operator logs
|
|
command: kubectl -n {{ tailscale_operator_namespace }} logs deployment/operator --tail=200
|
|
register: tailscale_operator_logs
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Fail when Tailscale OAuth permissions are insufficient
|
|
fail:
|
|
msg: |
|
|
Tailscale operator started but cannot create auth keys (OAuth/tag permission error).
|
|
Fix your Tailscale OAuth client/tag permissions.
|
|
|
|
Required checks in Tailscale admin:
|
|
- OAuth client has devices:core, auth_keys, and services write access
|
|
- OAuth client can create tagged devices for: {{ tailscale_operator_default_tags | join(', ') }}
|
|
- ACL/tag ownership allows those tags for this OAuth client
|
|
|
|
Operator log excerpt:
|
|
{{ tailscale_operator_logs.stdout | default('n/a') }}
|
|
when:
|
|
- tailscale_operator_required | bool
|
|
- "tailscale_operator_logs.stdout is defined and ('does not have enough permissions' in tailscale_operator_logs.stdout or 'Status: 403' in tailscale_operator_logs.stdout or 'invalid or not permitted' in tailscale_operator_logs.stdout or 'Status: 400' in tailscale_operator_logs.stdout)"
|
|
|
|
- name: Warn when Tailscale OAuth permissions are insufficient (non-blocking)
|
|
debug:
|
|
msg: |
|
|
Tailscale operator is not ready due to OAuth/tag permissions.
|
|
Continuing deployment because tailscale_operator_required=false.
|
|
Operator log excerpt:
|
|
{{ tailscale_operator_logs.stdout | default('n/a') }}
|
|
when:
|
|
- not (tailscale_operator_required | bool)
|
|
- "tailscale_operator_logs.stdout is defined and ('does not have enough permissions' in tailscale_operator_logs.stdout or 'Status: 403' in tailscale_operator_logs.stdout or 'invalid or not permitted' in tailscale_operator_logs.stdout or 'Status: 400' in tailscale_operator_logs.stdout)"
|
|
|
|
- name: Mark Tailscale operator ready when rollout succeeds and no auth errors
|
|
set_fact:
|
|
tailscale_operator_ready: true
|
|
when:
|
|
- tailscale_rollout.rc == 0
|
|
- "tailscale_operator_logs.stdout is not defined or (('does not have enough permissions' not in tailscale_operator_logs.stdout) and ('Status: 403' not in tailscale_operator_logs.stdout) and ('invalid or not permitted' not in tailscale_operator_logs.stdout) and ('Status: 400' not in tailscale_operator_logs.stdout))"
|
|
|
|
- name: Warn if Tailscale operator is not ready yet
|
|
debug:
|
|
msg: |
|
|
Tailscale operator deployment is still converging.
|
|
This is non-blocking for CI; service endpoints may appear shortly.
|
|
Rollout output:
|
|
{{ tailscale_rollout.stdout | default('') }}
|
|
{{ tailscale_deploy.stdout | default('') }}
|
|
when: tailscale_rollout.rc != 0
|