Using Portainer API to update images
This commit is contained in:
94
main.py
94
main.py
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@@ -10,6 +11,71 @@ BASH_COMPANION_SCRIPT = os.getcwd() + '/docker_updater.sh'
|
|||||||
REPO_UPDATER_SCRIPT = os.getcwd() + '/update_repos.sh'
|
REPO_UPDATER_SCRIPT = os.getcwd() + '/update_repos.sh'
|
||||||
|
|
||||||
|
|
||||||
|
class PortainerClient:
|
||||||
|
|
||||||
|
def __init__(self, portainer_url, access_token):
|
||||||
|
self.portainer_url = portainer_url
|
||||||
|
self.access_token = access_token
|
||||||
|
|
||||||
|
self.api_url = f"{self.portainer_url}/api"
|
||||||
|
|
||||||
|
def _get_headers(self):
|
||||||
|
return {
|
||||||
|
"accept": "application/json",
|
||||||
|
"X-API-Key": self.access_token
|
||||||
|
}
|
||||||
|
|
||||||
|
def list_stacks(self):
|
||||||
|
response = requests.get(f"{self.api_url}/stacks", headers=self._get_headers())
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_stack(self, stack_id):
|
||||||
|
response = requests.get(f"{self.api_url}/stacks/{stack_id}", headers=self._get_headers())
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_stack_file(self, stack_id):
|
||||||
|
response = requests.get(f"{self.api_url}/stacks/{stack_id}/file", headers=self._get_headers())
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def upgrade_stack(self, stack):
|
||||||
|
file_response = self.get_stack_file(stack['Id'])
|
||||||
|
payload = {
|
||||||
|
"pullImage": True,
|
||||||
|
"prune": True,
|
||||||
|
"StackFileContent": file_response["StackFileContent"],
|
||||||
|
"Env": stack["Env"]
|
||||||
|
}
|
||||||
|
response = requests.put(
|
||||||
|
f"{self.api_url}/stacks/{stack['Id']}?endpointId={stack['EndpointId']}",
|
||||||
|
headers=self._get_headers(),
|
||||||
|
json=payload
|
||||||
|
)
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def list_stack_containers(self, endpoint, stack_name):
|
||||||
|
filters = '{"label":["com.docker.compose.project=' + stack_name + '"]}'
|
||||||
|
response = requests.get(
|
||||||
|
f"{self.api_url}/endpoints/{endpoint}/docker/containers/json?all=1&filters={filters}",
|
||||||
|
headers=self._get_headers()
|
||||||
|
)
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def update_image(self, endpoint, image):
|
||||||
|
response = requests.post(
|
||||||
|
f"{self.api_url}/endpoints/{endpoint}/docker/images/create?fromImage={image}",
|
||||||
|
headers=self._get_headers()
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
status = json.loads(response.text.strip().split('\r\n')[-1])['status']
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return f"Downloaded newer image for {image}" in status
|
||||||
|
|
||||||
|
|
||||||
def update_repositories():
|
def update_repositories():
|
||||||
for repo_path in config.git_repositories:
|
for repo_path in config.git_repositories:
|
||||||
ret = os.system(f"{REPO_UPDATER_SCRIPT} {repo_path}")
|
ret = os.system(f"{REPO_UPDATER_SCRIPT} {repo_path}")
|
||||||
@@ -17,7 +83,7 @@ def update_repositories():
|
|||||||
exit(ret)
|
exit(ret)
|
||||||
|
|
||||||
|
|
||||||
def update_stack(stack):
|
def update_local_stack(stack):
|
||||||
project_name = stack['Name']
|
project_name = stack['Name']
|
||||||
|
|
||||||
print(f"Updating stack: {project_name}")
|
print(f"Updating stack: {project_name}")
|
||||||
@@ -33,17 +99,23 @@ def update_stack(stack):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
update_repositories()
|
update_repositories()
|
||||||
|
|
||||||
headers = {
|
client = PortainerClient(portainer_url=config.portainer_url, access_token=config.access_token)
|
||||||
"accept": "application/json",
|
|
||||||
"X-API-Key": config.access_token
|
|
||||||
}
|
|
||||||
|
|
||||||
api_url = f"{config.portainer_url}/api/stacks"
|
for stack in client.list_stacks():
|
||||||
response = requests.get(api_url, headers=headers)
|
endpoint = stack['EndpointId']
|
||||||
stack_list = response.json()
|
stack_name = stack['Name']
|
||||||
|
if stack['Status'] == 1:
|
||||||
|
containers = client.list_stack_containers(endpoint, stack_name)
|
||||||
|
|
||||||
for s in stack_list:
|
an_image_was_updated = False
|
||||||
if s['Status'] == 1:
|
for c in containers:
|
||||||
update_stack(s)
|
this_image_was_updated = client.update_image(endpoint, c['Image'])
|
||||||
|
an_image_was_updated = an_image_was_updated or this_image_was_updated
|
||||||
|
|
||||||
|
if an_image_was_updated:
|
||||||
|
if endpoint == 2 and stack_name in ('portainer', 'traefik'):
|
||||||
|
update_local_stack(stack)
|
||||||
|
else:
|
||||||
|
client.upgrade_stack(stack)
|
||||||
|
|
||||||
os.system('docker image prune -fa')
|
os.system('docker image prune -fa')
|
||||||
|
|||||||
Reference in New Issue
Block a user