checking portainer connection
This commit is contained in:
107
app/routes/admin_api.py
Normal file
107
app/routes/admin_api.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
from flask import request, jsonify, current_app
|
||||||
|
from flask_login import login_required
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from app.utils.gitea_api import GiteaAPI
|
||||||
|
from app.models.gitea_settings import GiteaSettings
|
||||||
|
|
||||||
|
@admin_api.route('/test-git-connection', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def test_git_connection():
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
if not data:
|
||||||
|
return jsonify({'success': False, 'error': 'No data provided'}), 400
|
||||||
|
|
||||||
|
required_fields = ['gitea_url', 'username', 'api_token', 'repo_name']
|
||||||
|
for field in required_fields:
|
||||||
|
if field not in data:
|
||||||
|
return jsonify({'success': False, 'error': f'Missing required field: {field}'}), 400
|
||||||
|
|
||||||
|
# Test the connection using the provided credentials
|
||||||
|
gitea = GiteaAPI(
|
||||||
|
url=data['gitea_url'],
|
||||||
|
token=data['api_token']
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try to get repository information
|
||||||
|
repo = gitea.get_repo(data['username'], data['repo_name'])
|
||||||
|
if not repo:
|
||||||
|
return jsonify({'success': False, 'error': 'Repository not found'}), 404
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'message': 'Successfully connected to Gitea',
|
||||||
|
'data': {
|
||||||
|
'repo_name': repo.name,
|
||||||
|
'description': repo.description,
|
||||||
|
'default_branch': repo.default_branch,
|
||||||
|
'created_at': repo.created_at,
|
||||||
|
'updated_at': repo.updated_at
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||||||
|
|
||||||
|
@admin_api.route('/check-docker-compose', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def check_docker_compose():
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
if not data:
|
||||||
|
return jsonify({'success': False, 'error': 'No data provided'}), 400
|
||||||
|
|
||||||
|
required_fields = ['repository', 'branch']
|
||||||
|
for field in required_fields:
|
||||||
|
if field not in data:
|
||||||
|
return jsonify({'success': False, 'error': f'Missing required field: {field}'}), 400
|
||||||
|
|
||||||
|
# Get Gitea settings from database
|
||||||
|
gitea_settings = GiteaSettings.query.first()
|
||||||
|
if not gitea_settings:
|
||||||
|
return jsonify({'success': False, 'error': 'Gitea settings not configured'}), 400
|
||||||
|
|
||||||
|
# Initialize Gitea API
|
||||||
|
gitea = GiteaAPI(
|
||||||
|
url=gitea_settings.server_url,
|
||||||
|
token=gitea_settings.api_token
|
||||||
|
)
|
||||||
|
|
||||||
|
# Split repository into owner and repo name
|
||||||
|
owner, repo_name = data['repository'].split('/')
|
||||||
|
|
||||||
|
# Get the docker-compose.yml file content
|
||||||
|
try:
|
||||||
|
file_content = gitea.get_file_content(
|
||||||
|
owner=owner,
|
||||||
|
repo=repo_name,
|
||||||
|
filepath='docker-compose.yml',
|
||||||
|
ref=data['branch']
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'success': False, 'error': f'Failed to get docker-compose.yml: {str(e)}'}), 404
|
||||||
|
|
||||||
|
# Save the file content to a temporary location
|
||||||
|
temp_dir = os.path.join(current_app.config['UPLOAD_FOLDER'], 'temp')
|
||||||
|
os.makedirs(temp_dir, exist_ok=True)
|
||||||
|
|
||||||
|
file_path = os.path.join(temp_dir, f'docker-compose-{owner}-{repo_name}.yml')
|
||||||
|
with open(file_path, 'w') as f:
|
||||||
|
f.write(file_content)
|
||||||
|
|
||||||
|
# Get file stats
|
||||||
|
file_stats = os.stat(file_path)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'message': 'Successfully found and downloaded docker-compose.yml',
|
||||||
|
'data': {
|
||||||
|
'file_path': file_path,
|
||||||
|
'size': file_stats.st_size,
|
||||||
|
'last_modified': datetime.fromtimestamp(file_stats.st_mtime).isoformat()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||||||
Binary file not shown.
@@ -1684,8 +1684,12 @@ def init_routes(main_bp):
|
|||||||
|
|
||||||
# Get NGINX settings
|
# Get NGINX settings
|
||||||
nginx_settings = KeyValueSettings.get_value('nginx_settings')
|
nginx_settings = KeyValueSettings.get_value('nginx_settings')
|
||||||
|
# Get Portainer settings
|
||||||
|
portainer_settings = KeyValueSettings.get_value('portainer_settings')
|
||||||
|
|
||||||
return render_template('main/launch_progress.html', nginx_settings=nginx_settings)
|
return render_template('main/launch_progress.html',
|
||||||
|
nginx_settings=nginx_settings,
|
||||||
|
portainer_settings=portainer_settings)
|
||||||
|
|
||||||
@main_bp.route('/api/check-dns', methods=['POST'])
|
@main_bp.route('/api/check-dns', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ function initializeSteps() {
|
|||||||
`;
|
`;
|
||||||
stepsContainer.appendChild(nginxStep);
|
stepsContainer.appendChild(nginxStep);
|
||||||
|
|
||||||
// Add SSL Certificate generation step (now step 3)
|
// Add SSL Certificate generation step
|
||||||
const sslStep = document.createElement('div');
|
const sslStep = document.createElement('div');
|
||||||
sslStep.className = 'step-item';
|
sslStep.className = 'step-item';
|
||||||
sslStep.innerHTML = `
|
sslStep.innerHTML = `
|
||||||
@@ -205,7 +205,7 @@ function initializeSteps() {
|
|||||||
`;
|
`;
|
||||||
stepsContainer.appendChild(sslStep);
|
stepsContainer.appendChild(sslStep);
|
||||||
|
|
||||||
// Add Proxy Host creation step (now step 4)
|
// Add Proxy Host creation step
|
||||||
const proxyStep = document.createElement('div');
|
const proxyStep = document.createElement('div');
|
||||||
proxyStep.className = 'step-item';
|
proxyStep.className = 'step-item';
|
||||||
proxyStep.innerHTML = `
|
proxyStep.innerHTML = `
|
||||||
@@ -216,6 +216,18 @@ function initializeSteps() {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
stepsContainer.appendChild(proxyStep);
|
stepsContainer.appendChild(proxyStep);
|
||||||
|
|
||||||
|
// Add Portainer connection check step (now last)
|
||||||
|
const portainerStep = document.createElement('div');
|
||||||
|
portainerStep.className = 'step-item';
|
||||||
|
portainerStep.innerHTML = `
|
||||||
|
<div class="step-icon"><i class="fab fa-docker"></i></div>
|
||||||
|
<div class="step-content">
|
||||||
|
<h5>Checking Portainer Connection</h5>
|
||||||
|
<p class="step-status">Verifying connection to Portainer...</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
stepsContainer.appendChild(portainerStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startLaunch(data) {
|
async function startLaunch(data) {
|
||||||
@@ -234,7 +246,7 @@ async function startLaunch(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the step to show success
|
// Update the step to show success
|
||||||
const dnsStep = document.querySelector('.step-item');
|
const dnsStep = document.querySelectorAll('.step-item')[0];
|
||||||
dnsStep.classList.remove('active');
|
dnsStep.classList.remove('active');
|
||||||
dnsStep.classList.add('completed');
|
dnsStep.classList.add('completed');
|
||||||
|
|
||||||
@@ -294,7 +306,7 @@ async function startLaunch(data) {
|
|||||||
nginxStep.classList.add('completed');
|
nginxStep.classList.add('completed');
|
||||||
nginxStep.querySelector('.step-status').textContent = 'Successfully connected to NGINX Proxy Manager';
|
nginxStep.querySelector('.step-status').textContent = 'Successfully connected to NGINX Proxy Manager';
|
||||||
|
|
||||||
// Step 3: Generate SSL Certificate (moved up)
|
// Step 3: Generate SSL Certificate
|
||||||
await updateStep(3, 'Generating SSL Certificate', 'Setting up secure HTTPS connection...');
|
await updateStep(3, 'Generating SSL Certificate', 'Setting up secure HTTPS connection...');
|
||||||
const sslResult = await generateSSLCertificate(data.webAddresses);
|
const sslResult = await generateSSLCertificate(data.webAddresses);
|
||||||
|
|
||||||
@@ -302,7 +314,7 @@ async function startLaunch(data) {
|
|||||||
throw new Error(sslResult.error || 'Failed to generate SSL certificate');
|
throw new Error(sslResult.error || 'Failed to generate SSL certificate');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Create Proxy Host (moved down)
|
// Step 4: Create Proxy Host
|
||||||
await updateStep(4, 'Creating Proxy Host', 'Setting up NGINX proxy host configuration...');
|
await updateStep(4, 'Creating Proxy Host', 'Setting up NGINX proxy host configuration...');
|
||||||
const proxyResult = await createProxyHost(data.webAddresses, data.port, sslResult.data.certificate.id);
|
const proxyResult = await createProxyHost(data.webAddresses, data.port, sslResult.data.certificate.id);
|
||||||
|
|
||||||
@@ -310,6 +322,20 @@ async function startLaunch(data) {
|
|||||||
throw new Error(proxyResult.error || 'Failed to create proxy host');
|
throw new Error(proxyResult.error || 'Failed to create proxy host');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 5: Check Portainer connection
|
||||||
|
await updateStep(5, 'Checking Portainer Connection', 'Verifying connection to Portainer...');
|
||||||
|
const portainerResult = await checkPortainerConnection();
|
||||||
|
|
||||||
|
if (!portainerResult.success) {
|
||||||
|
throw new Error(portainerResult.error || 'Failed to connect to Portainer');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the step to show success
|
||||||
|
const portainerStep = document.querySelectorAll('.step-item')[4];
|
||||||
|
portainerStep.classList.remove('active');
|
||||||
|
portainerStep.classList.add('completed');
|
||||||
|
portainerStep.querySelector('.step-status').textContent = 'Successfully connected to Portainer';
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showError(error.message);
|
showError(error.message);
|
||||||
}
|
}
|
||||||
@@ -391,6 +417,66 @@ async function checkNginxConnection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkPortainerConnection() {
|
||||||
|
try {
|
||||||
|
// Get CSRF token from meta tag
|
||||||
|
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||||
|
|
||||||
|
// Get Portainer settings from the template
|
||||||
|
const portainerSettings = {
|
||||||
|
url: '{{ portainer_settings.url if portainer_settings else "" }}',
|
||||||
|
api_key: '{{ portainer_settings.api_key if portainer_settings else "" }}'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Debug log the raw template values
|
||||||
|
console.log('Raw template values:', {
|
||||||
|
url: '{{ portainer_settings.url if portainer_settings else "" }}',
|
||||||
|
api_key: '{{ portainer_settings.api_key if portainer_settings else "" }}'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Debug log the settings (without API key)
|
||||||
|
console.log('Portainer Settings:', {
|
||||||
|
url: portainerSettings.url,
|
||||||
|
hasApiKey: !!portainerSettings.api_key
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if any required field is missing
|
||||||
|
if (!portainerSettings.url || !portainerSettings.api_key) {
|
||||||
|
console.error('Missing Portainer settings:', portainerSettings);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: 'Portainer settings are not configured. Please configure Portainer settings in the admin panel.'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const testResponse = await fetch('/api/admin/test-portainer-connection', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-Token': csrfToken
|
||||||
|
},
|
||||||
|
body: JSON.stringify(portainerSettings)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!testResponse.ok) {
|
||||||
|
const error = await testResponse.json();
|
||||||
|
console.error('Portainer connection error:', error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error.error || 'Failed to connect to Portainer'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking Portainer connection:', error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error.message || 'Error checking Portainer connection'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateStatus(step, message, type = 'info', details = '') {
|
function updateStatus(step, message, type = 'info', details = '') {
|
||||||
const statusElement = document.getElementById(`${step}Status`);
|
const statusElement = document.getElementById(`${step}Status`);
|
||||||
const detailsElement = document.getElementById(`${step}Details`);
|
const detailsElement = document.getElementById(`${step}Details`);
|
||||||
@@ -508,7 +594,7 @@ async function createProxyHost(domains, port, sslCertificateId) {
|
|||||||
forward_host: '192.168.68.124',
|
forward_host: '192.168.68.124',
|
||||||
forward_port: parseInt(port),
|
forward_port: parseInt(port),
|
||||||
ssl_forced: true,
|
ssl_forced: true,
|
||||||
caching_enabled: false,
|
caching_enabled: true,
|
||||||
block_exploits: true,
|
block_exploits: true,
|
||||||
allow_websocket_upgrade: true,
|
allow_websocket_upgrade: true,
|
||||||
http2_support: true,
|
http2_support: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user