- Adds the k8s.cluster and k8s.odoo.instance models - Successful connection test (ignoring SSL self-signed cert error) - Successfully pulls OdooInstance information from the cluster Further work roadmap: - Fix the SSL issue (cluster-side, most likely) - Get rid of the text fields containing straight JSON and convert to appropriately typed Odoo fields (on read). - Allow updating OdooInstance fields and writing patches back to the cluster. Failed patch should result in a failed write and reverting back to actual cluster status.
132 lines
4.4 KiB
Python
132 lines
4.4 KiB
Python
import logging
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class K8sSyncInstancesWizard(models.TransientModel):
|
|
_name = 'k8s.sync.instances.wizard'
|
|
_description = 'Sync Odoo Instances from Kubernetes'
|
|
|
|
cluster_ids = fields.Many2many(
|
|
'k8s.cluster',
|
|
string='Clusters to Sync',
|
|
default=lambda self: self._default_cluster_ids()
|
|
)
|
|
|
|
sync_all = fields.Boolean(
|
|
string='Sync All Active Clusters',
|
|
default=True,
|
|
help='If checked, will sync all active clusters regardless of selection above'
|
|
)
|
|
|
|
sync_result = fields.Text(
|
|
string='Sync Result',
|
|
readonly=True
|
|
)
|
|
|
|
state = fields.Selection([
|
|
('draft', 'Ready to Sync'),
|
|
('syncing', 'Syncing...'),
|
|
('done', 'Sync Complete'),
|
|
], default='draft')
|
|
|
|
@api.model
|
|
def _default_cluster_ids(self):
|
|
"""Default to active clusters"""
|
|
active_ids = self.env.context.get('active_ids', [])
|
|
if active_ids and self.env.context.get('active_model') == 'k8s.cluster':
|
|
return [(6, 0, active_ids)]
|
|
else:
|
|
# Return all active clusters
|
|
clusters = self.env['k8s.cluster'].search([('active', '=', True)])
|
|
return [(6, 0, clusters.ids)]
|
|
|
|
def action_sync_instances(self):
|
|
"""Sync instances from selected clusters"""
|
|
self.ensure_one()
|
|
|
|
self.state = 'syncing'
|
|
|
|
# Determine which clusters to sync
|
|
if self.sync_all:
|
|
clusters = self.env['k8s.cluster'].search([('active', '=', True)])
|
|
else:
|
|
clusters = self.cluster_ids.filtered('active')
|
|
|
|
if not clusters:
|
|
raise UserError(_('No active clusters selected for synchronization'))
|
|
|
|
results = []
|
|
total_synced = 0
|
|
errors = []
|
|
|
|
for cluster in clusters:
|
|
try:
|
|
_logger.info(f"Syncing instances from cluster: {cluster.name}")
|
|
|
|
# Count instances before sync
|
|
before_count = len(cluster.instance_ids)
|
|
|
|
# Perform sync
|
|
result = cluster.sync_odoo_instances()
|
|
|
|
# Count instances after sync
|
|
after_count = len(cluster.instance_ids)
|
|
synced_count = after_count # This is the total count, not delta
|
|
|
|
results.append(f"✓ {cluster.name}: {synced_count} instances")
|
|
total_synced += synced_count
|
|
|
|
except Exception as e:
|
|
error_msg = f"✗ {cluster.name}: {str(e)}"
|
|
results.append(error_msg)
|
|
errors.append(error_msg)
|
|
_logger.error(f"Sync failed for cluster {cluster.name}: {e}")
|
|
|
|
# Prepare result message
|
|
if errors:
|
|
self.sync_result = f"Sync completed with errors:\n\n" + "\n".join(results)
|
|
if len(errors) == len(clusters):
|
|
self.sync_result += f"\n\n⚠️ All clusters failed to sync!"
|
|
else:
|
|
self.sync_result += f"\n\n✓ Total instances synced: {total_synced}"
|
|
else:
|
|
self.sync_result = f"✓ Sync completed successfully!\n\n" + "\n".join(results)
|
|
self.sync_result += f"\n\n✓ Total instances synced: {total_synced}"
|
|
|
|
self.state = 'done'
|
|
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'k8s.sync.instances.wizard',
|
|
'res_id': self.id,
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
'context': self.env.context,
|
|
}
|
|
|
|
def action_close(self):
|
|
"""Close the wizard"""
|
|
return {'type': 'ir.actions.act_window_close'}
|
|
|
|
def action_view_instances(self):
|
|
"""View the synced instances"""
|
|
self.ensure_one()
|
|
|
|
if self.sync_all:
|
|
clusters = self.env['k8s.cluster'].search([('active', '=', True)])
|
|
else:
|
|
clusters = self.cluster_ids.filtered('active')
|
|
|
|
domain = [('cluster_id', 'in', clusters.ids)]
|
|
|
|
return {
|
|
'name': _('Synced Odoo Instances'),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'k8s.odoo.instance',
|
|
'view_mode': 'list,form',
|
|
'domain': domain,
|
|
'context': {'search_default_group_cluster': 1},
|
|
}
|