Skip to content

Commit 49f96f4

Browse files
committed
Merge branch 'release/2.1.0' of github.com:MetaCell/cloud-harness into release/2.1.0
2 parents b10fc43 + 469d77c commit 49f96f4

13 files changed

Lines changed: 8683 additions & 421 deletions

File tree

.github/workflows/trivy-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030

3131
- name: Build an image from Dockerfile
3232
run: |
33-
docker build -t cloudharness-base:${{ github.sha }} . -f ./infrastructure/base-images/cloudharness-base/Dockerfile
33+
DOCKER_BUILDKIT=1 docker build -t cloudharness-base:${{ github.sha }} . -f ./infrastructure/base-images/cloudharness-base/Dockerfile
3434
3535
- name: Run Trivy vulnerability scanner
3636
uses: aquasecurity/trivy-action@2a2157eb22c08c9a1fac99263430307b8d1bc7a2

deployment-configuration/helm/templates/auto-database.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ kind: Deployment
3131
metadata:
3232
name: {{ .app.harness.database.name | quote }}
3333
namespace: {{ .root.Values.namespace }}
34+
labels:
35+
usesvolume: {{ .app.harness.database.name }}
3436
spec:
3537
replicas: 1
3638
selector:
@@ -41,7 +43,18 @@ spec:
4143
labels:
4244
app: {{ .app.harness.database.name | quote }}
4345
service: db
46+
usesvolume: {{ .app.harness.database.name }}
4447
spec:
48+
affinity:
49+
podAffinity:
50+
requiredDuringSchedulingIgnoredDuringExecution:
51+
- labelSelector:
52+
matchExpressions:
53+
- key: usesvolume
54+
operator: In
55+
values:
56+
- {{ .app.harness.database.name }}
57+
topologyKey: "kubernetes.io/hostname"
4558
containers:
4659
- name: {{ .app.harness.database.name | quote }}
4760
imagePullPolicy: IfNotPresent
@@ -66,10 +79,19 @@ spec:
6679
mountPath: {{ (printf "%s/%s/%s" .root.Values.backup.dir .app.harness.database.type .app.harness.database.name) | quote }}
6780
readOnly: true
6881
{{- end }}
82+
{{- if eq .app.harness.database.type "postgres" }}
83+
- mountPath: /dev/shm
84+
name: dshm
85+
{{- end }}
6986
volumes:
7087
- name: {{ .app.harness.database.name | quote }}
7188
persistentVolumeClaim:
7289
claimName: {{ .app.harness.database.name | quote }}
90+
{{- if eq .app.harness.database.type "postgres" }}
91+
- emptyDir:
92+
medium: Memory
93+
name: dshm
94+
{{- end }}
7395
{{- if .root.Values.backup.active }}
7496
- name: "db-backups"
7597
persistentVolumeClaim:

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Migration(migrations.Migration):
2828
name='Member',
2929
fields=[
3030
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31-
('kc_id', models.CharField(max_length=100)),
31+
('kc_id', models.CharField(max_length=100, db_index=True)),
3232
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
3333
],
3434
),

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def __str__(self):
1313

1414
class Member(models.Model):
1515
user = models.OneToOneField(User, on_delete=models.CASCADE)
16-
kc_id = models.CharField(max_length = 100)
16+
kc_id = models.CharField(max_length = 100, db_index=True)
1717

1818
def __str__(self):
1919
return f"{self.user.first_name} {self.user.last_name}"

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/auth.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ class AuthorizationLevel(Enum):
2121

2222
# create the auth client
2323
if os.path.isfile(ALLVALUES_PATH):
24+
try:
2425
# CH values exists so running with a valid config
25-
auth_client = AuthClient(os.getenv("ACCOUNTS_ADMIN_USERNAME", None), os.getenv("ACCOUNTS_ADMIN_PASSWORD", None))
26+
auth_client = AuthClient(os.getenv("ACCOUNTS_ADMIN_USERNAME", None), os.getenv("ACCOUNTS_ADMIN_PASSWORD", None))
27+
except:
28+
log.exception("Failed to initialize auth client")
29+
auth_client = None
2630
else:
2731
auth_client = None
2832

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/user.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
from cloudharness_django.models import Team, Member
44
from cloudharness_django.services.auth import AuthorizationLevel
55

