Skip to content

Commit 0076007

Browse files
author
lijianguo
committed
feat(helmbroker): add loader
1 parent 76bbe89 commit 0076007

9 files changed

Lines changed: 280 additions & 21 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{{/* Generate helmbroker deployment envs */}}
2+
{{- define "helmbroker.envs" -}}
3+
env:
4+
{{- range $key, $value := .Values.environment }}
5+
- name: {{ $key }}
6+
value: {{ $value | quote }}
7+
{{- end }}
8+
{{- end }}
9+
10+
11+
{{/* Generate helmbroker deployment limits */}}
12+
{{- define "helmbroker.limits" -}}
13+
{{- if or (.Values.limits_cpu) (.Values.limits_memory) }}
14+
resources:
15+
limits:
16+
{{- if (.Values.limits_cpu) }}
17+
cpu: {{.Values.limits_cpu}}
18+
{{- end }}
19+
{{- if (.Values.limits_memory) }}
20+
memory: {{.Values.limits_memory}}
21+
{{- end }}
22+
{{- end }}
23+
{{- end }}
24+
25+
{{/* Generate helmbroker deployment volumeMounts */}}
26+
{{- define "helmbroker.volumeMounts" }}
27+
volumeMounts:
28+
- name: drycc-helmbroker-cm
29+
mountPath: "/etc/helmbroker/config"
30+
readOnly: true
31+
{{- if .Values.persistence.enabled }}
32+
- name: helmbroker-data
33+
mountPath: /etc/helmbroker
34+
{{- end }}
35+
{{- end }}
36+
37+
{{/* Generate helmbroker deployment volumes */}}
38+
{{- define "helmbroker.volumes" }}
39+
volumes:
40+
- name: drycc-helmbroker-cm
41+
configMap:
42+
name: drycc-helmbroker-cm
43+
{{- if .Values.persistence.enabled }}
44+
- name: helmbroker-data
45+
persistentVolumeClaim:
46+
claimName: drycc-helmbroker
47+
{{- end }}
48+
{{- end }}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{{- if .Values.repositories }}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: drycc-helmbroker-cm
6+
labels:
7+
heritage: drycc
8+
annotations:
9+
component.drycc.cc/version: {{ .Values.image_tag }}
10+
data:
11+
repositories:
12+
{{- range .Values.repositories }}
13+
- name: {{ .name }}
14+
url: {{ .url }}
15+
{{- end }}
16+
{{- end }}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: drycc-helmbroker-cm
5+
labels:
6+
heritage: drycc
7+
annotations:
8+
component.drycc.cc/version: {{ .Values.image_tag }}
9+
spec:
10+
replicas: {{ .Values.replicas }}
11+
strategy:
12+
rollingUpdate:
13+
maxSurge: 1
14+
maxUnavailable: 0
15+
type: RollingUpdate
16+
selector:
17+
matchLabels:
18+
app: drycc-helmbroker
19+
template:
20+
metadata:
21+
labels:
22+
app: drycc-helmbroker
23+
spec:
24+
serviceAccount: drycc-helmbroker
25+
containers:
26+
- name: drycc-helmbroker
27+
image: {{.Values.image_registry}}/{{.Values.image_org}}/helmbroker:{{.Values.image_tag}}
28+
imagePullPolicy: {{.Values.image_pull_policy}}
29+
livenessProbe:
30+
httpGet:
31+
path: /healthz
32+
port: 5000
33+
initialDelaySeconds: 30
34+
timeoutSeconds: 10
35+
readinessProbe:
36+
httpGet:
37+
path: /readiness
38+
port: 5000
39+
initialDelaySeconds: 30
40+
timeoutSeconds: 10
41+
periodSeconds: 5
42+
ports:
43+
- containerPort: 8000
44+
name: http
45+
{{- include "helmbroker.limits" . | indent 10 }}
46+
{{- include "helmbroker.envs" . | indent 10 }}
47+
{{- include "helmbroker.volumeMounts" . | indent 10 }}
48+
{{- include "helmbroker.volumes" . | indent 6 }}

