Create deployment script
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
parent
ec4abaae1f
commit
bac592b5b0
14
.drone.yml
14
.drone.yml
|
@ -7,9 +7,17 @@ steps:
|
||||||
image: alpine
|
image: alpine
|
||||||
commands:
|
commands:
|
||||||
- apk update
|
- apk update
|
||||||
- apk add envsubst curl
|
- apk add envsubst curl python3
|
||||||
- envsubst < portainer_deploy.template.json > portainer_deploy.json
|
- python3 -m ensurepip
|
||||||
- curl -d @portainer_deploy.json -H "Content-Type:application/json" -H "X-API-Key:ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=" -X POST https://dvportainer.privatedns.org/api/stacks/create/standalone/repository?endpointId=10
|
- pip3 install requests python-dotenv --quiet
|
||||||
|
- python3 deploy/portainer/deploy.py \
|
||||||
|
--PORTAINER https://dvportainer.privatedns.org \
|
||||||
|
--API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q= \
|
||||||
|
--PORTAINER_EP=CICD-runner \
|
||||||
|
--DEPLOY_REPO_URL=${DRONE_REPO_LINK} \
|
||||||
|
--DEPLOY_REF=${DRONE_COMMIT_REF} \
|
||||||
|
--DEPLOY_HOST=dvdemo.privatedns.org \
|
||||||
|
--DEPLOY_NAME=${DRONE_COMMIT_SHA}
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
PORTAINER=https://dvportainer.privatedns.org
|
||||||
|
API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
|
||||||
|
PORTAINER_EP=CICD-runner
|
||||||
|
DEPLOY_REPO_URL=https://dvgit.privatedns.org/lars/DeployTests
|
||||||
|
DEPLOY_REF=refs/heads/main
|
||||||
|
DEPLOY_HOST=dvdemo.privatedns.org
|
||||||
|
DEPLOY_PROJECT=ManualDeployTests
|
||||||
|
DEPLOY_NAME=ManualDeploy
|
|
@ -0,0 +1,100 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from string import Template
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
required_env_vars = {
|
||||||
|
'PORTAINER': 'The portainer instance to deploy to',
|
||||||
|
'API_KEY': 'API-Key to access portainer instance',
|
||||||
|
'PORTAINER_EP': 'Portainer Environment EndPoint to deploy to',
|
||||||
|
'DEPLOY_REPO_URL': 'The repository URL to deploy',
|
||||||
|
'DEPLOY_REF': 'The git ref to deploy',
|
||||||
|
'DEPLOY_HOST': 'The host name under which the deployment will be reachable',
|
||||||
|
'DEPLOY_NAME': 'Custom name to use as the deployment name',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try getting all arguments from (in order): 1 command line, 2 .env file, 3 Environment
|
||||||
|
parser = argparse.ArgumentParser(description='Deploys a docker compose application to portainer.')
|
||||||
|
|
||||||
|
for var, usage in required_env_vars.items():
|
||||||
|
parser.add_argument(f'--{var}', default=os.getenv(var, None), help=usage)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Check if all were parsed
|
||||||
|
not_parsed = []
|
||||||
|
for var, usage in required_env_vars.items():
|
||||||
|
if not getattr(args, var):
|
||||||
|
not_parsed.append(var)
|
||||||
|
else:
|
||||||
|
print(f'--{var}: {getattr(args, var)}')
|
||||||
|
|
||||||
|
if not_parsed:
|
||||||
|
print(f"Error: The following required environment variables were not provided: {', '.join(not_parsed)}")
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
portainer=args.PORTAINER
|
||||||
|
api_key=args.API_KEY
|
||||||
|
portainer_ep=args.PORTAINER_EP
|
||||||
|
|
||||||
|
# Deploy variables to substitute in portainer deploy template
|
||||||
|
deploy_variables = {key: getattr(args, key) for key in
|
||||||
|
['DEPLOY_REPO_URL', 'DEPLOY_HOST', 'DEPLOY_PROJECT', 'DEPLOY_NAME', 'DEPLOY_REF']
|
||||||
|
}
|
||||||
|
|
||||||
|
### Find CICD-runner portainer environment endpointId ###
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-API-Key': api_key,
|
||||||
|
}
|
||||||
|
url = f'{portainer}/api/endpoints'
|
||||||
|
json_endpoints = None
|
||||||
|
try:
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # Raise HTTPError for bad requests
|
||||||
|
json_endpoints = response.json()
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as err:
|
||||||
|
raise Exception(f'Could not retrieve portainer endpoints: {err}')
|
||||||
|
|
||||||
|
endpoint_id = None
|
||||||
|
for endpoint in json_endpoints:
|
||||||
|
if endpoint["Name"] == portainer_ep:
|
||||||
|
endpoint_id = endpoint["Id"]
|
||||||
|
break
|
||||||
|
if endpoint_id is None:
|
||||||
|
raise Exception(f'Portainer endpoint \'{portainer_ep}\' not found.')
|
||||||
|
else:
|
||||||
|
print(f'Found portainer endpoint \'{portainer_ep}\' has id: \'{endpoint_id}\'.')
|
||||||
|
|
||||||
|
|
||||||
|
### Template substitution for the portainer stack deployment ###
|
||||||
|
portainer_deploy_json = None
|
||||||
|
with open('portainer_deploy.template.json', 'r') as file:
|
||||||
|
portainer_template = Template(file.read())
|
||||||
|
|
||||||
|
# Perform variable substitution
|
||||||
|
portainer_deploy_json = portainer_template.substitute(**deploy_variables)
|
||||||
|
|
||||||
|
### Deploy to portainer ###
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-API-Key': api_key,
|
||||||
|
}
|
||||||
|
url = f'{portainer}/api/stacks/create/standalone/repository?endpointId={endpoint_id}'
|
||||||
|
try:
|
||||||
|
response = requests.post(url, headers=headers, json=json.loads(portainer_deploy_json))
|
||||||
|
response.raise_for_status() # Raise HTTPError for bad requests
|
||||||
|
response_data = response.json() # Parse response JSON
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as err:
|
||||||
|
raise Exception(f'Could not deploy portainer stack: {err}')
|
||||||
|
|
||||||
|
print(f'Successfully deployed project')
|
|
@ -13,15 +13,19 @@
|
||||||
"env": [
|
"env": [
|
||||||
{
|
{
|
||||||
"name": "HOST",
|
"name": "HOST",
|
||||||
"value": "dvdemo.privatedns.org"
|
"value": "${DEPLOY_HOST}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "COMPOSE_PROJECT_NAME",
|
||||||
|
"value": "${DEPLOY_NAME}"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fromAppTemplate": false,
|
"fromAppTemplate": false,
|
||||||
"name": "DeployTest_${DRONE_COMMIT}",
|
"name": "${DEPLOY_NAME}",
|
||||||
"repositoryAuthentication": true,
|
"repositoryAuthentication": true,
|
||||||
"repositoryUsername": "cicd",
|
"repositoryUsername": "cicd",
|
||||||
"repositoryPassword": "gJ6@$7ZjWGyV4%i",
|
"repositoryPassword": "gJ6@$$7ZjWGyV4%i",
|
||||||
"repositoryReferenceName": "${DRONE_COMMIT_REF}",
|
"repositoryReferenceName": "${DEPLOY_REF}",
|
||||||
"repositoryURL": "${DRONE_REPO_LINK}",
|
"repositoryURL": "${DEPLOY_REPO_URL}",
|
||||||
"tlsskipVerify": false
|
"tlsskipVerify": false
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@ version: '3.4'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
http-echo:
|
http-echo:
|
||||||
container_name: http-echo
|
|
||||||
image: mendhak/http-https-echo:latest
|
image: mendhak/http-https-echo:latest
|
||||||
expose:
|
expose:
|
||||||
- 8080
|
- 8080
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"additionalFiles": [],
|
|
||||||
"autoUpdate": {
|
|
||||||
"forcePullImage": false,
|
|
||||||
"forceUpdate": false,
|
|
||||||
"interval": "1m30s",
|
|
||||||
"jobID": "15",
|
|
||||||
"webhook": "05de31a2-79fa-4644-9c12-faa67e5c49f0"
|
|
||||||
},
|
|
||||||
"composeFile": "docker-compose.yml",
|
|
||||||
"env": [
|
|
||||||
{
|
|
||||||
"name": "HOST",
|
|
||||||
"value": "dvdemo.privatedns.org"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ECHO_PATH",
|
|
||||||
"value": "deployed_echo"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fromAppTemplate": false,
|
|
||||||
"name": "DeployTest_test1",
|
|
||||||
"repositoryAuthentication": true,
|
|
||||||
"repositoryUsername": "cicd",
|
|
||||||
"repositoryPassword": "gJ6@$7ZjWGyV4%i",
|
|
||||||
"repositoryReferenceName": "refs/heads/main",
|
|
||||||
"repositoryURL": "https://dvgit.privatedns.org/lars/DeployTests",
|
|
||||||
"tlsskipVerify": false
|
|
||||||
}
|
|
Loading…
Reference in New Issue