6+
def get_user_by_kc_id(kc_id) -> User:
7+
try:
8+
return Member.objects.get(kc_id=kc_id).user
9+
except Member.DoesNotExist:
10+
return None
11+
612
class UserService:
713
def __init__(self, auth_service):
814
self.auth_service = auth_service
@@ -28,6 +34,7 @@ def _map_kc_user(self, user, kc_user=None, is_superuser=False, delete=False):
2834
user.username = kc_user.get("username", kc_user["email"])
2935
user.first_name = kc_user.get("firstName", "")
3036
user.last_name = kc_user.get("lastName", "")
37+
user.email = kc_user.get("email", "")
3138

3239
user.is_active = kc_user.get("enabled", delete)
3340
return user
@@ -98,7 +105,7 @@ def sync_kc_user(self, kc_user, is_superuser=False, delete=False):
98105

99106
def sync_kc_user_groups(self, kc_user):
100107
# Sync the user usergroups and memberships
101-
user = User.objects.get(email=kc_user["email"])
108+
user = User.objects.get(username=kc_user["email"])
102109
user_groups = []
103110
for kc_group in kc_user["userGroups"]:
104111
user_groups += [Group.objects.get(name=kc_group["name"])]

libraries/cloudharness-common/cloudharness/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ def init(appname: str):
4646
if not appname:
4747
raise NotCorrectlyInitialized
4848
try:
49-
from cloudharness import sentry
50-
sentry.init(appname)
49+
from cloudharness import sentry, applications
50+
if applications.get_current_configuration().is_sentry_enabled():
51+
sentry.init(appname)
5152
except Exception as e:
5253
log.warning(f'Error enabling Sentry for {appname}', exc_info=True)
5354

libraries/cloudharness-common/cloudharness/auth/quota.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from cloudharness import log
66

77
# quota tree node to hold the tree quota attributes
8+
9+
810
class QuotaNode:
911
def __init__(self, name, attrs):
1012
self.attrs = attrs
@@ -27,14 +29,20 @@ def _filter_quota_attrs(attrs, valid_keys_map):
2729
return valid_attrs
2830

2931

