finalized update feature
This commit is contained in:
@@ -1870,7 +1870,7 @@ def copy_smtp_settings():
|
||||
def update_stack():
|
||||
try:
|
||||
data = request.get_json()
|
||||
if not data or 'stack_id' not in data or 'StackFileContent' not in data:
|
||||
if not data or 'stack_id' not in data:
|
||||
return jsonify({'error': 'Missing required fields'}), 400
|
||||
|
||||
# Get Portainer settings
|
||||
@@ -1924,7 +1924,7 @@ def update_stack():
|
||||
current_app.logger.info(f"Using endpoint ID: {endpoint_id}")
|
||||
current_app.logger.info(f"Using timeout: {stack_timeout} seconds")
|
||||
|
||||
# First, verify the stack exists
|
||||
# First, verify the stack exists and get its current configuration
|
||||
stack_url = f"{portainer_settings['url'].rstrip('/')}/api/stacks/{data['stack_id']}"
|
||||
stack_response = requests.get(
|
||||
stack_url,
|
||||
@@ -1942,15 +1942,83 @@ def update_stack():
|
||||
stack_info = stack_response.json()
|
||||
current_app.logger.info(f"Found existing stack: {stack_info['Name']} (ID: {stack_info['Id']})")
|
||||
|
||||
# Get the current stack file content from Portainer
|
||||
stack_file_url = f"{portainer_settings['url'].rstrip('/')}/api/stacks/{data['stack_id']}/file"
|
||||
stack_file_response = requests.get(
|
||||
stack_file_url,
|
||||
headers={
|
||||
'X-API-Key': portainer_settings['api_key'],
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
params={'endpointId': endpoint_id},
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if not stack_file_response.ok:
|
||||
current_app.logger.error(f"Failed to get stack file: {stack_file_response.text}")
|
||||
return jsonify({'error': f'Failed to get existing stack file: {stack_file_response.text}'}), 500
|
||||
|
||||
stack_file_data = stack_file_response.json()
|
||||
current_stack_file_content = stack_file_data.get('StackFileContent')
|
||||
|
||||
if not current_stack_file_content:
|
||||
current_app.logger.error("No StackFileContent found in existing stack")
|
||||
return jsonify({'error': 'No existing stack file content found'}), 500
|
||||
|
||||
current_app.logger.info("Retrieved existing stack file content")
|
||||
|
||||
# Get existing environment variables from the stack
|
||||
existing_env_vars = stack_file_data.get('Env', [])
|
||||
current_app.logger.info(f"Retrieved {len(existing_env_vars)} existing environment variables")
|
||||
|
||||
# Create a dictionary of existing environment variables for easy lookup
|
||||
existing_env_dict = {env['name']: env['value'] for env in existing_env_vars}
|
||||
current_app.logger.info(f"Existing environment variables: {list(existing_env_dict.keys())}")
|
||||
|
||||
# Get new environment variables from the request
|
||||
new_env_vars = data.get('Env', [])
|
||||
current_app.logger.info(f"New environment variables to update: {[env['name'] for env in new_env_vars]}")
|
||||
|
||||
# Merge existing and new environment variables
|
||||
# Start with existing variables
|
||||
merged_env_vars = existing_env_vars.copy()
|
||||
|
||||
# Update with new variables (this will overwrite existing ones with the same name)
|
||||
for new_env in new_env_vars:
|
||||
# Find if this environment variable already exists
|
||||
existing_index = None
|
||||
for i, existing_env in enumerate(merged_env_vars):
|
||||
if existing_env['name'] == new_env['name']:
|
||||
existing_index = i
|
||||
break
|
||||
|
||||
if existing_index is not None:
|
||||
# Update existing variable
|
||||
merged_env_vars[existing_index]['value'] = new_env['value']
|
||||
current_app.logger.info(f"Updated environment variable: {new_env['name']} = {new_env['value']}")
|
||||
else:
|
||||
# Add new variable
|
||||
merged_env_vars.append(new_env)
|
||||
current_app.logger.info(f"Added new environment variable: {new_env['name']} = {new_env['value']}")
|
||||
|
||||
current_app.logger.info(f"Final merged environment variables: {[env['name'] for env in merged_env_vars]}")
|
||||
|
||||
# Update the stack using Portainer's update API
|
||||
update_url = f"{portainer_settings['url'].rstrip('/')}/api/stacks/{data['stack_id']}/update"
|
||||
update_url = f"{portainer_settings['url'].rstrip('/')}/api/stacks/{data['stack_id']}"
|
||||
current_app.logger.info(f"Making update request to: {update_url}")
|
||||
|
||||
# Prepare the request body for stack update
|
||||
request_body = {
|
||||
'StackFileContent': data['StackFileContent'],
|
||||
'Env': data.get('Env', [])
|
||||
'StackFileContent': current_stack_file_content, # Use existing stack file content
|
||||
'Env': merged_env_vars # Use merged environment variables
|
||||
}
|
||||
|
||||
# If new StackFileContent is provided, use it instead
|
||||
if 'StackFileContent' in data:
|
||||
request_body['StackFileContent'] = data['StackFileContent']
|
||||
current_app.logger.info("Using provided StackFileContent for update")
|
||||
else:
|
||||
current_app.logger.info("Using existing StackFileContent for update")
|
||||
|
||||
# Add endpointId as a query parameter
|
||||
params = {'endpointId': endpoint_id}
|
||||
|
||||
Reference in New Issue
Block a user