charts/helmbroker/values.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
image_org: "drycc"
2+
image_tag: "canary"
3+
image_registry: "docker.io"
4+
image_pull_policy: "Always"
5+
replicas: 1
6+
# limits_cpu: "100m"
7+
# limits_memory: "50Mi"
8+
9+
## config the helm-broker repositories
10+
repositories: {}
11+
#- name: drycc-helm-broker
12+
# url: http://helm-broker.drycc.cc/index-drycc.yaml
13+
14+
persistence:
15+
enabled: false
16+
accessMode: ReadWriteOnce
17+
size: 5Gi
18+
storageClass: ""
19+
volumeName: ""

rootfs/helmbroker/broker.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,35 @@
88

99
from .utils import get_instance_path, get_chart_path, get_plan_path, get_addon_path
1010
from .tasks import provision
11+
from helmbroker.loader import read_addons_file
12+
1113

1214
class HelmServiceBroker(ServiceBroker):
1315

1416
def catalog(self) -> Union[Service, List[Service]]:
17+
services = read_addons_file()
1518
return [Service(
16-
id='server',
17-
name='server',
18-
description='service description',
19-
bindable=True,
20-
plans=[
21-
ServicePlan(
22-
id='server-1:1-1',
23-
name='1-1',
24-
description='plan description',
25-
),
26-
ServicePlan(
27-
id='server-2:2-2',
28-
name='2-2',
29-
description='plan description',
30-
)
31-
],
32-
plan_updateable=True,
33-
)]
19+
**addons
20+
) for _,addons in services.items()]
21+
# return Service(
22+
# id='server',
23+
# name='server',
24+
# description='service description',
25+
# bindable=True,
26+
# plans=[
27+
# ServicePlan(
28+
# id='server-1:1-1',
29+
# name='1-1',
30+
# description='plan description',
31+
# ),
32+
# ServicePlan(
33+
# id='server-2:2-2',
34+
# name='2-2',
35+
# description='plan description',
36+
# )
37+
# ],
38+
# plan_updateable=True,
39+
# )
3440

3541
def provision(self,
3642
instance_id: str,

rootfs/helmbroker/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88
INSTANCES_PATH = os.path.join(HELMBROKER_ROOT, 'instances')
99

1010
class Config:
11+
DEBUG = True
12+
if not os.path.exists(ADDONS_PATH):
13+
os.makedirs(ADDONS_PATH)
1114
with open(CONFIG_PATH, 'r') as f:
1215
repository = yaml.load(f.read())

rootfs/helmbroker/loader.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import os
2+
import shutil
3+
import tarfile
4+
import requests
5+
import yaml
6+
7+
from helmbroker.config import ADDONS_PATH, CONFIG_PATH, Config
8+
9+
10+
def download_file(url, dest):
11+
if not os.path.exists(dest):
12+
os.system(f'mkdir -p {dest}')
13+
filename = url.split('/')[-1]
14+
file = requests.get(url)
15+
with open(f"{dest}/{filename}", 'wb') as f:
16+
f.write(file.content)
17+
if filename.endswith(".yaml") or filename.endswith(".yml"):
18+
return yaml.load(file.content.decode(encoding="utf-8"),
19+
Loader=yaml.Loader)
20+
21+
22+
def read_addons_file():
23+
data = read_file(f'{ADDONS_PATH}/addons.yaml')
24+
addons_info = yaml.load(data, Loader=yaml.Loader)
25+
return addons_info
26+
27+
28+
def read_file(filename):
29+
if not os.path.exists(filename):
30+
return
31+
with open(filename, 'r') as f:
32+
file_content = f.read()
33+
return file_content
34+
35+
36+
def save_file(content, dest, filename):
37+
if not os.path.exists(dest):
38+
os.system(f'mkdir -p {dest}')
39+
with open(f"{dest}/{filename}", 'w') as f:
40+
f.write(content)
41+
42+
43+
def extract_tgz(tgz_file, dest):
44+
if not os.path.exists(tgz_file):
45+
return
46+
if not os.path.exists(dest):
47+
os.system(f'mkdir -p {dest}')
48+
49+
tarobj = tarfile.open(tgz_file, "r:gz")
50+
for tarinfo in tarobj:
51+
tarobj.extract(tarinfo.name, dest)
52+
tarobj.close()
53+
54+
55+
def addons_meta_file():
56+
meta_files = []
57+
# get meta.yaml
58+
for root, dirnames, filenames in os.walk(ADDONS_PATH):
59+
for filename in filenames:
60+
if filename == 'meta.yaml':
61+
meta_files.append(os.path.join(root, filename))
62+
meta_files = [meta_file.split(ADDONS_PATH)[1] for meta_file in meta_files]
63+
addons_meta = []
64+
plans_meta = []
65+
for meta_file in meta_files:
66+
if len(meta_file.split('/')) == 3:
67+
addons_meta.append(meta_file.split('/')[1:])
68+
else:
69+
plans_meta.append(meta_file.split('/')[1:])
70+
addons_dict = {}
71+
for addon_meta in addons_meta:
72+
with open(f'{ADDONS_PATH}/{"/".join(addon_meta)}',
73+
'r') as f:
74+
meta = yaml.load(f.read(), Loader=yaml.Loader)
75+
meta['plans'] = []
76+
addons_dict[meta['name']] = meta
77+
78+
for plan_meta in plans_meta:
79+
with open(f'{ADDONS_PATH}/{"/".join(plan_meta)}', 'r') as f:
80+
addons_mata = yaml.load(f.read(), Loader=yaml.Loader)
81+
addons_dict[f'{"-".join(plan_meta[0].split("-")[0:-1])}']['plans'].append(addons_mata) # noqa
82+
save_file(yaml.dump(addons_dict), ADDONS_PATH, 'addons.yaml')
83+
84+
85+
def load_addons(repository):
86+
if not repository:
87+
return
88+
index_name = repository['url'].split('/')[-1]
89+
local_index_file = f'{ADDONS_PATH}/{index_name}'
90+
# download index.yaml
91+
remote_index = requests.get(repository['url']).content.decode(
92+
encoding="utf-8")
93+
# compare index.yaml, is update
94+
local_index = read_file(local_index_file)
95+
if remote_index == local_index:
96+
return
97+
# delete old repository catalog
98+
if os.path.exists(ADDONS_PATH):
99+
shutil.rmtree(ADDONS_PATH)
100+
# new index
101+
save_file(remote_index, ADDONS_PATH, index_name)
102+
remote_index = yaml.load(remote_index, Loader=yaml.Loader)
103+
# save index.yaml addons
104+
for k, v in remote_index.get('entries', {}).items():
105+
for _ in v:
106+
url = "/".join(repository["url"].split("/")[0:-1])
107+
tgz_name = f'{_["name"]}-{_["version"]}'
108+
addon_tgz_url = f'{url}/{tgz_name}.tgz'
109+
download_file(addon_tgz_url, ADDONS_PATH)
110+
extract_tgz(f'{ADDONS_PATH}/{tgz_name}.tgz',
111+
f'{ADDONS_PATH}/{tgz_name}')
112+
addons_meta_file()
113+
114+
115+
if __name__ == '__main__':
116+
with open(CONFIG_PATH, 'r') as f:
117+
repository = yaml.load(f.read(), Loader=yaml.Loader)
118+
load_addons(repository['repositories'][0])

rootfs/helmbroker/tasks.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import shutil
3-
from .celery import app
43
from .utils import command, get_plan_path, get_chart_path, get_or_create_instance_meta
54
from openbrokerapi.service_broker import *
65

@@ -12,7 +11,7 @@ def provision(iself,
1211
**kwargs) -> ProvisionedServiceSpec:
1312
chart_path = get_chart_path(instance_id)
1413
values_file = os.path.join(get_plan_path(instance_id), "values.yaml")
15-
args = [
14+
args = [
1615
"install",
1716
details.context["instance_name"],
1817
chart_path,

rootfs/requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
pyyaml==5.4.1
1+
PyYAML==5.4.1
22
gunicorn==20.1.0
33
openbrokerapi==4.1.2
4+
requests==2.26.0
5+
celery==5.1.2

0 commit comments

Comments
 (0)