32+
def get_group_quotas(group, application_config: ApplicationConfig):
33+
base_quotas = application_config.get("harness", {}).get("quotas", {})
34+
valid_keys_map = {key for key in base_quotas}
35+
return _compute_quotas_from_tree(_construct_quota_tree([group], valid_keys_map))
36+
37+
3038
def _construct_quota_tree(groups, valid_keys_map) -> QuotaNode:
3139
root = QuotaNode("root", {})
3240
for group in groups:
3341
r = root
3442
paths = group["path"].split("/")[1:]
3543
# loop through all segements except the last segment
3644
# the last segment is the one we want to add the attributes to
37-
for segment in paths[0 : len(paths) - 1]:
45+
for segment in paths[0: len(paths) - 1]:
3846
for child in r.children:
3947
if child.name == segment:
4048
r = child
@@ -56,13 +64,13 @@ def _construct_quota_tree(groups, valid_keys_map) -> QuotaNode:
5664
def _compute_quotas_from_tree(node: QuotaNode):
5765
"""Recursively traverse the tree and find the quota per level
5866
the lower leafs overrule parent leafs values
59-
67+
6068
Args:
6169
node (QuotaNode): the quota tree of QuotaNodes of the user for the given application
62-
70+
6371
Returns:
6472
dict: key/value pairs of the quotas
65-
73+
6674
Example:
6775
{'quota-ws-maxcpu': 1000, 'quota-ws-open': 10, 'quota-ws-max': 8}
6876
@@ -96,24 +104,23 @@ def _compute_quotas_from_tree(node: QuotaNode):
96104
return node.attrs
97105

98106

99-
def get_user_quotas(application_config: ApplicationConfig =None, user_id: str=None) -> dict:
107+
def get_user_quotas(application_config: ApplicationConfig = None, user_id: str = None) -> dict:
100108
"""Get the user quota from Keycloak and application
101-
109+
102110
Args:
103111
application_config (ApplicationConfig): the application config to use for getting the quotas
104112
user_id (str): the Keycloak user id or username to get the quotas for
105-
113+
106114
Returns:
107115
dict: key/value pairs of the user quota
108-
116+
109117
Example:
110118
{'quota-ws-maxcpu': 1000, 'quota-ws-open': 10, 'quota-ws-max': 8}
111119
"""
112120
if not application_config:
113121
application_config = get_current_configuration()
114122

115-
116-
base_quotas = application_config.get("harness",{}).get("quotas", {})
123+
base_quotas = application_config.get("harness", {}).get("quotas", {})
117124
try:
118125
auth_client = AuthClient()
119126
if not user_id:
@@ -123,11 +130,8 @@ def get_user_quotas(application_config: ApplicationConfig =None, user_id: str=No
123130
log.warning("Quotas not available: error retrieving user: %s", user_id)
124131
return base_quotas
125132

126-
valid_keys_map = []
127-
128-
for key in base_quotas:
129-
valid_keys_map.append(key)
130-
133+
valid_keys_map = {key for key in base_quotas}
134+
131135
group_quotas = _compute_quotas_from_tree(
132136
_construct_quota_tree(
133137
user["userGroups"],

libraries/cloudharness-common/cloudharness/utils/env.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .. import log
66

77
from .config import CloudharnessConfig as conf
8+
from ..applications import get_configuration
89

910
TEST = 'TEST'
1011
PROD = 'PROD'
@@ -105,36 +106,35 @@ def get_sub_variable(*vars):
105106

106107

107108
def get_service_public_address(app_name):
108-
return ".".join([get_sub_variable('CH', app_name.upper(), 'SUBDOMAIN'), get_public_domain()])
109+
return get_configuration(app_name).get_public_address()
109110

110111

111112
def get_public_domain():
112113
return get_variable('CH_DOMAIN')
113114

114115

115116
def get_cloudharness_workflows_service_url():
116-
return get_service_public_address('WORKFLOWS')
117+
return get_service_public_address('workflows')
117118

118119
def get_cloudharness_sentry_service_url():
119-
return 'https://' + get_service_public_address('sentry')
120+
return get_configuration('sentry').get_public_address()
120121

121122
def get_sentry_service_cluster_address():
122-
sentry_app = conf.get_application_by_filter(name='sentry')[0]
123-
return f'http://{sentry_app.name}:{sentry_app.port}'
123+
return get_configuration('sentry').get_service_address()
124124

125125
def get_cloudharness_common_service_url():
126-
return 'https://' + get_service_public_address('common')
126+
return get_configuration('common').get_public_address()
127127

128128
def get_common_service_cluster_address():
129-
common_app = conf.get_application_by_filter(name='common')[0]
130-
return f'http://{common_app.name}:{common_app.port}'
129+
common_app = get_configuration('common')
130+
return common_app.get_service_address()
131131

132132
def get_auth_service_cluster_address():
133-
return get_service_cluster_address('ACCOUNTS')
133+
return get_configuration('accounts').get_service_address()
134134

135135

136136
def get_auth_service_url():
137-
return get_service_public_address('ACCOUNTS')
137+
return get_configuration('accounts').get_public_address()
138138

139139

140140
def get_auth_realm():

libraries/models/cloudharness_model/util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ def deserialize_model(data, klass):
113113
instance = klass()
114114
except:
115115
raise
116-
instance._raw_dict = data
116+
if isinstance(data, dict):
117+
instance._raw_dict = data
117118

118119
if not hasattr(instance, "openapi_types") or isinstance(data, klass):
119120
return data

0 commit comments

Comments
 (0)