mirror of https://github.com/jumpserver/jumpserver
commit
0b3a7bb020
@ -0,0 +1,31 @@
|
||||
name: Check I18n files CompileMessages
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'dev'
|
||||
paths:
|
||||
- 'apps/i18n/core/**/*.po'
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
jobs:
|
||||
compile-messages-check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and check compilemessages
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
push: false
|
||||
file: Dockerfile
|
||||
target: stage-build
|
||||
tags: jumpserver/core:stage-build
|
@ -0,0 +1,30 @@
|
||||
# Generated by Django 4.1.13 on 2024-08-26 09:05
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0005_myasset'),
|
||||
('accounts', '0003_automation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='changesecretrecord',
|
||||
name='account',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.account'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='changesecretrecord',
|
||||
name='asset',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.asset'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='changesecretrecord',
|
||||
name='execution',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.automationexecution'),
|
||||
),
|
||||
]
|
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.1.13 on 2024-09-13 08:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('assets', '0005_myasset'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='database',
|
||||
name='pg_ssl_mode',
|
||||
field=models.CharField(choices=[
|
||||
('prefer', 'Prefer'),
|
||||
('require', 'Require'),
|
||||
('verify-ca', 'Verify CA'),
|
||||
('verify-full', 'Verify Full')
|
||||
], default='prefer',
|
||||
max_length=16, verbose_name='Postgresql SSL mode'),
|
||||
),
|
||||
]
|
@ -1,2 +1 @@
|
||||
from .k8s import *
|
||||
from .node import *
|
||||
|
@ -1,177 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from urllib.parse import urlencode, urlparse
|
||||
|
||||
from kubernetes import client
|
||||
from kubernetes.client import api_client
|
||||
from kubernetes.client.api import core_v1_api
|
||||
from sshtunnel import SSHTunnelForwarder, BaseSSHTunnelForwarderError
|
||||
|
||||
from common.utils import get_logger
|
||||
from ..const import CloudTypes, Category
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class KubernetesClient:
|
||||
def __init__(self, asset, token):
|
||||
self.url = asset.address
|
||||
self.token = token or ''
|
||||
self.server = self.get_gateway_server(asset)
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
configuration = client.Configuration()
|
||||
scheme = urlparse(self.url).scheme
|
||||
if not self.server:
|
||||
host = self.url
|
||||
else:
|
||||
host = f'{scheme}://127.0.0.1:{self.server.local_bind_port}'
|
||||
configuration.host = host
|
||||
configuration.verify_ssl = False
|
||||
configuration.api_key = {"authorization": "Bearer " + self.token}
|
||||
c = api_client.ApiClient(configuration=configuration)
|
||||
api = core_v1_api.CoreV1Api(c)
|
||||
return api
|
||||
|
||||
def get_namespaces(self):
|
||||
namespaces = []
|
||||
resp = self.api.list_namespace()
|
||||
for ns in resp.items:
|
||||
namespaces.append(ns.metadata.name)
|
||||
return namespaces
|
||||
|
||||
def get_pods(self, namespace):
|
||||
pods = []
|
||||
resp = self.api.list_namespaced_pod(namespace)
|
||||
for pd in resp.items:
|
||||
pods.append(pd.metadata.name)
|
||||
return pods
|
||||
|
||||
def get_containers(self, namespace, pod_name):
|
||||
containers = []
|
||||
resp = self.api.read_namespaced_pod(pod_name, namespace)
|
||||
for container in resp.spec.containers:
|
||||
containers.append(container.name)
|
||||
return containers
|
||||
|
||||
@staticmethod
|
||||
def get_gateway_server(asset):
|
||||
gateway = None
|
||||
if not asset.is_gateway and asset.domain:
|
||||
gateway = asset.domain.select_gateway()
|
||||
|
||||
if not gateway:
|
||||
return
|
||||
|
||||
remote_bind_address = (
|
||||
urlparse(asset.address).hostname,
|
||||
urlparse(asset.address).port or 443
|
||||
)
|
||||
server = SSHTunnelForwarder(
|
||||
(gateway.address, gateway.port),
|
||||
ssh_username=gateway.username,
|
||||
ssh_password=gateway.password,
|
||||
ssh_pkey=gateway.private_key_path,
|
||||
remote_bind_address=remote_bind_address
|
||||
)
|
||||
try:
|
||||
server.start()
|
||||
except BaseSSHTunnelForwarderError:
|
||||
err_msg = 'Gateway is not active: %s' % asset.get('name', '')
|
||||
print('\033[31m %s \033[0m\n' % err_msg)
|
||||
return server
|
||||
|
||||
def run(self, tp, *args):
|
||||
func_name = f'get_{tp}s'
|
||||
data = []
|
||||
if hasattr(self, func_name):
|
||||
try:
|
||||
data = getattr(self, func_name)(*args)
|
||||
except Exception as e:
|
||||
logger.error(f'K8S tree get {tp} error: {e}')
|
||||
|
||||
if self.server:
|
||||
self.server.stop()
|
||||
return data
|
||||
|
||||
|
||||
class KubernetesTree:
|
||||
def __init__(self, asset, secret):
|
||||
self.asset = asset
|
||||
self.secret = secret
|
||||
|
||||
def as_asset_tree_node(self):
|
||||
i = str(self.asset.id)
|
||||
name = str(self.asset)
|
||||
node = self.create_tree_node(
|
||||
i, i, name, 'asset', icon='k8s', is_open=True,
|
||||
)
|
||||
return node
|
||||
|
||||
def as_namespace_node(self, name, tp):
|
||||
i = urlencode({'namespace': name})
|
||||
pid = str(self.asset.id)
|
||||
node = self.create_tree_node(i, pid, name, tp, icon='cloud')
|
||||
return node
|
||||
|
||||
def as_pod_tree_node(self, namespace, name, tp):
|
||||
pid = urlencode({'namespace': namespace})
|
||||
i = urlencode({'namespace': namespace, 'pod': name})
|
||||
node = self.create_tree_node(i, pid, name, tp, icon='cloud')
|
||||
return node
|
||||
|
||||
def as_container_tree_node(self, namespace, pod, name, tp):
|
||||
pid = urlencode({'namespace': namespace, 'pod': pod})
|
||||
i = urlencode({'namespace': namespace, 'pod': pod, 'container': name})
|
||||
node = self.create_tree_node(
|
||||
i, pid, name, tp, icon='cloud', is_container=True
|
||||
)
|
||||
return node
|
||||
|
||||
@staticmethod
|
||||
def create_tree_node(id_, pid, name, identity, icon='', is_container=False, is_open=False):
|
||||
node = {
|
||||
'id': id_,
|
||||
'name': name,
|
||||
'title': name,
|
||||
'pId': pid,
|
||||
'isParent': not is_container,
|
||||
'open': is_open,
|
||||
'iconSkin': icon,
|
||||
'meta': {
|
||||
'type': 'k8s',
|
||||
'data': {
|
||||
'category': Category.CLOUD,
|
||||
'type': CloudTypes.K8S,
|
||||
'identity': identity
|
||||
}
|
||||
}
|
||||
}
|
||||
return node
|
||||
|
||||
def async_tree_node(self, namespace, pod):
|
||||
tree = []
|
||||
k8s_client = KubernetesClient(self.asset, self.secret)
|
||||
if pod:
|
||||
tp = 'container'
|
||||
containers = k8s_client.run(
|
||||
tp, namespace, pod
|
||||
)
|
||||
for container in containers:
|
||||
container_node = self.as_container_tree_node(
|
||||
namespace, pod, container, tp
|
||||
)
|
||||
tree.append(container_node)
|
||||
elif namespace:
|
||||
tp = 'pod'
|
||||
pods = k8s_client.run(tp, namespace)
|
||||
for pod in pods:
|
||||
pod_node = self.as_pod_tree_node(namespace, pod, tp)
|
||||
tree.append(pod_node)
|
||||
else:
|
||||
tp = 'namespace'
|
||||
namespaces = k8s_client.run(tp)
|
||||
for namespace in namespaces:
|
||||
namespace_node = self.as_namespace_node(namespace, tp)
|
||||
tree.append(namespace_node)
|
||||
return tree
|
@ -1,5 +1,6 @@
|
||||
|
||||
CRONTAB_AT_AM_TWO = '0 2 * * *'
|
||||
CRONTAB_AT_AM_THREE = '0 3 * * *'
|
||||
CRONTAB_AT_AM_TEN = '0 10 * * *'
|
||||
CRONTAB_AT_PM_TWO = '0 14 * * *'
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue