diff --git a/doc/puppet_classes/puppet_cd_3A_3Aparams.html b/doc/puppet_classes/puppet_cd_3A_3Aparams.html
index 0b36cf0..0df5e7c 100644
--- a/doc/puppet_classes/puppet_cd_3A_3Aparams.html
+++ b/doc/puppet_classes/puppet_cd_3A_3Aparams.html
@@ -1670,17 +1670,7 @@
238
239
240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
+241
# File 'manifests/params.pp', line 88
@@ -1801,9 +1791,6 @@ class puppet_cd::params (
$pt_puppetdb_ssl = "${pt_puppetdb_main}/ssl"
$pt_puppetdb_log = '/var/log/puppetlabs/puppetdb'
$pt_puppetdb_var_dir = '/opt/puppetlabs/server/data/puppetdb'
-## r10k
- $pt_r10k_dir = "${pt_main_dir}/r10k"
- $pt_r10k_webhook_dir = '/etc/r10k-webhook'
# files
## puppet
@@ -1830,14 +1817,7 @@ class puppet_cd::params (
$pt_puppetdb_repl_ini = "${pt_puppetdb_conf_d}/repl.ini"
$pt_puppetdb_repl_erb = 'puppet_cd/puppetdb/repl.ini.erb'
## r10k
- $pt_r10k_file = "${pt_r10k_dir}/r10k.yaml"
- $pt_r10k_erb = 'puppet_cd/r10k/r10k.yaml.erb'
- $pt_r10k_webhook_file = "${pt_r10k_webhook_dir}/webhook_server.py"
- $pt_r10k_webhook_erb = 'puppet_cd/r10k/webhook.py.erb'
- $pt_r10k_req_file = "${pt_r10k_webhook_dir}/requirements.txt"
- $pt_r10k_req_erb = 'puppet_cd/r10k/requirements.txt.erb'
- $pt_r10k_wh_config_file = "${pt_r10k_webhook_dir}/config.json"
- $pt_r10k_wh_config_erb = 'puppet_cd/r10k/r10k_webhook_config.erb'
+ $pt_r10k_hook_file = '/usr/local/bin/webhook'
# service
$pt_server_service = 'puppetserver'
diff --git a/doc/puppet_classes/puppet_cd_3A_3Ar10k_3A_3Awebhook.html b/doc/puppet_classes/puppet_cd_3A_3Ar10k_3A_3Awebhook.html
index d51ba97..a149208 100644
--- a/doc/puppet_classes/puppet_cd_3A_3Ar10k_3A_3Awebhook.html
+++ b/doc/puppet_classes/puppet_cd_3A_3Ar10k_3A_3Awebhook.html
@@ -125,55 +125,7 @@
27
28
29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
+30
|
# File 'manifests/r10k/webhook.pp', line 6
@@ -182,73 +134,25 @@ class puppet_cd::r10k::webhook (
) inherits puppet_cd::params {
if ($pt_pm_fqdn == $fqdn) and ($pt_use_r10k_webhook == true) {
- # install packages
- package { $pt_r10k_webhook_pkg:
- ensure => $pt_pkg_ensure,
- }
-
- # create the webhook dir
- file { $pt_r10k_webhook_dir:
- ensure => directory,
+ # create the webhook binary
+ file { $pt_r10k_hook_file:
+ ensure => file,
owner => 'root',
group => 'root',
mode => '0755',
selrange => s0,
selrole => object_r,
- seltype => etc_t,
- seluser => system_u,
+ seltype => bin_t,
+ seluser => unconfined_u,
+ source => 'puppet:///module/puppet_cd/webhook',
}
- # create the requirements file
- file { $pt_r10k_req_file:
- ensure => file,
- owner => 'puppet',
- group => 'puppet',
- mode => '0644',
- selrange => s0,
- selrole => object_r,
- seltype => etc_t,
- seluser => system_u,
- content => template($pt_r10k_req_erb),
- }
-
- # create the webhook config file
- file { $pt_r10k_wh_config_file:
- ensure => file,
- owner => 'root',
- group => 'root',
- mode => '0644',
- selrange => s0,
- selrole => object_r,
- seltype => etc_t,
- seluser => system_u,
- content => template($pt_r10k_wh_config_erb),
- require => File[$pt_r10k_webhook_dir],
- }
-
-
- # install pip dependencies
- exec { 'pip_install_r10k_webhook':
- command => 'pip3 install --user -r /opt/r10k-webhook/requirements.txt',
- user => 'puppet',
- require => [Package[$pt_r10k_webhook_pkg],File[$pt_r10k_req_file]],
- unless => 'pip3 show fastapi', # Idempotent check
- }
-
- # establish exec systemd reload
- exec { 'systemctl_daemon_reload':
- command => 'systemctl daemon-reload',
- path => ['/bin', '/usr/bin'],
- require => Exec['pip_install_r10k_webhook'],
- refreshonly => true,
- }
-
- # manage service
- service { 'r10k-webhook':
- ensure => 'running',
- enable => true,
- subscribe => File[$pt_r10k_wh_config_file],
- }
+# # manage service
+# service { 'r10k-webhook':
+# ensure => 'running',
+# enable => true,
+# subscribe => File[$pt_r10k_wh_config_file],
+# }
}
}
|
diff --git a/files/webhook b/files/webhook
new file mode 100644
index 0000000..024455b
Binary files /dev/null and b/files/webhook differ
diff --git a/manifests/params.pp b/manifests/params.pp
index de0641c..eca724d 100644
--- a/manifests/params.pp
+++ b/manifests/params.pp
@@ -201,9 +201,6 @@ class puppet_cd::params (
$pt_puppetdb_ssl = "${pt_puppetdb_main}/ssl"
$pt_puppetdb_log = '/var/log/puppetlabs/puppetdb'
$pt_puppetdb_var_dir = '/opt/puppetlabs/server/data/puppetdb'
-## r10k
- $pt_r10k_dir = "${pt_main_dir}/r10k"
- $pt_r10k_webhook_dir = '/etc/r10k-webhook'
# files
## puppet
@@ -230,14 +227,7 @@ class puppet_cd::params (
$pt_puppetdb_repl_ini = "${pt_puppetdb_conf_d}/repl.ini"
$pt_puppetdb_repl_erb = 'puppet_cd/puppetdb/repl.ini.erb'
## r10k
- $pt_r10k_file = "${pt_r10k_dir}/r10k.yaml"
- $pt_r10k_erb = 'puppet_cd/r10k/r10k.yaml.erb'
- $pt_r10k_webhook_file = "${pt_r10k_webhook_dir}/webhook_server.py"
- $pt_r10k_webhook_erb = 'puppet_cd/r10k/webhook.py.erb'
- $pt_r10k_req_file = "${pt_r10k_webhook_dir}/requirements.txt"
- $pt_r10k_req_erb = 'puppet_cd/r10k/requirements.txt.erb'
- $pt_r10k_wh_config_file = "${pt_r10k_webhook_dir}/config.json"
- $pt_r10k_wh_config_erb = 'puppet_cd/r10k/r10k_webhook_config.erb'
+ $pt_r10k_hook_file = '/usr/local/bin/webhook'
# service
$pt_server_service = 'puppetserver'
diff --git a/manifests/r10k/webhook.pp b/manifests/r10k/webhook.pp
index 3a5e9ef..41af8df 100644
--- a/manifests/r10k/webhook.pp
+++ b/manifests/r10k/webhook.pp
@@ -7,72 +7,24 @@ class puppet_cd::r10k::webhook (
) inherits puppet_cd::params {
if ($pt_pm_fqdn == $fqdn) and ($pt_use_r10k_webhook == true) {
- # install packages
- package { $pt_r10k_webhook_pkg:
- ensure => $pt_pkg_ensure,
- }
-
- # create the webhook dir
- file { $pt_r10k_webhook_dir:
- ensure => directory,
+ # create the webhook binary
+ file { $pt_r10k_hook_file:
+ ensure => file,
owner => 'root',
group => 'root',
mode => '0755',
selrange => s0,
selrole => object_r,
- seltype => etc_t,
- seluser => system_u,
+ seltype => bin_t,
+ seluser => unconfined_u,
+ source => 'puppet:///module/puppet_cd/webhook',
}
- # create the requirements file
- file { $pt_r10k_req_file:
- ensure => file,
- owner => 'puppet',
- group => 'puppet',
- mode => '0644',
- selrange => s0,
- selrole => object_r,
- seltype => etc_t,
- seluser => system_u,
- content => template($pt_r10k_req_erb),
- }
-
- # create the webhook config file
- file { $pt_r10k_wh_config_file:
- ensure => file,
- owner => 'root',
- group => 'root',
- mode => '0644',
- selrange => s0,
- selrole => object_r,
- seltype => etc_t,
- seluser => system_u,
- content => template($pt_r10k_wh_config_erb),
- require => File[$pt_r10k_webhook_dir],
- }
-
-
- # install pip dependencies
- exec { 'pip_install_r10k_webhook':
- command => 'pip3 install --user -r /opt/r10k-webhook/requirements.txt',
- user => 'puppet',
- require => [Package[$pt_r10k_webhook_pkg],File[$pt_r10k_req_file]],
- unless => 'pip3 show fastapi', # Idempotent check
- }
-
- # establish exec systemd reload
- exec { 'systemctl_daemon_reload':
- command => 'systemctl daemon-reload',
- path => ['/bin', '/usr/bin'],
- require => Exec['pip_install_r10k_webhook'],
- refreshonly => true,
- }
-
- # manage service
- service { 'r10k-webhook':
- ensure => 'running',
- enable => true,
- subscribe => File[$pt_r10k_wh_config_file],
- }
+# # manage service
+# service { 'r10k-webhook':
+# ensure => 'running',
+# enable => true,
+# subscribe => File[$pt_r10k_wh_config_file],
+# }
}
}
diff --git a/templates/r10k/requirements.txt.erb b/templates/r10k/requirements.txt.erb
deleted file mode 100644
index 4d50e5b..0000000
--- a/templates/r10k/requirements.txt.erb
+++ /dev/null
@@ -1,4 +0,0 @@
-#fastapi==0.115.0
-#uvicorn==0.30.6
-#pydantic==2.8.2
-r10k-webhook
\ No newline at end of file
diff --git a/templates/r10k/webhook.py.erb b/templates/r10k/webhook.py.erb
deleted file mode 100644
index c5f7862..0000000
--- a/templates/r10k/webhook.py.erb
+++ /dev/null
@@ -1,198 +0,0 @@
-#!/usr/bin/env python3
-"""
-Custom r10k Webhook Server for Puppet Control Repo
-"""
-
-from datetime import datetime
-import os
-import subprocess
-import logging
-import hmac
-import hashlib
-
-from fastapi import FastAPI, Request, HTTPException, BackgroundTasks
-from fastapi.responses import JSONResponse
-import uvicorn
-from pydantic import BaseModel
-
-
-# Configure logging
-logging.basicConfig(
- level=logging.INFO,
- format='%(asctime)s - %(levelname)s - %(message)s',
- handlers=[
- logging.FileHandler('/var/log/r10k-webhook.log'),
- logging.StreamHandler()
- ]
-)
-logger = logging.getLogger(__name__)
-
-
-app = FastAPI(title="r10k Webhook Server")
-
-
-class WebhookPayload(BaseModel):
- """Data model for webhook payload"""
- ref: str
- project: dict
- commits: list
-
-
-def run_r10k_deploy() -> bool:
- """Run r10k deploy command"""
- try:
- cmd = [
- '/usr/bin/r10k', 'deploy',
- '-v',
- '-c', '/etc/puppetlabs/r10k/r10k.conf'
- ]
-
- logger.info("Starting r10k deploy...")
- result = subprocess.run(
- cmd,
- capture_output=True,
- text=True,
- check=True
- )
-
- logger.info("r10k deploy successful!")
- logger.debug("r10k stdout: %s", result.stdout)
- if result.stderr:
- logger.warning("r10k stderr: %s", result.stderr)
- return True
-
- except subprocess.CalledProcessError as e:
- logger.error("r10k deploy failed: %s", e)
- logger.error("stdout: %s", e.stdout)
- logger.error("stderr: %s", e.stderr)
- return False
- except FileNotFoundError:
- logger.error("r10k binary not found")
- return False
- except PermissionError:
- logger.error("Permission denied running r10k")
- return False
-
-
-def validate_signature(payload: bytes, signature: str, secret: str) -> bool:
- """Validate webhook signature"""
- if not secret:
- return True
-
- expected = hmac.new(
- secret.encode(),
- payload,
- hashlib.sha256
- ).hexdigest()
-
- if signature.startswith('sha256='):
- return hmac.compare_digest(signature, f'sha256={expected}')
-
- return hmac.compare_digest(signature, expected)
-
-
-@app.post("/webhook")
-async def webhook_handler(
- request: Request,
- background_tasks: BackgroundTasks
-):
- """Handle incoming webhook requests"""
-
- body = await request.body()
- headers = dict(request.headers)
- event_type = headers.get(
- 'x-gitlab-event',
- headers.get('x-github-event', 'unknown')
- )
- signature = headers.get(
- 'x-gitlab-token',
- headers.get('x-hub-signature-256', '')
- )
-
- print(
- f"DEBUG: Received webhook: event_type={event_type}, "
- f"headers={headers}"
- )
- logger.info(
- "Received webhook: event_type=%s, headers=%s",
- event_type,
- headers
- )
-
- webhook_secret = os.getenv('R10K_WEBHOOK_SECRET', '')
- is_valid = validate_signature(body, signature, webhook_secret)
- if webhook_secret and not is_valid:
- logger.warning("Invalid webhook signature")
- raise HTTPException(status_code=403, detail="Invalid signature")
-
- try:
- payload = await request.json()
- ref = payload.get('ref', '')
- branch = ref.split('/')[-1] if '/' in ref else ref
- print(
- f"DEBUG: Parsed payload: ref={ref}, "
- f"branch={branch}"
- )
- logger.info("Parsed payload: ref=%s, branch=%s", ref, branch)
-
- if branch not in ['main', 'master']:
- logger.info("Ignoring non-main branch: %s", branch)
- return JSONResponse({
- "status": "ignored",
- "branch": branch
- })
-
- # Match GitLab event types explicitly
- valid_events = [
- 'push hook', 'merge request hook',
- 'push', 'Push', 'Push Hook'
- ]
- normalized_event = event_type.lower().strip()
- print(f"DEBUG: Normalized event: {normalized_event}")
- logger.info("Normalized event: %s", normalized_event)
- if normalized_event in valid_events:
- logger.info("Triggering r10k for %s on %s", event_type, branch)
- background_tasks.add_task(run_r10k_deploy)
- return JSONResponse({
- "status": "accepted",
- "message": "r10k deploy triggered",
- "timestamp": datetime.utcnow().isoformat(),
- "branch": branch
- })
-
- logger.info("Ignoring event type: %s", event_type)
- return JSONResponse({
- "status": "ignored",
- "event": event_type
- })
-
- except ValueError as e:
- logger.error("Webhook processing error: %s", e)
- raise HTTPException(
- status_code=400,
- detail="Invalid payload"
- ) from e
-
-
-@app.get("/health")
-async def health_check():
- """Health check endpoint"""
- result = subprocess.run(
- ['r10k', '--version'],
- capture_output=True,
- text=True,
- check=True
- )
- return {
- "status": "healthy",
- "r10k_version": result.stdout.strip()
- }
-
-
-if __name__ == "__main__":
- uvicorn.run(
- "webhook_server:app",
- host="0.0.0.0",
- port=8080,
- log_level="info"
- )