chore: add k8s and docker as service to agent and update logic for ansible deploy
ci-agent / build (push) Failing after 2m35s
ci-agent / build (push) Failing after 2m35s
This commit is contained in:
@@ -7,32 +7,39 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ErrUnknownDeployType is returned when an unsupported deployment type is specified
|
||||
var ErrUnknownDeployType = fmt.Errorf("unknown deploy type, expected 'docker' or 'binary'")
|
||||
|
||||
// Executor handles running Ansible playbooks
|
||||
type Executor struct {
|
||||
workDir string
|
||||
grpcServerHost string
|
||||
grpcServerPort string
|
||||
backendURL string
|
||||
workDir string
|
||||
grpcServerHost string
|
||||
grpcServerPort string
|
||||
backendURL string
|
||||
giteaReleasesURL string
|
||||
}
|
||||
|
||||
// ExecutorConfig holds configuration for the Executor
|
||||
type ExecutorConfig struct {
|
||||
WorkDir string
|
||||
GRPCServerHost string
|
||||
GRPCServerPort string
|
||||
BackendURL string
|
||||
WorkDir string
|
||||
GRPCServerHost string
|
||||
GRPCServerPort string
|
||||
BackendURL string
|
||||
GiteaReleasesURL string
|
||||
}
|
||||
|
||||
// NewExecutor creates a new Ansible executor
|
||||
func NewExecutor(cfg ExecutorConfig) *Executor {
|
||||
return &Executor{
|
||||
workDir: cfg.WorkDir,
|
||||
grpcServerHost: cfg.GRPCServerHost,
|
||||
grpcServerPort: cfg.GRPCServerPort,
|
||||
backendURL: cfg.BackendURL,
|
||||
workDir: cfg.WorkDir,
|
||||
grpcServerHost: cfg.GRPCServerHost,
|
||||
grpcServerPort: cfg.GRPCServerPort,
|
||||
backendURL: cfg.BackendURL,
|
||||
giteaReleasesURL: cfg.GiteaReleasesURL,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +62,42 @@ func (e *Executor) GRPCURL() string {
|
||||
return e.grpcServerHost + ":" + e.grpcServerPort
|
||||
}
|
||||
|
||||
// CheckDockerCollection verifies that the community.docker Ansible collection is installed.
|
||||
// Returns an error if the collection is not found.
|
||||
func (e *Executor) CheckDockerCollection() error {
|
||||
cmd := exec.Command("ansible-galaxy", "collection", "list", "community.docker")
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("community.docker collection not found: %s", stderr.String())
|
||||
}
|
||||
|
||||
// ansible-galaxy collection list returns output like:
|
||||
// # /usr/share/ansible/collections/ansible_collections
|
||||
// Collection Version
|
||||
// ---------------- -------
|
||||
// community.docker 3.10.0
|
||||
//
|
||||
// If the collection is not installed, it won't appear in the output.
|
||||
if !strings.Contains(stdout.String(), "community.docker") {
|
||||
return fmt.Errorf("community.docker collection is not installed. Run: ansible-galaxy collection install community.docker")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deploy runs Ansible playbook for the given inventory
|
||||
func (e *Executor) Deploy(
|
||||
ctx context.Context,
|
||||
inventoryPath string,
|
||||
deployType string,
|
||||
) ([]DeployResult, error) {
|
||||
if deployType != "docker" && deployType != "binary" {
|
||||
return nil, fmt.Errorf("invalid deploy type %q: %w", deployType, ErrUnknownDeployType)
|
||||
}
|
||||
|
||||
playbookName := "binary_deploy.yml"
|
||||
if deployType == "docker" {
|
||||
playbookName = "docker_deploy.yml"
|
||||
@@ -72,6 +109,7 @@ func (e *Executor) Deploy(
|
||||
"-i", inventoryPath,
|
||||
"-e", fmt.Sprintf("backend_url=%s", e.backendURL),
|
||||
"-e", fmt.Sprintf("grpc_url=%s", e.grpcServerHost+":"+e.grpcServerPort),
|
||||
"-e", fmt.Sprintf("gitea_releases_url=%s", e.giteaReleasesURL),
|
||||
playbookPath,
|
||||
)
|
||||
|
||||
@@ -100,6 +138,7 @@ func (e *Executor) DeployParallel(
|
||||
deployType string,
|
||||
) (map[string][]DeployResult, error) {
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
results := make(map[string][]DeployResult)
|
||||
errCh := make(chan error, len(inventoryPaths))
|
||||
|
||||
@@ -111,7 +150,9 @@ func (e *Executor) DeployParallel(
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
mu.Lock()
|
||||
results[p] = res
|
||||
mu.Unlock()
|
||||
}(path)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,16 +26,13 @@ type Inventory struct {
|
||||
Hosts []InventoryHost
|
||||
}
|
||||
|
||||
const inventoryTemplateText = `{{ range .Hosts }}
|
||||
{{ .Name }} ansible_host={{ .IP }} ansible_port={{ .Port }} ansible_user={{ .User }} ansible_connection=ssh
|
||||
{{ if eq .AuthMethod "key" }}ansible_ssh_private_key_file={{ .SSHKey }}{{ end }}
|
||||
{{ if eq .AuthMethod "password" }}ansible_ssh_pass={{ .Password }}{{ end }}
|
||||
deploy_type={{ .DeployType }}
|
||||
agent_token={{ .Token }}
|
||||
agent_label={{ .Name }}
|
||||
grpc_url={{ .GRPCURL }}
|
||||
|
||||
{{ end }}`
|
||||
const inventoryTemplateText = `{{- range $i, $host := .Hosts }}
|
||||
{{ $host.Name }} ansible_host={{ $host.IP }} ansible_port={{ $host.Port }} ansible_user={{ $host.User }} ansible_connection=ssh{{ if eq $host.AuthMethod "key" }} ansible_ssh_private_key_file={{ $host.SSHKey }}{{ end }}{{ if eq $host.AuthMethod "password" }} ansible_ssh_pass={{ $host.Password }}{{ end }}
|
||||
deploy_type={{ $host.DeployType }}
|
||||
agent_token={{ $host.Token }}
|
||||
agent_label={{ $host.Name }}
|
||||
grpc_url={{ $host.GRPCURL }}
|
||||
{{ end -}}`
|
||||
|
||||
// GenerateInventory generates an Ansible inventory file from the given hosts
|
||||
func GenerateInventory(hosts []InventoryHost, outputPath string) error {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package ansible
|
||||
|
||||
// BinaryDeployPlaybook returns the Ansible playbook for binary deployment.
|
||||
// Downloads the agent binary, writes config, and starts it directly (no systemd).
|
||||
// systemd unit is managed separately (e.g. via goreleaser .deb/.rpm packages).
|
||||
// Downloads the agent binary, writes config, and installs a systemd unit for automatic restart.
|
||||
const BinaryDeployPlaybook = `---
|
||||
- name: Deploy HellreigN Agent (Binary)
|
||||
hosts: all
|
||||
@@ -14,6 +13,7 @@ const BinaryDeployPlaybook = `---
|
||||
install_dir: /opt/hellreign
|
||||
bin_name: hellreign-agent
|
||||
cert_dir: "{{ install_dir }}/certs"
|
||||
gitea_releases_url: "{{ gitea_releases_url | default('https://gitea.d3m0k1d.ru/d3m0k1d/HellreigN/releases/latest/download') }}"
|
||||
|
||||
tasks:
|
||||
- name: Create installation directory
|
||||
@@ -30,7 +30,7 @@ const BinaryDeployPlaybook = `---
|
||||
|
||||
- name: Download HellreigN Agent binary
|
||||
get_url:
|
||||
url: "https://gitea.d3m0k1d.ru/d3m0k1d/HellreigN/releases/latest/download/{{ bin_name }}"
|
||||
url: "{{ gitea_releases_url }}/{{ bin_name }}"
|
||||
dest: "{{ install_dir }}/{{ bin_name }}"
|
||||
mode: '0755'
|
||||
|
||||
@@ -48,16 +48,43 @@ const BinaryDeployPlaybook = `---
|
||||
dest: "{{ install_dir }}/config.yml"
|
||||
mode: '0644'
|
||||
|
||||
- name: Start HellreigN Agent
|
||||
shell: |
|
||||
nohup {{ install_dir }}/{{ bin_name }} > /dev/null 2>&1 &
|
||||
echo $!
|
||||
args:
|
||||
executable: /bin/bash
|
||||
environment:
|
||||
CONFIG_FILE: "{{ install_dir }}/config.yml"
|
||||
register: agent_pid
|
||||
changed_when: true
|
||||
- name: Create systemd unit file
|
||||
copy:
|
||||
content: |
|
||||
[Unit]
|
||||
Description=HellreigN Agent
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart={{ install_dir }}/{{ bin_name }}
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
Environment=CONFIG_FILE={{ install_dir }}/config.yml
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
dest: /etc/systemd/system/hellreign-agent.service
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload systemd daemon
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Enable and start HellreigN Agent service
|
||||
systemd:
|
||||
name: hellreign-agent
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Wait for agent to start
|
||||
pause:
|
||||
seconds: 3
|
||||
|
||||
- name: Verify HellreigN Agent is running
|
||||
command: systemctl is-active --quiet hellreign-agent
|
||||
changed_when: false
|
||||
`
|
||||
|
||||
// DockerDeployPlaybook returns the Ansible playbook for Docker deployment.
|
||||
@@ -72,7 +99,9 @@ const DockerDeployPlaybook = `---
|
||||
grpc_url: "{{ grpc_url | default('localhost:9001') }}"
|
||||
container_name: hellreign-agent-{{ agent_label }}
|
||||
image: "gitea.d3m0k1d.ru/d3m0k1d/hellreign-agent:latest"
|
||||
install_dir: /opt/hellreign
|
||||
cert_dir: /etc/hellreign-agent/certs
|
||||
config_dir: /etc/hellreign-agent
|
||||
|
||||
tasks:
|
||||
- name: Install Docker (if not present)
|
||||
@@ -94,6 +123,12 @@ const DockerDeployPlaybook = `---
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create configuration directory
|
||||
file:
|
||||
path: "{{ config_dir }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Pull HellreigN Agent image
|
||||
community.docker.docker_image:
|
||||
name: "{{ image }}"
|
||||
@@ -103,14 +138,15 @@ const DockerDeployPlaybook = `---
|
||||
copy:
|
||||
content: |
|
||||
backend_url: "{{ backend_url }}"
|
||||
grpc_url: "{{ grpc_url }}"
|
||||
grpc_url: "{{ grpc_url | default('localhost:9001') }}"
|
||||
label: "{{ agent_label }}"
|
||||
registration_token: "{{ agent_token }}"
|
||||
cert_dir: "{{ cert_dir }}"
|
||||
services:
|
||||
- name: system
|
||||
type: journald
|
||||
dest: "{{ cert_dir }}/config.yml"
|
||||
- name: "{{ agent_label }}"
|
||||
type: docker
|
||||
path: "{{ container_name }}"
|
||||
dest: "{{ config_dir }}/config.yml"
|
||||
mode: '0644'
|
||||
|
||||
- name: Create and run HellreigN Agent container
|
||||
@@ -121,6 +157,7 @@ const DockerDeployPlaybook = `---
|
||||
restart_policy: always
|
||||
volumes:
|
||||
- "{{ cert_dir }}:/etc/hellreign-agent/certs"
|
||||
- "{{ config_dir }}/config.yml:/etc/hellreign-agent/config.yml:ro"
|
||||
env:
|
||||
CONFIG_FILE: /etc/hellreign-agent/certs/config.yml
|
||||
CONFIG_FILE: /etc/hellreign-agent/config.yml
|
||||
`
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
package ansible
|
||||
|
||||
const BaseInvTemplate = `
|
||||
|
||||
`
|
||||
// This package contains embedded Ansible templates for playbooks and inventory generation.
|
||||
// All templates are defined in playbooks.go and inventory.go.
|
||||
|
||||
Reference in New Issue
Block a user