Compare commits

..

173 commits

Author SHA1 Message Date
3a7706fcf7
Fix redis hostname 2025-02-18 10:14:36 +01:00
d5bad300ba
Fix path 2025-02-18 09:59:38 +01:00
f97d835cbf
Fix path 2025-02-18 09:58:12 +01:00
f52102c642 Merge pull request 'Fix path.segments' (#2) from fix_appset into main
Reviewed-on: #2
Reviewed-by: Micke <kano@sunet.se>
2025-02-18 08:23:48 +00:00
d55157ab68
Fix path.segments 2025-02-18 09:22:35 +01:00
3998b7417a Merge pull request 'testing just using an emptyDir for rendered config (+more)' (#1) from richir-more-labb into main
Reviewed-on: #1
Reviewed-by: lasse <lasse@sunet.se>
2025-02-18 08:11:37 +00:00
1d60bac661
Remove old application 2025-02-18 09:04:04 +01:00
a260fed464
Remove obsolete parameters 2025-02-18 08:54:03 +01:00
75153298db
Remove namePrefix 2025-02-18 08:52:05 +01:00
f01ec30d64
Use kustomize configMapGenerator to generate configmaps from files 2025-02-17 10:37:34 +01:00
311cadd280
testing just using an emptyDir for rendered config 2025-02-14 13:41:51 +01:00
e0f94b308e
remove gss from nc-upgrade script 2025-02-11 11:06:21 +01:00
93ce560985
new tag 30.0.5.2-2 for customer image 2025-02-11 11:04:50 +01:00
02a7ac8d5c
Only run backup at night 2025-02-07 16:11:12 +01:00
c31722a50e
Use posix shell 2025-02-07 16:07:19 +01:00
d80e9a65b6
Missing comma 2025-02-07 16:03:15 +01:00
c9ad7d7bab
Add liveness to overlay 2025-02-07 15:54:14 +01:00
0a43f3965e
Move stuff around 2025-02-07 15:50:53 +01:00
3e43c4dfb8
don't use same name 2025-02-07 15:46:47 +01:00
9de204737a
Try livenessprobe 2025-02-07 15:44:49 +01:00
030de7dd64
Try with --daemon in two containers 2025-02-07 15:33:39 +01:00
a1e5cce33e
Make mount point env var 2025-02-07 15:27:18 +01:00
fb2e06cc64
Quiet output and run later and only once per day 2025-02-07 15:18:25 +01:00
fa413ff7ee
Add back security context 2025-02-07 15:16:18 +01:00
3622887a3e
Single container 2025-02-07 15:11:43 +01:00
e22ad6faf9
Try one thing at a time 2025-02-07 14:58:49 +01:00
330e9c22d3
umount after job finishes 2025-02-07 14:58:10 +01:00
3d8a5443e9
set hostname 2025-02-07 14:29:48 +01:00
d4839fe725
Try every five minutes 2025-02-07 14:26:06 +01:00
7b196bb081
Maybe now? 2025-02-07 14:17:51 +01:00
d4b6326c54
Debug 2025-02-07 14:13:49 +01:00
9af09cc676
Debug 2025-02-07 14:06:12 +01:00
5f456ba249
Debug 2025-02-07 14:05:31 +01:00
f4ce5010eb
Update options 2025-02-07 13:53:10 +01:00
238a4098f5
Add more options 2025-02-07 13:41:03 +01:00
0b22d32221
Fix option 2025-02-07 13:34:07 +01:00
a76d5f1292
Run even sooner 2025-02-07 13:31:59 +01:00
5cb51541e0
Run sooner 2025-02-07 13:23:27 +01:00
acf1971976
One more nesting level 2025-02-07 13:21:37 +01:00
05e94f10f0
Add cronjob 2025-02-07 13:15:20 +01:00
d054334edd
Moar debug :P 2025-02-06 09:45:45 +01:00
a82ca5eb11
Better debug 2025-02-06 09:19:22 +01:00
7fc4893396
Debug 2025-02-06 09:16:20 +01:00
9ef35ee859
Set env 2025-02-06 09:10:49 +01:00
b99be7ecc3
adding richir to proxysql 2025-02-04 13:52:26 +01:00
814bf644a9
Try the same as in vr 2025-01-27 16:43:15 +01:00
368a6021fe try again 2025-01-24 18:05:48 +01:00
790480f443 try again 2025-01-24 18:02:27 +01:00
1ed7aec45f try again 2025-01-24 17:51:34 +01:00
fc0a70edf7 try again 2025-01-24 17:47:43 +01:00
558c0fc882 try again 2025-01-24 17:44:13 +01:00
b5f529ffbd try again 2025-01-24 17:40:16 +01:00
3a2f65a6eb try again 2025-01-24 17:27:49 +01:00
edd32217d3 try again 2025-01-24 17:22:54 +01:00
876b07bd0a Put config in normal filesystem 2025-01-24 17:17:09 +01:00
675dc269c3 seems only way to make readble: [200~https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/volume/~ 2025-01-24 17:03:42 +01:00
236a4bcc87 Fix syntax error 2025-01-24 16:50:13 +01:00
520f8f0861 Allow occ to fail 2025-01-24 16:46:02 +01:00
98a2939475 Remove even more stuff 2025-01-24 16:35:47 +01:00
0a6f1bd02a try this way 2025-01-24 16:33:19 +01:00
48e8fdd512 try without init-container and pvc 2025-01-24 16:20:40 +01:00
618452c1d3 Upgrade nc to 30.0.5.2-1 2025-01-24 13:56:28 +01:00
e5ccfe8ce0
Downgrade mfazones 2025-01-16 09:22:06 +01:00
87c38bb9f3
Upgrade to 29.0.10.3-1 in test for vinnova and nordunet 2024-12-10 11:10:30 +01:00
31169707e7
Allow rise to log in on extern 2024-12-09 11:57:46 +01:00
b20951f12b
Rename 2024-12-04 11:42:37 +01:00
fcafe5502c
Add cert manager to nextcloud 2024-12-04 11:40:06 +01:00
427be9456b
Add cert-manager 2024-12-04 11:22:14 +01:00
8a294a768e
Fix idp url 2024-12-03 17:20:23 +01:00
b0449a0e25
Add dual ingress 2024-12-03 15:24:42 +01:00
6f66eda86d
Kustomize deployment for portal 2024-12-02 18:14:53 +01:00
7686d8f4c5
New alias 2024-12-02 15:20:40 +01:00
b8d95b6104
Remove alias 2024-12-02 15:19:14 +01:00
b2f5515024
Remove alias 2024-12-02 15:12:26 +01:00
e20aaee976
Add portal for prod 2024-12-02 12:47:33 +01:00
fbb960b64b
Add cert-manager for drive-prod 2024-12-02 09:31:42 +01:00
6d1c4f6562
Add more aliases to ingress 2024-11-27 15:50:38 +01:00
8fd92bea74
Add sunet-kube.drive.test.sunet.se to ingress 2024-11-27 15:43:55 +01:00
ecbf71e0f1
Add sunet-kube.drive.sunet.se to ingress 2024-11-27 15:40:29 +01:00
f8977d44cf
Go to 3.2.1 2024-11-27 14:49:27 +01:00
36ebac5ec1
Go to 4.0.0 2024-11-25 11:00:06 +01:00
15757c0383
Update images to match manifests version 2024-11-25 10:41:21 +01:00
8992dcec17
Run app on apex domain 2024-11-22 10:20:57 +01:00
7c8db87856
Bump version 2024-11-22 10:12:41 +01:00
b4da89ff87
Bump image version 2024-11-21 16:32:10 +01:00
561ee6a29f
Add cert-manager 2024-11-21 11:19:13 +01:00
50d2d1047c
Add cert-manager 2024-11-21 11:17:40 +01:00
21401f0490
Add drive ingress 2024-11-21 11:11:27 +01:00
b7638d9a12
Upgrade to 4.0.0 2024-11-21 11:06:46 +01:00
8f97f3f839
Add cert-manager 2024-11-21 11:03:00 +01:00
238621e2d7
Add cert-manager 2024-11-21 10:57:54 +01:00
bb2755d031
Bump version in test to 29.0.9.3-1 2024-11-18 11:52:40 +01:00
d749ed838e
Bump image version 2024-11-14 17:11:56 +01:00
1c082c4c32
Bump image version 2024-11-14 14:49:04 +01:00
4f519b3399
New appversion 2024-11-14 13:00:43 +01:00
5785023ff1
Remove schem 2024-11-14 12:55:20 +01:00
1fe4a77fee
Don't overwrite image version 2024-11-14 12:52:08 +01:00
57df5e7aa8
Bump image version 2024-11-14 12:43:13 +01:00
6a93585dbf
Try with whole deployment 2024-11-14 12:40:52 +01:00
04e4fbc0c8
Format 2024-11-14 12:40:05 +01:00
fa259a2d7c
Remove init containers 2024-11-14 12:24:53 +01:00
29d8638215
Try some options for pvc 2024-11-14 12:18:41 +01:00
42e500e2cb
Bump version 2024-11-14 11:33:49 +01:00
f2a850278c
Typo 2024-11-14 11:22:05 +01:00
8a9ede5c3a
One more try 2024-11-14 11:20:56 +01:00
b706c72110
order 2024-11-14 11:15:20 +01:00
81262d2af1
Template deployment 2024-11-14 11:12:42 +01:00
32afc32ebb
Generate config for portal 2024-11-14 11:01:20 +01:00
70c3f1537b
Dummy
Signed-off-by: Micke Nordin <kano@sunet.se>
2024-11-12 11:34:27 +01:00
0a505b59ff
Add jupyter for vr-prod
Signed-off-by: Micke Nordin <kano@sunet.se>
2024-11-12 11:22:33 +01:00
31388e392b
Add ingress for vr argo in prod 2024-11-12 10:51:40 +01:00
2a2325e109
Add jupyterhub v4.0.0 and vr-test 2024-11-11 15:12:48 +01:00
a69449ede1
Add jupyterhub for vr test 2024-11-11 15:01:57 +01:00
874f216848
Add cert manager
Signed-off-by: Micke Nordin <kano@sunet.se>
2024-11-06 15:56:57 +01:00
a6c7d4e2f0
Add argo for vr-test 2024-11-06 15:46:49 +01:00
a9cbc314bb
Pull new image 2024-11-05 08:07:50 +01:00
0bb0636d61
Try new version 2024-11-04 11:50:46 +01:00
325b05d352
Bump version to 29.0.8.2-4 2024-10-25 11:40:49 +02:00
43c368211e
Update nextcloud version to 29.0.8.2-1 for nordunet and vinnova. 2024-10-15 10:51:16 +02:00
6f477d9c1b
Dummy commit 2024-10-07 08:23:39 +02:00
fca1f166e0
Signed dummy commit 2024-10-04 17:16:59 +02:00
427e71606a Signed dummy commit
Signed-off-by: Micke Nordin <kano@sunet.se>
2024-10-04 17:15:53 +02:00
cd9fbdf1d5 Set read only again 2024-10-01 11:19:50 +02:00
73db86588c Deploy 29.0.7.2-1 and set config to not read only 2024-10-01 11:17:41 +02:00
aaae51d17b Bump version 2024-08-20 17:12:53 +02:00
ff93521ac3 switch port 2024-08-19 10:34:05 +02:00
af6fdfd154 correct ns 2024-08-19 10:32:31 +02:00
f0bb76f6aa Fix syntax 2024-08-19 10:32:02 +02:00
343a09c93e Fix syntax 2024-08-19 10:30:22 +02:00
ed27635841 Fix syntax 2024-08-19 10:24:41 +02:00
6919487a06 Switch port 2024-08-19 10:21:25 +02:00
cb22a0d919 Switch ingress class 2024-08-19 10:20:26 +02:00
f6f2047535 Switch ingress class 2024-08-19 10:18:16 +02:00
a589c1ed76 Correct ingress type 2024-08-19 10:07:40 +02:00
dfc0ed9d89 Uppgarde nc version 2024-08-05 12:00:02 +02:00
a9e3c68d28 Add basic auth 2024-06-28 15:13:02 +02:00
544b99a843 Rename files 2024-06-28 14:29:48 +02:00
0e7417ddee Rename files 2024-06-28 14:28:48 +02:00
57d27855db File name 2024-06-28 14:26:16 +02:00
39b411e3aa Try another image of the proxy 2024-06-28 14:24:18 +02:00
0609270a81 Add more cluster components 2024-06-28 12:57:08 +02:00
16da1df16b Add spark service 2024-06-28 12:46:02 +02:00
036ef590d2 Maybe its the name that should be like this 2024-06-28 12:35:53 +02:00
e925058169 Chart is named spark-operator 2024-06-28 12:33:20 +02:00
b09b0e3237 Correct version 2024-06-28 12:32:14 +02:00
9f6220e1a7 Also patch 2024-06-28 12:29:40 +02:00
79949532c7 Add ingress 2024-06-28 12:27:58 +02:00
da9a983596 No resources for now 2024-06-28 12:07:38 +02:00
e5c66613b3 First stab at deploying spark 2024-06-28 12:03:43 +02:00
923f67db76 Correct name 2024-06-24 14:04:32 +02:00
85a55ec7a1 Deploy portal 2024-06-24 14:01:35 +02:00
2bd544568e Move to nginx 2024-06-24 11:05:04 +02:00
bfdc489cea Move rds to nginx 2024-06-24 11:00:44 +02:00
8927c853ba Move health to nginx 2024-06-24 10:57:47 +02:00
4cbeee1a32 Enable nginx for drive-test 2024-06-24 10:46:25 +02:00
ab5b6a3e11 Correct hostnames 2024-06-19 16:35:44 +02:00
7eb3369a04 Add jupyterhub 2024-06-19 16:34:18 +02:00
d9cd80d8b0 Add overlay for sunet-prod 2024-06-19 15:53:19 +02:00
33c6a68cd6 Add overlay for sunet-prod 2024-06-19 15:51:06 +02:00
3faace2b35 Bump nextcloud version to 28.0.6.2-1 2024-06-05 11:44:29 +02:00
175741f8ef Remove doris connector from values.yaml 2024-05-31 14:12:28 +01:00
a19e4c71af Change display name for Doris connector 2024-05-31 13:57:39 +01:00
944c114c40 Add env variable 2024-05-29 12:36:01 +02:00
9376178752 Add gu service 2024-05-29 11:56:15 +02:00
01a2c8d258 Add gu service 2024-05-29 11:55:05 +02:00
4d7c577c79 New port for doris 2024-05-27 15:54:09 +02:00
8f8c6704ea Add debug logging 2024-05-27 15:31:51 +02:00
d7afb8190a Change to str 2024-05-27 14:48:49 +02:00
f7085e1a72 Use layer1-port-doris 2024-05-27 14:35:53 +02:00
58d973c5f2 Use layer1-port-doris 2024-05-27 14:33:43 +02:00
5aebe67702 Merge branch 'mandersson-dorisgu' 2024-05-27 14:25:05 +02:00
d250b8a654 Use 28.0.5.2-6 in test 2024-05-21 16:32:07 +02:00
7cf1e79698 Upgrade to new inage 28.0.5.2-5 2024-05-21 08:56:20 +02:00
131 changed files with 13739 additions and 854 deletions

View file

@ -0,0 +1,45 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: customer-applications
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- git:
repoURL: 'https://platform.sunet.se/Drive/k8s-manifests'
revision: HEAD
directories:
- path: 'customers/overlays/*'
template:
metadata:
name: '{{index .path.segments 2}}'
spec:
project: default
source:
repoURL: 'https://platform.sunet.se/Drive/k8s-manifests'
targetRevision: HEAD
path: 'customers/overlays/{{index .path.segments 2}}/test'
destination:
server: https://kubernetes.default.svc
namespace: '{{index .path.segments 2}}'
syncPolicy:
automated:
prune: false
selfHeal: true
allowEmpty: false
syncOptions: # maybe needs FIXME
- Validate=true # disables resource validation (equivalent to 'kubectl apply --validate=false') ( true by default ).
- CreateNamespace=true # Namespace Auto-Creation ensures that namespace specified as the application destination exists in the destination cluster.
- PrunePropagationPolicy=foreground # Supported policies are background, foreground and orphan.
- PruneLast=true # Allow the ability for resource pruning to happen as a final, implicit wave of a sync operation
- RespectIgnoreDifferences=true # When syncing changes, respect fields ignored by the ignoreDifferences configuration
- ApplyOutOfSyncOnly=true # Only sync out-of-sync resources, rather than applying every object in the application
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 2

View file

@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: drive@sunet.se
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx

View file

@ -1,2 +1,3 @@
resources: resources:
- argocd-ingress.yaml - argocd-ingress.yaml
- argocd-cert-issuer.yaml

View file

@ -3,16 +3,13 @@ kind: Ingress
metadata: metadata:
name: argocd-ingress name: argocd-ingress
namespace: argocd namespace: argocd
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
defaultBackend: defaultBackend:
service: service:
name: argocd-server name: argocd-server
port: port:
number: 8443 number: 80
ingressClassName: traefik ingressClassName: nginx
tls: tls:
- hosts: - hosts:
- argocd.drive.test.sunet.dev - argocd.drive.test.sunet.dev

View file

@ -0,0 +1,30 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: argocd-server
port:
number: 80
ingressClassName: nginx
tls:
- hosts:
- argocd.drive.sunet.se
secretName: tls-secret
rules:
- host: argocd.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80

View file

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base]
patches:
- path: argocd-ingress.yaml

View file

@ -0,0 +1,30 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
namespace: argocd
spec:
defaultBackend:
service:
name: argocd-server
port:
number: 80
ingressClassName: nginx
tls:
- hosts:
- sunet-argocd.drive.sunet.se
secretName: tls-secret
rules:
- host: sunet-argocd.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80

View file

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base]
patches:
- path: argocd-ingress.yaml

View file

@ -0,0 +1,30 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: argocd-server
port:
number: 80
ingressClassName: nginx
tls:
- hosts:
- vr-argocd.drive.sunet.se
secretName: tls-secret
rules:
- host: vr-argocd.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80

View file

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base]
patches:
- path: argocd-ingress.yaml

View file

@ -0,0 +1,30 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: argocd-server
port:
number: 80
ingressClassName: nginx
tls:
- hosts:
- argocd.drive.test.sunet.se
secretName: tls-secret
rules:
- host: argocd.drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80

View file

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base]
patches:
- path: argocd-ingress.yaml

View file

@ -3,6 +3,9 @@ kind: Ingress
metadata: metadata:
name: argocd-ingress name: argocd-ingress
namespace: argocd namespace: argocd
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec: spec:
defaultBackend: defaultBackend:
service: service:
@ -13,6 +16,7 @@ spec:
tls: tls:
- hosts: - hosts:
- sunet-argocd.drive.test.sunet.se - sunet-argocd.drive.test.sunet.se
- sunet-kube.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
rules: rules:
- host: sunet-argocd.drive.test.sunet.se - host: sunet-argocd.drive.test.sunet.se

View file

@ -0,0 +1,30 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: argocd-server
port:
number: 80
ingressClassName: nginx
tls:
- hosts:
- vr-argocd.drive.test.sunet.se
secretName: tls-secret
rules:
- host: vr-argocd.drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80

View file

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base]
patches:
- path: argocd-ingress.yaml

View file

@ -0,0 +1,60 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup
spec:
schedule: "0 0 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
volumes:
- name: backup-storage
emptyDir: {}
- name: ipc-storage
emptyDir: {}
restartPolicy: Never
containers:
- name: backup-container
image: docker.sunet.se/drive/duplicity:bookworm-slim-1
command: ["bash"]
args: [ "-c", "duplicity /backup_storage rclone://destination:$(BUCKET) --no-encryption --full-if-older-than 1M; touch /backup_ipc/stop" ]
env:
- name: RCLONE_CONFIG_DESTINATION_ACL
value: private
- name: RCLONE_CONFIG_DESTINATION_TYPE
value: s3
- name: RCLONE_CONFIG_DESTINATION_ENDPOINT
value: s3.sto3.safedc.net
- name: RCLONE_CONFIG_DESTINATION_PROVIDER
value: Ceph
volumeMounts:
- name: backup-storage
mountPath: /backup_storage
mountPropagation: HostToContainer
- name: ipc-storage
mountPath: /backup_ipc
- name: mount-container
image: rclone/rclone:1.69.0
args: ["mount", "--allow-non-empty", "source:$(BUCKET)", "/backup_storage"]
securityContext:
privileged: true
env:
- name: RCLONE_CONFIG_SOURCE_ACL
value: private
- name: RCLONE_CONFIG_SOURCE_TYPE
value: s3
- name: RCLONE_CONFIG_SOURCE_ENDPOINT
value: s3.sto4.safedc.net
- name: RCLONE_CONFIG_SOURCE_PROVIDER
value: Ceph
volumeMounts:
- name: backup-storage
mountPath: /backup_storage
mountPropagation: Bidirectional
- name: ipc-storage
mountPath: /backup_ipc
livenessProbe:
exec:
command: ["sh", "-c", "if test -f /backup_ipc/stop; then umount /backup_storage; exit 1; fi;"]

View file

@ -0,0 +1,4 @@
---
kind: Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
resources: ['backup-cronjob.yaml']

View file

@ -0,0 +1,40 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup
spec:
schedule: "15 02 * * *"
jobTemplate:
spec:
template:
spec:
hostname: xrootd-test-mirror
containers:
- name: backup-container
env:
- name: BUCKET
value: "xrootd-test-mirror"
- name: RCLONE_CONFIG_DESTINATION_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: xrootd-secret
key: "destination-access-key-id"
- name: RCLONE_CONFIG_DESTINATION_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: xrootd-secret
key: "destination-secret-access-key"
- name: mount-container
env:
- name: BUCKET
value: "xrootd-test"
- name: RCLONE_CONFIG_SOURCE_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: xrootd-secret
key: "source-access-key-id"
- name: RCLONE_CONFIG_SOURCE_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: xrootd-secret
key: "source-secret-access-key"

View file

@ -0,0 +1,7 @@
---
kind: Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
resources: [../../../base]
patches:
- path: backup-cronjob.yaml

View file

@ -1,73 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: apache-configmap
data:
000-default.conf: |
LoadModule remoteip_module /usr/lib/apache2/modules/mod_remoteip.so
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Log format config
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" common
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
# Header config
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 37.156.195.14
RemoteIPInternalProxy 37.156.195.19
RemoteIPInternalProxy 37.156.195.84
RemoteIPInternalProxy 37.156.195.92
#ErrorDocument 404 /404.html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined env=forwarded
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /var/www/html/>
LimitRequestBody 0
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Log format config
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" common
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
# Header config
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 37.156.195.14
RemoteIPInternalProxy 37.156.195.19
RemoteIPInternalProxy 37.156.195.84
RemoteIPInternalProxy 37.156.195.92
#ErrorDocument 404 /404.html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined env=forwarded
SSLEngine On
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
<Directory /var/www/html/>
LimitRequestBody 0
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
<Directory /var/www/html/data>
Order allow,deny
deny from all
</Directory>
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

View file

@ -1,162 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: apache-php-configmap
data:
php.ini: |
[PHP]
allow_url_fopen = On
allow_url_include = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 60
disable_classes =
disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
engine = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = Off
file_uploads = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 1024
max_execution_time = 86400
max_file_uploads = 20
max_input_time = 86400
memory_limit = 512M
output_buffering = Off
post_max_size = 30G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = -1
short_open_tag = Off
unserialize_callback_func =
upload_max_filesize = 30G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zend.exception_ignore_args = On
zlib.output_compression = Off
[CLI Server]
cli_server.color = On
[Date]
; Nothing here
[filter]
; Nothing here
[iconv]
; Nothing here
[imap]
; Nothing here
[intl]
; Nothing here
[sqlite3]
; Nothing here
[Pcre]
; Nothing here
[Pdo]
; Nothing here
[Pdo_mysql]
pdo_mysql.default_socket=
[Phar]
; Nothing here
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
; Nothing here
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
; Nothing here
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[COM]
; Nothing here
[mbstring]
; Nothing here
[gd]
; Nothing here
[exif]
; Nothing here
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
; Nothing here
[ldap]
ldap.max_links = -1
[dba]
; Nothing here
[opcache]
opcache.interned_strings_buffer=64
[curl]
; Nothing here
[openssl]
; Nothing here
[ffi]
; Nothing here

View file

@ -1,8 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: apcu-configmap
data:
apcu.ini: |
extension=apcu.so
apc.enable_cli=1

View file

@ -1,162 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: cli-php-configmap
data:
php.ini: |
[PHP]
allow_url_fopen = On
allow_url_include = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 60
disable_classes =
disable_functions =
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
engine = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = On
file_uploads = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 1024
max_execution_time = 86400
max_file_uploads = 20
max_input_time = 86400
memory_limit = -1
output_buffering = Off
post_max_size = 16G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = -1
short_open_tag = Off
unserialize_callback_func =
upload_max_filesize = 16G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zend.exception_ignore_args = On
zlib.output_compression = Off
[CLI Server]
cli_server.color = On
[Date]
; Nothing here
[filter]
; Nothing here
[iconv]
; Nothing here
[imap]
; Nothing here
[intl]
; Nothing here
[sqlite3]
; Nothing here
[Pcre]
; Nothing here
[Pdo]
; Nothing here
[Pdo_mysql]
pdo_mysql.default_socket=
[Phar]
; Nothing here
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
; Nothing here
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
; Nothing here
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[COM]
; Nothing here
[mbstring]
; Nothing here
[gd]
; Nothing here
[exif]
; Nothing here
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
; Nothing here
[ldap]
ldap.max_links = -1
[dba]
; Nothing here
[opcache]
opcache.interned_strings_buffer=64
[curl]
; Nothing here
[openssl]
; Nothing here
[ffi]
; Nothing here

View file

@ -0,0 +1,26 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nextcloud-env
data:
GSS_MASTER_URL: 'https://drive.test.sunet.se'
LOOKUP_SERVER: 'https://lookup.drive.test.sunet.se'
MAIL_DOMAIN: 'drive.test.sunet.se'
MAIL_FROM_ADDRESS: 'noreply'
MAIL_SMTPHOST: 'smtp.sunet.se'
MAIL_SMTPNAME: 'noreply@drive.test.sunet.se'
MYSQL_DATABASE: 'nextcloud_customer'
MYSQL_HOST: 'proxysqlcluster.proxysql'
MYSQL_PORT: '6033'
MYSQL_USER: 'nextcloud_customer'
NEXTCLOUD_ADMIN_USER: 'admin'
NEXTCLOUD_TRUSTED_DOMAINS: 'customer.drive.test.sunet.se'
NEXTCLOUD_VERSION_STRING: '30.0.5.2'
OBJECTSTORE_S3_AUTOCREATE: 'true'
OBJECTSTORE_S3_BUCKET: 'primary-customer-drive-test.sunet.se'
OBJECTSTORE_S3_HOST: 's3.sto4.safedc.net'
OBJECTSTORE_S3_REGION: 'us-east-1'
OBJECTSTORE_S3_SSL: 'true'
OBJECTSTORE_S3_USEPATH_STYLE: 'true'
REDIS_HOST: 'redis'
SITE_NAME: 'customer.drive.test.sunet.se'

View file

@ -0,0 +1,73 @@
LoadModule remoteip_module /usr/lib/apache2/modules/mod_remoteip.so
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Log format config
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" xforwardedfor
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
PassEnv HOSTNAME
Header append Set-Cookie "SERVERID=%{HOSTNAME}e;Path=/;SameSite=Lax;HttpOnly;Secure"
# Header config
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 37.156.195.14
RemoteIPInternalProxy 37.156.195.19
RemoteIPInternalProxy 37.156.195.84
RemoteIPInternalProxy 37.156.195.92
#ErrorDocument 404 /404.html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log xforwardedfor env=forwarded
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!forwarded
<Directory /var/www/html/>
LimitRequestBody 0
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Log format config
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" xforwardedfor
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
PassEnv HOSTNAME
Header append Set-Cookie "SERVERID=%{HOSTNAME}e;Path=/;SameSite=Lax;HttpOnly;Secure"
# Header config
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 37.156.195.14
RemoteIPInternalProxy 37.156.195.19
RemoteIPInternalProxy 37.156.195.84
RemoteIPInternalProxy 37.156.195.92
#ErrorDocument 404 /404.html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log xforwardedfor env=forwarded
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!forwarded
SSLEngine On
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
<Directory /var/www/html/>
LimitRequestBody 0
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
<Directory /var/www/html/data>
Order allow,deny
deny from all
</Directory>
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

View file

@ -0,0 +1,157 @@
[PHP]
allow_url_fopen = On
allow_url_include = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 60
disable_classes =
disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
engine = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = Off
file_uploads = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 1024
max_execution_time = 86400
max_file_uploads = 20
max_input_time = 86400
memory_limit = 512M
output_buffering = Off
post_max_size = 30G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = -1
short_open_tag = Off
unserialize_callback_func =
upload_max_filesize = 30G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zend.exception_ignore_args = On
zlib.output_compression = Off
[CLI Server]
cli_server.color = On
[Date]
; Nothing here
[filter]
; Nothing here
[iconv]
; Nothing here
[imap]
; Nothing here
[intl]
; Nothing here
[sqlite3]
; Nothing here
[Pcre]
; Nothing here
[Pdo]
; Nothing here
[Pdo_mysql]
pdo_mysql.default_socket=
[Phar]
; Nothing here
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
; Nothing here
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
; Nothing here
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[COM]
; Nothing here
[mbstring]
; Nothing here
[gd]
; Nothing here
[exif]
; Nothing here
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
; Nothing here
[ldap]
ldap.max_links = -1
[dba]
; Nothing here
[opcache]
opcache.interned_strings_buffer=64
[curl]
; Nothing here
[openssl]
; Nothing here
[ffi]
; Nothing here

View file

@ -0,0 +1,3 @@
extension=apcu.so
apc.enable_cli=1

View file

@ -0,0 +1,157 @@
[PHP]
allow_url_fopen = On
allow_url_include = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 60
disable_classes =
disable_functions =
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
engine = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = On
file_uploads = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 1024
max_execution_time = 86400
max_file_uploads = 20
max_input_time = 86400
memory_limit = -1
output_buffering = Off
post_max_size = 16G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = -1
short_open_tag = Off
unserialize_callback_func =
upload_max_filesize = 16G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zend.exception_ignore_args = On
zlib.output_compression = Off
[CLI Server]
cli_server.color = On
[Date]
; Nothing here
[filter]
; Nothing here
[iconv]
; Nothing here
[imap]
; Nothing here
[intl]
; Nothing here
[sqlite3]
; Nothing here
[Pcre]
; Nothing here
[Pdo]
; Nothing here
[Pdo_mysql]
pdo_mysql.default_socket=
[Phar]
; Nothing here
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
; Nothing here
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
; Nothing here
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[COM]
; Nothing here
[mbstring]
; Nothing here
[gd]
; Nothing here
[exif]
; Nothing here
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
; Nothing here
[ldap]
ldap.max_links = -1
[dba]
; Nothing here
[opcache]
opcache.interned_strings_buffer=64
[curl]
; Nothing here
[openssl]
; Nothing here
[ffi]
; Nothing here

View file

@ -0,0 +1,107 @@
<?php
$CONFIG = array (
'app_install_overwrite' =>
array (
0 => 'globalsiteselector',
),
'apps_paths' =>
array (
0 =>
array (
'path' => '/var/www/html/apps',
'url' => '/apps',
'writable' => false,
),
1 =>
array (
'path' => '/var/www/html/custom_apps',
'url' => '/custom_apps',
'writable' => true,
),
),
'appstoreenabled' => false,
'config_is_read_only' => true,
'csrf.disabled' => true,
'datadirectory' => '/var/www/html/data',
'dbhost' => '{{MYSQL_HOST}}:{{MYSQL_PORT}}',
'dbname' => '{{MYSQL_DATABASE}}',
'dbpassword' => '{{MYSQL_PASSWORD}}',
'dbport' => '{{MYSQL_PORT}}',
'dbtableprefix' => 'oc_',
'dbtype' => 'mysql',
'dbuser' => '{{MYSQL_USER}}',
'default_phone_region' => 'SE',
'forcessl' => true,
'gs.enabled' => 'true',
'gs.federation' => 'global',
'gs.trustedHosts' => ['*.sunet.se'],
'htaccess.RewriteBase' => '/',
'installed' => true,
'instanceid' => '{{NEXTCLOUD_INSTANCEID}}',
'integrity.check.disabled' => true,
'log_type' => 'file',
'loglevel' => 0,
'lookup_server' => '{{LOOKUP_SERVER}}',
'mail_domain' => '{{MAIL_DOMAIN}}',
'mail_from_address' => '{{MAIL_FROM_ADDRESS}}',
'mail_sendmailmode' => 'smtp',
'mail_smtpauth' => 1,
'mail_smtpauthtype' => 'LOGIN',
'mail_smtphost' => '{{MAIL_SMTPHOST}}',
'mail_smtpmode' => 'smtp',
'mail_smtpname' => '{{MAIL_SMTPNAME}}',
'mail_smtppassword' => '{{MAIL_SMTPPASSWORD}}',
'mail_smtpport' => '587',
'mail_smtpsecure' => 'tls',
'mail_template_class' => 'OCA\DriveEmailTemplate\EMailTemplate',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'mysql.utf8mb4' => true,
'objectstore' =>
array (
'class' => '\\OC\\Files\\ObjectStore\\S3',
'arguments' =>
array (
'autocreate' => false,
'bucket' => '{{OBJECTSTORE_S3_BUCKET}}',
'hostname' => '{{OBJECTSTORE_S3_HOST}}',
'key' => '{{OBJECTSTORE_S3_KEY}}',
'legacy_auth' => false,
'objectPrefix' => 'urn:oid:',
'port' => '',
'region' => '{{OBJECTSTORE_S3_REGION}}',
'secret' => '{{OBJECTSTORE_S3_SECRET}}',
'use_path_style' => true,
'use_ssl' => true,
),
),
'overwrite.cli.url' => 'https://{{SITE_NAME}}/',
'overwritehost' => '{{SITE_NAME}}',
'overwriteprotocol' => 'https',
'passwordsalt' => '{{NEXTCLOUD_PASSWORDSALT}}',
'secret' => '{{NEXTCLOUD_SECRET}}',
'redis' =>
array (
'host' => '{{REDIS_HOST}}',
'port' => 6379,
),
'skeletondirectory' => '',
'templatedirectory' => '',
'trusted_domains' =>
array (
0 => '{{NEXTCLOUD_TRUSTED_DOMAINS}}'
),
'trusted_proxies' =>
array (
0 => '10.0.0.0/8'
),
'twofactor_enforced' => 'true',
'twofactor_enforced_groups' =>
array (
0 => 'admin',
),
'updatechecker' => false,
'version' => '{{NEXTCLOUD_VERSION_STRING}}',
);

View file

@ -0,0 +1,14 @@
#!/bin/bash
sed "s/config_is_read_only\(.\) => true,/config_is_read_only\1 => false,/" /var/www/html/config/config.php > /var/www/html/config/config.php.tmp
mv /var/www/html/config/config.php.tmp /var/www/html/config/config.php
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ upgrade
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ maintenance:update:htaccess
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ maintenance:repair
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ maintenance:mode --off
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ db:add-missing-primary-keys
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ db:add-missing-columns
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ db:add-missing-indices
sed "s/config_is_read_only\(.\) => false,/config_is_read_only\1 => true,/" /var/www/html/config/config.php > /var/www/html/config/config.php.tmp
mv /var/www/html/config/config.php.tmp /var/www/html/config/config.php
chown www-data:www-data /var/www/html/config/config.php

View file

@ -1,13 +1,37 @@
resources: resources:
- apache-configmap.yml - env-configmap.yml
- apache-php-configmap.yml - nextcloud-cert-issuer.yml
- apcu-configmap.yml
- cli-php-configmap.yml
- nextcloud-configmap.yml
- nextcloud-deployment.yml - nextcloud-deployment.yml
- nextcloud-ingress.yml - nextcloud-ingress.yml
- nextcloud-service.yml - nextcloud-service.yml
- redis-deployment.yml - redis-deployment.yml
- redis-service.yml - redis-service.yml
- s3-service.yml - s3-service.yml
- script-configmap.yml
configMapGenerator:
- name: apache-configmap
files:
- files/000-default.conf
- name: apache-php-configmap
files:
- php.ini=files/apache-php.ini
- name: apcu-configmap
files:
- files/apcu.ini
- name: nextcloud-configmap
files:
- files/config.php
- name: cli-php-configmap
files:
- php.ini=files/cli-php.ini
- name: script-configmap
files:
- files/nc-upgrade
generatorOptions:
disableNameSuffixHash: true
images:
- name: nextcloud-custom-image
newName: docker.sunet.se/drive/nextcloud-custom
newTag: 30.0.5.2-2

View file

@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: drive@sunet.se
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx

View file

@ -1,115 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nextcloud-configmap
data:
config.php: |
<?php
$CONFIG = array (
'app_install_overwrite' =>
array (
0 => 'globalsiteselector',
),
'apps_paths' =>
array (
0 =>
array (
'path' => '/var/www/html/apps',
'url' => '/apps',
'writable' => false,
),
1 =>
array (
'path' => '/var/www/html/custom_apps',
'url' => '/custom_apps',
'writable' => true,
),
),
'appstoreenabled' => false,
'config_is_read_only' => true,
'csrf.disabled' => true,
'datadirectory' => '/var/www/html/data',
'dbhost' => '{{MYSQL_HOST}}:{{MYSQL_PORT}}',
'dbname' => '{{MYSQL_DATABASE}}',
'dbpassword' => '{{MYSQL_PASSWORD}}',
'dbport' => '{{MYSQL_PORT}}',
'dbtableprefix' => 'oc_',
'dbtype' => 'mysql',
'dbuser' => '{{MYSQL_USER}}',
'default_phone_region' => 'SE',
'forcessl' => true,
'gs.enabled' => 'true',
'gs.federation' => 'global',
'gs.trustedHosts' => ['*.sunet.se'],
'gss.jwt.key' => '{{GSS_JWT_KEY}}',
'gss.master.url' => '{{GSS_MASTER_URL}}',
'gss.mode' => 'slave',
'gss.user.discovery.module' => '\\OCA\\GlobalSiteSelector\\UserDiscoveryModules\\ManualUserMapping',
'installed' => true,
'instanceid' => '{{NEXTCLOUD_INSTANCEID}}',
'integrity.check.disabled' => true,
'log_type' => 'file',
'loglevel' => 0,
'lookup_server' => '{{LOOKUP_SERVER}}',
'mail_domain' => '{{MAIL_DOMAIN}}',
'mail_from_address' => '{{MAIL_FROM_ADDRESS}}',
'mail_sendmailmode' => 'smtp',
'mail_smtpauth' => 1,
'mail_smtpauthtype' => 'LOGIN',
'mail_smtphost' => '{{MAIL_SMTPHOST}}',
'mail_smtpmode' => 'smtp',
'mail_smtpname' => '{{MAIL_SMTPNAME}}',
'mail_smtppassword' => '{{MAIL_SMTPPASSWORD}}',
'mail_smtpport' => '587',
'mail_smtpsecure' => 'tls',
'mail_template_class' => 'OCA\DriveEmailTemplate\EMailTemplate',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'mysql.utf8mb4' => true,
'objectstore' =>
array (
'class' => '\\OC\\Files\\ObjectStore\\S3',
'arguments' =>
array (
'autocreate' => false,
'bucket' => '{{OBJECTSTORE_S3_BUCKET}}',
'hostname' => '{{OBJECTSTORE_S3_HOST}}',
'key' => '{{OBJECTSTORE_S3_KEY}}',
'legacy_auth' => false,
'objectPrefix' => 'urn:oid:',
'port' => '',
'region' => '{{OBJECTSTORE_S3_REGION}}',
'secret' => '{{OBJECTSTORE_S3_SECRET}}',
'use_path_style' => true,
'use_ssl' => true,
),
),
'overwrite.cli.url' => 'https://{{SITE_NAME}}',
'overwritehost' => '{{SITE_NAME}}',
'overwriteprotocol' => 'https',
'passwordsalt' => '{{NEXTCLOUD_PASSWORDSALT}}',
'secret' => '{{NEXTCLOUD_SECRET}}',
'redis' =>
array (
'host' => '{{REDIS_HOST}}',
'port' => 6379,
),
'skeletondirectory' => '',
'templatedirectory' => '',
'trusted_domains' =>
array (
0 => '{{NEXTCLOUD_TRUSTED_DOMAINS}}'
),
'trusted_proxies' =>
array (
0 => '10.0.0.0/8'
),
'twofactor_enforced' => 'true',
'twofactor_enforced_groups' =>
array (
0 => 'admin',
),
'updatechecker' => false,
'version' => '{{NEXTCLOUD_VERSION_STRING}}',
);

View file

@ -11,16 +11,6 @@ spec:
app: customer-node app: customer-node
updateStrategy: updateStrategy:
type: RollingUpdate type: RollingUpdate
volumeClaimTemplates:
- metadata:
name: nextcloud-data
spec:
storageClassName: csi-sc-cinderplugin
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
template: template:
metadata: metadata:
labels: labels:
@ -28,9 +18,25 @@ spec:
kano: micke kano: micke
spec: spec:
restartPolicy: Always restartPolicy: Always
initContainers:
- image: docker.sunet.se/sunet/docker-jinja:latest
name: init-config
volumeMounts:
- name: nextcloud-config
mountPath: /tmp/config.php.template
subPath: config.php
- name: nextcloud-data
mountPath: /var/www/html/config
subPath: config
envFrom:
- configMapRef:
name: nextcloud-env
- secretRef:
name: nextcloud-secrets
command: ["/bin/bash", "-c", "/usr/bin/j2 -f env -o /var/www/html/config/config.php /tmp/config.php.template"]
containers: containers:
- name: customer - name: customer
image: docker.sunet.se/drive/nextcloud-custom:28.0.5.2-2 image: nextcloud-custom-image
volumeMounts: volumeMounts:
- name: nextcloud-data - name: nextcloud-data
mountPath: /var/www/html/config/ mountPath: /var/www/html/config/
@ -76,105 +82,6 @@ spec:
postStart: postStart:
exec: exec:
command: ["/bin/bash", "-c", "/usr/local/bin/nc-upgrade"] command: ["/bin/bash", "-c", "/usr/local/bin/nc-upgrade"]
initContainers:
- image: docker.sunet.se/sunet/docker-jinja:latest
name: init-config
volumeMounts:
- name: nextcloud-config
mountPath: /tmp/config.php.template
subPath: config.php
- name: nextcloud-data
mountPath: /var/www/html/config
subPath: config
env:
- name: GSS_MASTER_URL
value: "https://drive.test.sunet.se"
- name: GSS_JWT_KEY
valueFrom:
secretKeyRef:
name: gss-secret
key: "jwt_key"
- name: LOOKUP_SERVER
value: "https://lookup.drive.test.sunet.se"
- name: MAIL_DOMAIN
value: "drive.test.sunet.se"
- name: MAIL_FROM_ADDRESS
value: "noreply"
- name: MAIL_SMTPHOST
value: "smtp.sunet.se"
- name: MAIL_SMTPNAME
value: "noreply@drive.test.sunet.se"
- name: MAIL_SMTPPASSWORD
valueFrom:
secretKeyRef:
name: mail-secret
key: "smtp_password"
- name: MYSQL_DATABASE
value: "nextcloud_customer"
- name: MYSQL_USER
value: "nextcloud_customer"
- name: MYSQL_HOST
value: "proxysqlcluster.proxysql"
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: "db_password"
- name: MYSQL_PORT
value: "6033"
- name: NEXTCLOUD_TRUSTED_DOMAINS
value: "customer.drive.test.sunet.se"
- name: NEXTCLOUD_ADMIN_USER
value: admin
- name: NEXTCLOUD_VERSION_STRING
value: "28.0.3.3"
- name: NEXTCLOUD_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: nc-secret
key: "nc_admin_password"
- name: NEXTCLOUD_PASSWORDSALT
valueFrom:
secretKeyRef:
name: nc-secret
key: "nc_passwordsalt"
- name: NEXTCLOUD_INSTANCEID
valueFrom:
secretKeyRef:
name: nc-secret
key: "nc_instanceid"
- name: NEXTCLOUD_SECRET
valueFrom:
secretKeyRef:
name: nc-secret
key: "nc_secret"
- name: OBJECTSTORE_S3_REGION
value: "us-east-1"
- name: OBJECTSTORE_S3_HOST
value: "s3.sto4.safedc.net"
- name: OBJECTSTORE_S3_BUCKET
value: "primary-customer-drive-test.sunet.se"
- name: OBJECTSTORE_S3_KEY
valueFrom:
secretKeyRef:
name: s3-secret
key: "s3_key"
- name: OBJECTSTORE_S3_SECRET
valueFrom:
secretKeyRef:
name: s3-secret
key: "s3_secret"
- name: OBJECTSTORE_S3_USEPATH_STYLE
value: "true"
- name: OBJECTSTORE_S3_AUTOCREATE
value: "true"
- name: OBJECTSTORE_S3_SSL
value: "true"
- name: REDIS_HOST
value: "redis"
- name: SITE_NAME
value: "customer.drive.test.sunet.se"
command: ["/bin/bash", "-c", "/usr/bin/j2 -f env -o /var/www/html/config/config.php /tmp/config.php.template"]
volumes: volumes:
- name: script-config - name: script-config
configMap: configMap:
@ -213,3 +120,5 @@ spec:
items: items:
- key: "config.php" - key: "config.php"
path: "config.php" path: "config.php"
- name: nextcloud-data
emptyDir: {}

View file

@ -4,10 +4,15 @@ kind: Ingress
metadata: metadata:
name: customer-ingress name: customer-ingress
annotations: annotations:
kubernetes.io/ingress.class: traefik cert-manager.io/issuer: "letsencrypt"
traefik.ingress.kubernetes.io/router.entrypoints: websecure acme.cert-manager.io/http01-edit-in-place: "true"
traefik.ingress.kubernetes.io/router.tls: "true" nginx.ingress.kubernetes.io/affinity-mode: "persistent"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
nginx.ingress.kubernetes.io/session-cookie-name: "sticky"
spec: spec:
ingressClassName: nginx
defaultBackend: defaultBackend:
service: service:
name: customer-node name: customer-node
@ -17,7 +22,6 @@ spec:
- hosts: - hosts:
- customer.drive.test.sunet.se - customer.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
rules: rules:
- host: customer.drive.test.sunet.se - host: customer.drive.test.sunet.se
http: http:

View file

@ -1,19 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: script-configmap
data:
nc-upgrade: |
#!/bin/bash
sed "s/config_is_read_only\(.\) => true,/config_is_read_only\1 => false,/" /var/www/html/config/config.php > /var/www/html/config/config.php.tmp
mv /var/www/html/config/config.php.tmp /var/www/html/config/config.php
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ app:disable globalsiteselector
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ upgrade
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ app:enable globalsiteselector
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ maintenance:repair
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ maintenance:mode --off
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ db:add-missing-primary-keys
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ db:add-missing-columns
php -d apc.enable_cli=1 -d memory_limit=-1 /var/www/html/occ db:add-missing-indices
sed "s/config_is_read_only\(.\) => false,/config_is_read_only\1 => true,/" /var/www/html/config/config.php > /var/www/html/config/config.php.tmp
mv /var/www/html/config/config.php.tmp /var/www/html/config/config.php

View file

@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nextcloud-env
data:
MYSQL_DATABASE: 'nextcloud_nordunet'
MYSQL_USER: 'nextcloud_nordunet'
NEXTCLOUD_TRUSTED_DOMAINS: 'nordunet.drive.test.sunet.se'
OBJECTSTORE_S3_BUCKET: 'primary-nordunet-drive-test.sunet.se'
SITE_NAME: 'nordunet.drive.test.sunet.se'

View file

@ -1,7 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- ../../../base - ../../../base
patches: patches:
- path: nextcloud-deployment.yml - path: env-configmap.yml
- path: nextcloud-ingress.yml - path: nextcloud-deployment.yml
- path: nextcloud-ingress.yml

View file

@ -6,30 +6,3 @@ metadata:
app: customer-node app: customer-node
spec: spec:
replicas: 1 replicas: 1
template:
metadata:
labels:
app: customer-node
spec:
initContainers:
- image: docker.sunet.se/sunet/docker-jinja:latest
name: init-config
env:
- name: MYSQL_DATABASE
value: "nextcloud_nordunet"
- name: MYSQL_USER
value: "nextcloud_nordunet"
- name: GSS_MASTER_URL
value: "https://drive.test.sunet.se"
- name: LOOKUP_SERVER
value: "https://lookup.drive.test.sunet.se"
- name: MAIL_DOMAIN
value: "drive.test.sunet.se"
- name: MAIL_SMTPNAME
value: "noreply@drive.test.sunet.se"
- name: NEXTCLOUD_TRUSTED_DOMAINS
value: "nordunet.drive.test.sunet.se"
- name: OBJECTSTORE_S3_BUCKET
value: "primary-nordunet-drive-test.sunet.se"
- name: SITE_NAME
value: "nordunet.drive.test.sunet.se"

View file

@ -4,15 +4,15 @@ kind: Ingress
metadata: metadata:
name: customer-ingress name: customer-ingress
annotations: annotations:
kubernetes.io/ingress.class: traefik cert-manager.io/issuer: "letsencrypt"
traefik.ingress.kubernetes.io/router.entrypoints: websecure acme.cert-manager.io/http01-edit-in-place: "true"
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
ingressClassName: nginx
tls: tls:
- hosts: - hosts:
- nordunet.drive.test.sunet.se - nordunet.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
ingressClassName: nginx
rules: rules:
- host: nordunet.drive.test.sunet.se - host: nordunet.drive.test.sunet.se
http: http:

View file

@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nextcloud-env
data:
MYSQL_DATABASE: 'nextcloud_richir'
MYSQL_USER: 'nextcloud_richir'
NEXTCLOUD_TRUSTED_DOMAINS: 'richir.drive.test.sunet.se'
OBJECTSTORE_S3_BUCKET: 'primary-richir-drive-test.sunet.se'
SITE_NAME: 'richir.drive.test.sunet.se'

View file

@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base
patches:
- path: env-configmap.yml
- path: nextcloud-deployment.yml
- path: nextcloud-ingress.yml

View file

@ -0,0 +1,8 @@
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: customer-node
labels:
app: customer-node
spec:
replicas: 2

View file

@ -0,0 +1,26 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: customer-ingress
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- richir.drive.test.sunet.se
secretName: tls-secret
ingressClassName: nginx
rules:
- host: richir.drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: customer-node
port:
number: 80

View file

@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nextcloud-env
data:
MYSQL_DATABASE: 'nextcloud_vinnova'
MYSQL_USER: 'nextcloud_vinnova'
NEXTCLOUD_TRUSTED_DOMAINS: 'vinnova.drive.test.sunet.se'
OBJECTSTORE_S3_BUCKET: 'primary-vinnova-test.sunet.se'
SITE_NAME: 'vinnova.drive.test.sunet.se'

View file

@ -1,7 +1,8 @@
apiVersion: 'kustomize.config.k8s.io/v1beta1' apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
bases: resources:
- ../../../base - ../../../base
patchesStrategicMerge: patches:
- nextcloud-deployment.yml - path: env-configmap.yml
- nextcloud-ingress.yml - path: nextcloud-deployment.yml
- path: nextcloud-ingress.yml

View file

@ -5,30 +5,4 @@ metadata:
labels: labels:
app: customer-node app: customer-node
spec: spec:
template: replicas: 1
metadata:
labels:
app: customer-node
spec:
initContainers:
- image: docker.sunet.se/sunet/docker-jinja:latest
name: init-config
env:
- name: MYSQL_DATABASE
value: "nextcloud_vinnova"
- name: MYSQL_USER
value: "nextcloud_vinnova"
- name: GSS_MASTER_URL
value: "https://drive.test.sunet.se"
- name: LOOKUP_SERVER
value: "https://lookup.drive.test.sunet.se"
- name: MAIL_DOMAIN
value: "drive.test.sunet.se"
- name: MAIL_SMTPNAME
value: "noreply@drive.test.sunet.se"
- name: NEXTCLOUD_TRUSTED_DOMAINS
value: "vinnova.drive.test.sunet.se"
- name: OBJECTSTORE_S3_BUCKET
value: "primary-vinnova-test.sunet.se"
- name: SITE_NAME
value: "vinnova.drive.test.sunet.se"

View file

@ -4,15 +4,15 @@ kind: Ingress
metadata: metadata:
name: customer-ingress name: customer-ingress
annotations: annotations:
kubernetes.io/ingress.class: traefik cert-manager.io/issuer: "letsencrypt"
traefik.ingress.kubernetes.io/router.entrypoints: websecure acme.cert-manager.io/http01-edit-in-place: "true"
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
ingressClassName: nginx
tls: tls:
- hosts: - hosts:
- vinnova.drive.test.sunet.se - vinnova.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
ingressClassName: nginx
rules: rules:
- host: vinnova.drive.test.sunet.se - host: vinnova.drive.test.sunet.se
http: http:

View file

@ -5,20 +5,18 @@ metadata:
name: health-ingress name: health-ingress
namespace: health namespace: health
annotations: annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure kubernetes.io/ingress.class: nginx
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
defaultBackend: defaultBackend:
service: service:
name: health-node name: health-node
port: port:
number: 8443 number: 8443
ingressClassName: traefik ingressClassName: nginx
tls: tls:
- hosts: - hosts:
- kube.drive.test.sunet.se - kube.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
rules: rules:
- host: kube.drive.test.sunet.se - host: kube.drive.test.sunet.se
http: http:

View file

@ -0,0 +1,30 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: health-ingress
namespace: health
annotations:
kubernetes.io/ingress.class: nginx
spec:
defaultBackend:
service:
name: health-node
port:
number: 8443
ingressClassName: nginx
tls:
- hosts:
- sunet-kube.drive.sunet.se
secretName: tls-secret
rules:
- host: sunet-kube.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: health-node
port:
number: 8080

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: health-ingress.yml

View file

@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: drive@sunet.se
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx

View file

@ -4,7 +4,6 @@ kind: Ingress
metadata: metadata:
name: jupyterhub-ingress name: jupyterhub-ingress
annotations: annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:

View file

@ -1,4 +1,4 @@
--- ---
resources: [jupyterhub-ingress.yml, jupyterhub-service.yml] resources: [jupyterhub-ingress.yml, jupyterhub-service.yml, jupyterhub-cert-issuer.yaml]
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization

View file

@ -1,23 +1,20 @@
---
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
name: jupyterhub-ingress name: jupyterhub-ingress
annotations: annotations:
kubernetes.io/ingress.class: traefik kubernetes.io/ingress.class: nginx
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
defaultBackend: defaultBackend:
service: service:
name: proxy-public name: proxy-public
port: port:
number: 8443 number: 80
ingressClassName: nginx
tls: tls:
- hosts: - hosts:
- vr-jupyter.drive.sunet.se - vr-jupyter.drive.sunet.se
secretName: prod-tls-secret secretName: prod-tls-secret
rules: rules:
- host: vr-jupyter.drive.sunet.se - host: vr-jupyter.drive.sunet.se
http: http:

View file

@ -0,0 +1,33 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jupyterhub-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
ingressClassName: nginx
defaultBackend:
service:
name: proxy-public
port:
number: 80
tls:
- hosts:
- sunet-jupyter.drive.sunet.se
- sunet-kube.drive.sunet.se
secretName: tls-secret
rules:
- host: sunet-jupyter.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: proxy-public
port:
number: 80

View file

@ -5,16 +5,15 @@ items:
kind: Service kind: Service
metadata: metadata:
labels: labels:
app: layer1-gu-port-doris app: jupyterhub-node
name: layer1-gu-port-doris name: jupyterhub-node
namespace: helmrds
spec: spec:
ports: ports:
- port: 80 - port: 8080
protocol: TCP protocol: TCP
targetPort: 8080 targetPort: 8080
selector: selector:
app: layer1-gu-port-doris app: jupyterhub-node
sessionAffinity: None sessionAffinity: None
type: ClusterIP type: ClusterIP
status: status:

View file

@ -0,0 +1,16 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base/]
helmCharts:
- includeCRDs: true
name: jupyterhub
releaseName: sunet-jupyterhub
valuesFile: ./values/values.yaml
version: 3.2.1
namespace: sunet-jupyterhub
helmGlobals:
chartHome: ../../../base/charts/
patches:
- path: jupyterhub-ingress.yml
- path: jupyterhub-service.yml

View file

@ -0,0 +1,337 @@
debug:
enabled: true
hub:
config:
Authenticator:
auto_login: true
enable_auth_state: true
JupyterHub:
tornado_settings:
headers: { 'Content-Security-Policy': "frame-ancestors *;" }
db:
pvc:
storageClassName: csi-sc-cinderplugin
extraConfig:
oauthCode: |
import time
import requests
from datetime import datetime
from oauthenticator.generic import GenericOAuthenticator
token_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/api/v1/token'
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
def get_nextcloud_access_token(refresh_token):
client_id = os.environ['NEXTCLOUD_CLIENT_ID']
client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
code = refresh_token
data = {
'grant_type': 'refresh_token',
'code': code,
'refresh_token': refresh_token,
'client_id': client_id,
'client_secret': client_secret
}
response = requests.post(token_url, data=data)
if debug:
print(response.text)
return response.json()
def post_auth_hook(authenticator, handler, authentication):
user = authentication['auth_state']['oauth_user']['ocs']['data']['id']
auth_state = authentication['auth_state']
auth_state['token_expires'] = time.time() + auth_state['token_response']['expires_in']
authentication['auth_state'] = auth_state
return authentication
class NextcloudOAuthenticator(GenericOAuthenticator):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_dict = {}
async def pre_spawn_start(self, user, spawner):
super().pre_spawn_start(user, spawner)
auth_state = await user.get_auth_state()
if not auth_state:
return
access_token = auth_state['access_token']
spawner.environment['NEXTCLOUD_ACCESS_TOKEN'] = access_token
async def refresh_user(self, user, handler=None):
auth_state = await user.get_auth_state()
if not auth_state:
if debug:
print(f'auth_state missing for {user}')
return False
access_token = auth_state['access_token']
refresh_token = auth_state['refresh_token']
token_response = auth_state['token_response']
now = time.time()
now_hr = datetime.fromtimestamp(now)
expires = auth_state['token_expires']
expires_hr = datetime.fromtimestamp(expires)
expires = 0
if debug:
print(f'auth_state for {user}: {auth_state}')
if now >= expires:
if debug:
print(f'Time is: {now_hr}, token expired: {expires_hr}')
print(f'Refreshing token for {user}')
try:
token_response = get_nextcloud_access_token(refresh_token)
auth_state['access_token'] = token_response['access_token']
auth_state['refresh_token'] = token_response['refresh_token']
auth_state['token_expires'] = now + token_response['expires_in']
auth_state['token_response'] = token_response
if debug:
print(f'Successfully refreshed token for {user.name}')
print(f'auth_state for {user.name}: {auth_state}')
return {'name': user.name, 'auth_state': auth_state}
except Exception as e:
if debug:
print(f'Failed to refresh token for {user}')
return False
return False
if debug:
print(f'Time is: {now_hr}, token expires: {expires_hr}')
return True
c.JupyterHub.authenticator_class = NextcloudOAuthenticator
c.NextcloudOAuthenticator.client_id = os.environ['NEXTCLOUD_CLIENT_ID']
c.NextcloudOAuthenticator.client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
c.NextcloudOAuthenticator.login_service = 'Sunet Drive'
c.NextcloudOAuthenticator.username_claim = lambda r: r.get('ocs', {}).get('data', {}).get('id')
c.NextcloudOAuthenticator.userdata_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/ocs/v2.php/cloud/user?format=json'
c.NextcloudOAuthenticator.authorize_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/authorize'
c.NextcloudOAuthenticator.token_url = token_url
c.NextcloudOAuthenticator.oauth_callback_url = 'https://' + os.environ['JUPYTER_HOST'] + '/hub/oauth_callback'
c.NextcloudOAuthenticator.allow_all = True
c.NextcloudOAuthenticator.refresh_pre_spawn = True
c.NextcloudOAuthenticator.enable_auth_state = True
c.NextcloudOAuthenticator.auth_refresh_age = 3600
c.NextcloudOAuthenticator.post_auth_hook = post_auth_hook
serviceCode: |
import sys
c.JupyterHub.load_roles = [
{
"name": "refresh-token",
"services": [
"refresh-token"
],
"scopes": [
"read:users",
"admin:auth_state"
]
},
{
"name": "user",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"self",
],
},
{
"name": "server",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"inherit",
],
}
]
c.JupyterHub.services = [
{
'name': 'refresh-token',
'url': 'http://' + os.environ.get('HUB_SERVICE_HOST', 'hub') + ':' + os.environ.get('HUB_SERVICE_PORT_REFRESH_TOKEN', '8082'),
'display': False,
'oauth_no_confirm': True,
'api_token': os.environ['JUPYTERHUB_API_KEY'],
'command': [sys.executable, '/usr/local/etc/jupyterhub/refresh-token.py']
}
]
c.JupyterHub.admin_users = {"refresh-token"}
c.JupyterHub.api_tokens = {
os.environ['JUPYTERHUB_API_KEY']: "refresh-token",
}
extraFiles:
refresh-token.py:
mountPath: /usr/local/etc/jupyterhub/refresh-token.py
stringData: |
"""A token refresh service authenticating with the Hub.
This service serves `/services/refresh-token/`,
authenticated with the Hub,
showing the user their own info.
"""
import json
import os
import requests
import socket
from jupyterhub.services.auth import HubAuthenticated
from jupyterhub.utils import url_path_join
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application, HTTPError, RequestHandler, authenticated
from urllib.parse import urlparse
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
def my_debug(s):
if debug:
with open("/proc/1/fd/1", "a") as stdout:
print(s, file=stdout)
class RefreshHandler(HubAuthenticated, RequestHandler):
def api_request(self, method, url, **kwargs):
my_debug(f'{self.hub_auth}')
url = url_path_join(self.hub_auth.api_url, url)
allow_404 = kwargs.pop('allow_404', False)
headers = kwargs.setdefault('headers', {})
headers.setdefault('Authorization', f'token {self.hub_auth.api_token}')
try:
r = requests.request(method, url, **kwargs)
except requests.ConnectionError as e:
my_debug(f'Error connecting to {url}: {e}')
msg = f'Failed to connect to Hub API at {url}.'
msg += f' Is the Hub accessible at this URL (from host: {socket.gethostname()})?'
if '127.0.0.1' in url:
msg += ' Make sure to set c.JupyterHub.hub_ip to an IP accessible to' + \
' single-user servers if the servers are not on the same host as the Hub.'
raise HTTPError(500, msg)
data = None
if r.status_code == 404 and allow_404:
pass
elif r.status_code == 403:
my_debug(
'Lacking permission to check authorization with JupyterHub,' +
f' my auth token may have expired: [{r.status_code}] {r.reason}'
)
my_debug(r.text)
raise HTTPError(
500,
'Permission failure checking authorization, I may need a new token'
)
elif r.status_code >= 500:
my_debug(f'Upstream failure verifying auth token: [{r.status_code}] {r.reason}')
my_debug(r.text)
raise HTTPError(
502, 'Failed to check authorization (upstream problem)')
elif r.status_code >= 400:
my_debug(f'Failed to check authorization: [{r.status_code}] {r.reason}')
my_debug(r.text)
raise HTTPError(500, 'Failed to check authorization')
else:
data = r.json()
return data
@authenticated
def get(self):
user_model = self.get_current_user()
# Fetch current auth state
user_data = self.api_request('GET', url_path_join('users', user_model['name']))
auth_state = user_data['auth_state']
access_token = auth_state['access_token']
token_expires = auth_state['token_expires']
self.set_header('content-type', 'application/json')
self.write(json.dumps({'access_token': access_token, 'token_expires': token_expires}, indent=1, sort_keys=True))
class PingHandler(RequestHandler):
def get(self):
my_debug(f"DEBUG: In ping get")
self.set_header('content-type', 'application/json')
self.write(json.dumps({'ping': 1}))
def main():
app = Application([
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + 'tokens', RefreshHandler),
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + '/?', PingHandler),
])
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port)
IOLoop.current().start()
if __name__ == '__main__':
main()
networkPolicy:
ingress:
- ports:
- port: 8082
from:
- podSelector:
matchLabels:
hub.jupyter.org/network-access-hub: "true"
service:
extraPorts:
- port: 8082
targetPort: 8082
name: refresh-token
extraEnv:
NEXTCLOUD_DEBUG_OAUTH: "no"
NEXTCLOUD_HOST: sunet.drive.sunet.se
JUPYTER_HOST: sunet-jupyter.drive.sunet.se
JUPYTERHUB_API_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: api-key
JUPYTERHUB_CRYPT_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: crypt-key
NEXTCLOUD_CLIENT_ID:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-id
NEXTCLOUD_CLIENT_SECRET:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-secret
networkPolicy:
enabled: false
proxy:
chp:
networkPolicy:
egress:
- to:
- podSelector:
matchLabels:
app: jupyterhub
component: hub
ports:
- port: 8082
singleuser:
image:
name: docker.sunet.se/drive/jupyter-custom
tag: lab-4.0.10-sunet5
storage:
dynamic:
storageClass: csi-sc-cinderplugin
extraEnv:
JUPYTER_ENABLE_LAB: "yes"
JUPYTER_HOST: sunet-jupyter.drive.sunet.se
NEXTCLOUD_HOST: sunet.drive.sunet.se
extraFiles:
jupyter_notebook_config:
mountPath: /home/jovyan/.jupyter/jupyter_server_config.py
stringData: |
import os
c = get_config()
c.NotebookApp.allow_origin = '*'
c.NotebookApp.tornado_settings = {
'headers': { 'Content-Security-Policy': "frame-ancestors *;" }
}
os.system('/usr/local/bin/nc-sync')
mode: 0644

View file

@ -0,0 +1,30 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jupyterhub-ingress
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: proxy-public
port:
number: 8443
tls:
- hosts:
- vr-jupyter.drive.sunet.se
secretName: tls-secret
ingressClassName: nginx
rules:
- host: vr-jupyter.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: proxy-public
port:
number: 80

View file

@ -0,0 +1,25 @@
---
apiVersion: v1
items:
- apiVersion: v1
kind: Service
metadata:
labels:
app: jupyterhub-node
name: jupyterhub-node
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: jupyterhub-node
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
kind: List
metadata:
resourceVersion: ""
selfLink: ""

View file

@ -0,0 +1,16 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base/]
helmCharts:
- includeCRDs: true
name: jupyterhub
releaseName: vr-jupyterhub
valuesFile: ./values/values.yaml
version: 3.2.1
namespace: vr-jupyterhub
helmGlobals:
chartHome: ../../../base/charts/
patches:
- path: jupyterhub-ingress.yml
- path: jupyterhub-service.yml

View file

@ -0,0 +1,337 @@
debug:
enabled: true
hub:
config:
Authenticator:
auto_login: true
enable_auth_state: true
JupyterHub:
tornado_settings:
headers: { 'Content-Security-Policy': "frame-ancestors *;" }
db:
pvc:
storageClassName: csi-sc-cinderplugin
extraConfig:
oauthCode: |
import time
import requests
from datetime import datetime
from oauthenticator.generic import GenericOAuthenticator
token_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/api/v1/token'
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
def get_nextcloud_access_token(refresh_token):
client_id = os.environ['NEXTCLOUD_CLIENT_ID']
client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
code = refresh_token
data = {
'grant_type': 'refresh_token',
'code': code,
'refresh_token': refresh_token,
'client_id': client_id,
'client_secret': client_secret
}
response = requests.post(token_url, data=data)
if debug:
print(response.text)
return response.json()
def post_auth_hook(authenticator, handler, authentication):
user = authentication['auth_state']['oauth_user']['ocs']['data']['id']
auth_state = authentication['auth_state']
auth_state['token_expires'] = time.time() + auth_state['token_response']['expires_in']
authentication['auth_state'] = auth_state
return authentication
class NextcloudOAuthenticator(GenericOAuthenticator):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_dict = {}
async def pre_spawn_start(self, user, spawner):
super().pre_spawn_start(user, spawner)
auth_state = await user.get_auth_state()
if not auth_state:
return
access_token = auth_state['access_token']
spawner.environment['NEXTCLOUD_ACCESS_TOKEN'] = access_token
async def refresh_user(self, user, handler=None):
auth_state = await user.get_auth_state()
if not auth_state:
if debug:
print(f'auth_state missing for {user}')
return False
access_token = auth_state['access_token']
refresh_token = auth_state['refresh_token']
token_response = auth_state['token_response']
now = time.time()
now_hr = datetime.fromtimestamp(now)
expires = auth_state['token_expires']
expires_hr = datetime.fromtimestamp(expires)
expires = 0
if debug:
print(f'auth_state for {user}: {auth_state}')
if now >= expires:
if debug:
print(f'Time is: {now_hr}, token expired: {expires_hr}')
print(f'Refreshing token for {user}')
try:
token_response = get_nextcloud_access_token(refresh_token)
auth_state['access_token'] = token_response['access_token']
auth_state['refresh_token'] = token_response['refresh_token']
auth_state['token_expires'] = now + token_response['expires_in']
auth_state['token_response'] = token_response
if debug:
print(f'Successfully refreshed token for {user.name}')
print(f'auth_state for {user.name}: {auth_state}')
return {'name': user.name, 'auth_state': auth_state}
except Exception as e:
if debug:
print(f'Failed to refresh token for {user}')
return False
return False
if debug:
print(f'Time is: {now_hr}, token expires: {expires_hr}')
return True
c.JupyterHub.authenticator_class = NextcloudOAuthenticator
c.NextcloudOAuthenticator.client_id = os.environ['NEXTCLOUD_CLIENT_ID']
c.NextcloudOAuthenticator.client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
c.NextcloudOAuthenticator.login_service = 'Sunet Drive'
c.NextcloudOAuthenticator.username_claim = lambda r: r.get('ocs', {}).get('data', {}).get('id')
c.NextcloudOAuthenticator.userdata_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/ocs/v2.php/cloud/user?format=json'
c.NextcloudOAuthenticator.authorize_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/authorize'
c.NextcloudOAuthenticator.token_url = token_url
c.NextcloudOAuthenticator.oauth_callback_url = 'https://' + os.environ['JUPYTER_HOST'] + '/hub/oauth_callback'
c.NextcloudOAuthenticator.allow_all = True
c.NextcloudOAuthenticator.refresh_pre_spawn = True
c.NextcloudOAuthenticator.enable_auth_state = True
c.NextcloudOAuthenticator.auth_refresh_age = 3600
c.NextcloudOAuthenticator.post_auth_hook = post_auth_hook
serviceCode: |
import sys
c.JupyterHub.load_roles = [
{
"name": "refresh-token",
"services": [
"refresh-token"
],
"scopes": [
"read:users",
"admin:auth_state"
]
},
{
"name": "user",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"self",
],
},
{
"name": "server",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"inherit",
],
}
]
c.JupyterHub.services = [
{
'name': 'refresh-token',
'url': 'http://' + os.environ.get('HUB_SERVICE_HOST', 'hub') + ':' + os.environ.get('HUB_SERVICE_PORT_REFRESH_TOKEN', '8082'),
'display': False,
'oauth_no_confirm': True,
'api_token': os.environ['JUPYTERHUB_API_KEY'],
'command': [sys.executable, '/usr/local/etc/jupyterhub/refresh-token.py']
}
]
c.JupyterHub.admin_users = {"refresh-token"}
c.JupyterHub.api_tokens = {
os.environ['JUPYTERHUB_API_KEY']: "refresh-token",
}
extraFiles:
refresh-token.py:
mountPath: /usr/local/etc/jupyterhub/refresh-token.py
stringData: |
"""A token refresh service authenticating with the Hub.
This service serves `/services/refresh-token/`,
authenticated with the Hub,
showing the user their own info.
"""
import json
import os
import requests
import socket
from jupyterhub.services.auth import HubAuthenticated
from jupyterhub.utils import url_path_join
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application, HTTPError, RequestHandler, authenticated
from urllib.parse import urlparse
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
def my_debug(s):
if debug:
with open("/proc/1/fd/1", "a") as stdout:
print(s, file=stdout)
class RefreshHandler(HubAuthenticated, RequestHandler):
def api_request(self, method, url, **kwargs):
my_debug(f'{self.hub_auth}')
url = url_path_join(self.hub_auth.api_url, url)
allow_404 = kwargs.pop('allow_404', False)
headers = kwargs.setdefault('headers', {})
headers.setdefault('Authorization', f'token {self.hub_auth.api_token}')
try:
r = requests.request(method, url, **kwargs)
except requests.ConnectionError as e:
my_debug(f'Error connecting to {url}: {e}')
msg = f'Failed to connect to Hub API at {url}.'
msg += f' Is the Hub accessible at this URL (from host: {socket.gethostname()})?'
if '127.0.0.1' in url:
msg += ' Make sure to set c.JupyterHub.hub_ip to an IP accessible to' + \
' single-user servers if the servers are not on the same host as the Hub.'
raise HTTPError(500, msg)
data = None
if r.status_code == 404 and allow_404:
pass
elif r.status_code == 403:
my_debug(
'Lacking permission to check authorization with JupyterHub,' +
f' my auth token may have expired: [{r.status_code}] {r.reason}'
)
my_debug(r.text)
raise HTTPError(
500,
'Permission failure checking authorization, I may need a new token'
)
elif r.status_code >= 500:
my_debug(f'Upstream failure verifying auth token: [{r.status_code}] {r.reason}')
my_debug(r.text)
raise HTTPError(
502, 'Failed to check authorization (upstream problem)')
elif r.status_code >= 400:
my_debug(f'Failed to check authorization: [{r.status_code}] {r.reason}')
my_debug(r.text)
raise HTTPError(500, 'Failed to check authorization')
else:
data = r.json()
return data
@authenticated
def get(self):
user_model = self.get_current_user()
# Fetch current auth state
user_data = self.api_request('GET', url_path_join('users', user_model['name']))
auth_state = user_data['auth_state']
access_token = auth_state['access_token']
token_expires = auth_state['token_expires']
self.set_header('content-type', 'application/json')
self.write(json.dumps({'access_token': access_token, 'token_expires': token_expires}, indent=1, sort_keys=True))
class PingHandler(RequestHandler):
def get(self):
my_debug(f"DEBUG: In ping get")
self.set_header('content-type', 'application/json')
self.write(json.dumps({'ping': 1}))
def main():
app = Application([
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + 'tokens', RefreshHandler),
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + '/?', PingHandler),
])
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port)
IOLoop.current().start()
if __name__ == '__main__':
main()
networkPolicy:
ingress:
- ports:
- port: 8082
from:
- podSelector:
matchLabels:
hub.jupyter.org/network-access-hub: "true"
service:
extraPorts:
- port: 8082
targetPort: 8082
name: refresh-token
extraEnv:
NEXTCLOUD_DEBUG_OAUTH: "no"
NEXTCLOUD_HOST: vr.drive.sunet.se
JUPYTER_HOST: vr-jupyter.drive.sunet.se
JUPYTERHUB_API_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: api-key
JUPYTERHUB_CRYPT_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: crypt-key
NEXTCLOUD_CLIENT_ID:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-id
NEXTCLOUD_CLIENT_SECRET:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-secret
networkPolicy:
enabled: false
proxy:
chp:
networkPolicy:
egress:
- to:
- podSelector:
matchLabels:
app: jupyterhub
component: hub
ports:
- port: 8082
singleuser:
image:
name: docker.sunet.se/drive/jupyter-custom
tag: lab-4.0.10-sunet4
storage:
dynamic:
storageClass: csi-sc-cinderplugin
extraEnv:
JUPYTER_ENABLE_LAB: "yes"
JUPYTER_HOST: vr-jupyter.drive.sunet.se
NEXTCLOUD_HOST: vr.drive.sunet.se
extraFiles:
jupyter_notebook_config:
mountPath: /home/jovyan/.jupyter/jupyter_server_config.py
stringData: |
import os
c = get_config()
c.NotebookApp.allow_origin = '*'
c.NotebookApp.tornado_settings = {
'headers': { 'Content-Security-Policy': "frame-ancestors *;" }
}
os.system('/usr/local/bin/nc-sync')
mode: 0644

View file

@ -5,6 +5,8 @@ metadata:
name: jupyterhub-ingress name: jupyterhub-ingress
annotations: annotations:
kubernetes.io/ingress.class: nginx kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec: spec:
ingressClassName: nginx ingressClassName: nginx
defaultBackend: defaultBackend:
@ -15,6 +17,7 @@ spec:
tls: tls:
- hosts: - hosts:
- sunet-jupyter.drive.test.sunet.se - sunet-jupyter.drive.test.sunet.se
- sunet-kube.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
rules: rules:

View file

@ -19,10 +19,12 @@ hub:
from oauthenticator.generic import GenericOAuthenticator from oauthenticator.generic import GenericOAuthenticator
token_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/api/v1/token' token_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/api/v1/token'
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes'] debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
os.environ['OAUTH2_TOKEN_URL'] = token_url
os.environ['OAUTH2_AUTHORIZE_URL'] = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/authorize'
def get_nextcloud_access_token(refresh_token): def get_nextcloud_access_token(refresh_token):
client_id = os.environ['NEXTCLOUD_CLIENT_ID'] client_id = os.environ['OAUTH2_CLIENT_ID']
client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET'] client_secret = os.environ['OAUTH2_CLIENT_SECRET']
code = refresh_token code = refresh_token
data = { data = {
@ -97,12 +99,12 @@ hub:
return True return True
c.JupyterHub.authenticator_class = NextcloudOAuthenticator c.JupyterHub.authenticator_class = NextcloudOAuthenticator
c.NextcloudOAuthenticator.client_id = os.environ['NEXTCLOUD_CLIENT_ID'] c.NextcloudOAuthenticator.client_id = os.environ['OAUTH2_CLIENT_ID']
c.NextcloudOAuthenticator.client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET'] c.NextcloudOAuthenticator.client_secret = os.environ['OAUTH2_CLIENT_SECRET']
c.NextcloudOAuthenticator.login_service = 'Sunet Drive' c.NextcloudOAuthenticator.login_service = 'Sunet Drive'
c.NextcloudOAuthenticator.username_claim = lambda r: r.get('ocs', {}).get('data', {}).get('id') c.NextcloudOAuthenticator.username_claim = 'kano@sunet.se' # lambda r: r.get('ocs', {}).get('data', {}).get('id')
c.NextcloudOAuthenticator.userdata_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/ocs/v2.php/cloud/user?format=json' c.NextcloudOAuthenticator.userdata_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/ocs/v2.php/cloud/user?format=json'
c.NextcloudOAuthenticator.authorize_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/authorize' c.NextcloudOAuthenticator.authorize_url = os.environ['OAUTH2_AUTHORIZE_URL']
c.NextcloudOAuthenticator.token_url = token_url c.NextcloudOAuthenticator.token_url = token_url
c.NextcloudOAuthenticator.oauth_callback_url = 'https://' + os.environ['JUPYTER_HOST'] + '/hub/oauth_callback' c.NextcloudOAuthenticator.oauth_callback_url = 'https://' + os.environ['JUPYTER_HOST'] + '/hub/oauth_callback'
c.NextcloudOAuthenticator.allow_all = True c.NextcloudOAuthenticator.allow_all = True
@ -276,7 +278,7 @@ hub:
targetPort: 8082 targetPort: 8082
name: refresh-token name: refresh-token
extraEnv: extraEnv:
NEXTCLOUD_DEBUG_OAUTH: "no" NEXTCLOUD_DEBUG_OAUTH: "yes"
NEXTCLOUD_HOST: sunet.drive.test.sunet.se NEXTCLOUD_HOST: sunet.drive.test.sunet.se
JUPYTER_HOST: sunet-jupyter.drive.test.sunet.se JUPYTER_HOST: sunet-jupyter.drive.test.sunet.se
JUPYTERHUB_API_KEY: JUPYTERHUB_API_KEY:
@ -289,12 +291,12 @@ hub:
secretKeyRef: secretKeyRef:
name: jupyterhub-secrets name: jupyterhub-secrets
key: crypt-key key: crypt-key
NEXTCLOUD_CLIENT_ID: OAUTH2_CLIENT_ID:
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: nextcloud-oauth-secrets name: nextcloud-oauth-secrets
key: client-id key: client-id
NEXTCLOUD_CLIENT_SECRET: OAUTH2_CLIENT_SECRET:
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: nextcloud-oauth-secrets name: nextcloud-oauth-secrets
@ -315,7 +317,7 @@ proxy:
singleuser: singleuser:
image: image:
name: docker.sunet.se/drive/jupyter-custom name: docker.sunet.se/drive/jupyter-custom
tag: lab-4.0.10-sunet5 tag: lab-4.0.10-sunet4
storage: storage:
dynamic: dynamic:
storageClass: csi-sc-cinderplugin storageClass: csi-sc-cinderplugin

View file

@ -0,0 +1,30 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jupyterhub-ingress
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: proxy-public
port:
number: 8443
tls:
- hosts:
- vr-jupyter.drive.test.sunet.se
secretName: tls-secret
ingressClassName: nginx
rules:
- host: vr-jupyter.drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: proxy-public
port:
number: 80

View file

@ -0,0 +1,24 @@
---
apiVersion: v1
items:
- apiVersion: v1
kind: Service
metadata:
labels:
app: jupyterhub-node
name: jupyterhub-node
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: jupyterhub-node
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
kind: List
metadata:
resourceVersion: ""
selfLink: ""

View file

@ -0,0 +1,16 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: [../../../base/]
helmCharts:
- includeCRDs: true
name: jupyterhub
releaseName: vr-jupyterhub
valuesFile: ./values/values.yaml
version: 3.2.1
namespace: vr-jupyterhub
helmGlobals:
chartHome: ../../../base/charts/
patches:
- path: jupyterhub-ingress.yml
- path: jupyterhub-service.yml

View file

@ -0,0 +1,337 @@
debug:
enabled: true
hub:
config:
Authenticator:
auto_login: true
enable_auth_state: true
JupyterHub:
tornado_settings:
headers: { 'Content-Security-Policy': "frame-ancestors *;" }
db:
pvc:
storageClassName: csi-sc-cinderplugin
extraConfig:
oauthCode: |
import time
import requests
from datetime import datetime
from oauthenticator.generic import GenericOAuthenticator
token_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/api/v1/token'
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
def get_nextcloud_access_token(refresh_token):
client_id = os.environ['NEXTCLOUD_CLIENT_ID']
client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
code = refresh_token
data = {
'grant_type': 'refresh_token',
'code': code,
'refresh_token': refresh_token,
'client_id': client_id,
'client_secret': client_secret
}
response = requests.post(token_url, data=data)
if debug:
print(response.text)
return response.json()
def post_auth_hook(authenticator, handler, authentication):
user = authentication['auth_state']['oauth_user']['ocs']['data']['id']
auth_state = authentication['auth_state']
auth_state['token_expires'] = time.time() + auth_state['token_response']['expires_in']
authentication['auth_state'] = auth_state
return authentication
class NextcloudOAuthenticator(GenericOAuthenticator):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_dict = {}
async def pre_spawn_start(self, user, spawner):
super().pre_spawn_start(user, spawner)
auth_state = await user.get_auth_state()
if not auth_state:
return
access_token = auth_state['access_token']
spawner.environment['NEXTCLOUD_ACCESS_TOKEN'] = access_token
async def refresh_user(self, user, handler=None):
auth_state = await user.get_auth_state()
if not auth_state:
if debug:
print(f'auth_state missing for {user}')
return False
access_token = auth_state['access_token']
refresh_token = auth_state['refresh_token']
token_response = auth_state['token_response']
now = time.time()
now_hr = datetime.fromtimestamp(now)
expires = auth_state['token_expires']
expires_hr = datetime.fromtimestamp(expires)
expires = 0
if debug:
print(f'auth_state for {user}: {auth_state}')
if now >= expires:
if debug:
print(f'Time is: {now_hr}, token expired: {expires_hr}')
print(f'Refreshing token for {user}')
try:
token_response = get_nextcloud_access_token(refresh_token)
auth_state['access_token'] = token_response['access_token']
auth_state['refresh_token'] = token_response['refresh_token']
auth_state['token_expires'] = now + token_response['expires_in']
auth_state['token_response'] = token_response
if debug:
print(f'Successfully refreshed token for {user.name}')
print(f'auth_state for {user.name}: {auth_state}')
return {'name': user.name, 'auth_state': auth_state}
except Exception as e:
if debug:
print(f'Failed to refresh token for {user}')
return False
return False
if debug:
print(f'Time is: {now_hr}, token expires: {expires_hr}')
return True
c.JupyterHub.authenticator_class = NextcloudOAuthenticator
c.NextcloudOAuthenticator.client_id = os.environ['NEXTCLOUD_CLIENT_ID']
c.NextcloudOAuthenticator.client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
c.NextcloudOAuthenticator.login_service = 'Sunet Drive'
c.NextcloudOAuthenticator.username_claim = lambda r: r.get('ocs', {}).get('data', {}).get('id')
c.NextcloudOAuthenticator.userdata_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/ocs/v2.php/cloud/user?format=json'
c.NextcloudOAuthenticator.authorize_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/authorize'
c.NextcloudOAuthenticator.token_url = token_url
c.NextcloudOAuthenticator.oauth_callback_url = 'https://' + os.environ['JUPYTER_HOST'] + '/hub/oauth_callback'
c.NextcloudOAuthenticator.allow_all = True
c.NextcloudOAuthenticator.refresh_pre_spawn = True
c.NextcloudOAuthenticator.enable_auth_state = True
c.NextcloudOAuthenticator.auth_refresh_age = 3600
c.NextcloudOAuthenticator.post_auth_hook = post_auth_hook
serviceCode: |
import sys
c.JupyterHub.load_roles = [
{
"name": "refresh-token",
"services": [
"refresh-token"
],
"scopes": [
"read:users",
"admin:auth_state"
]
},
{
"name": "user",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"self",
],
},
{
"name": "server",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"inherit",
],
}
]
c.JupyterHub.services = [
{
'name': 'refresh-token',
'url': 'http://' + os.environ.get('HUB_SERVICE_HOST', 'hub') + ':' + os.environ.get('HUB_SERVICE_PORT_REFRESH_TOKEN', '8082'),
'display': False,
'oauth_no_confirm': True,
'api_token': os.environ['JUPYTERHUB_API_KEY'],
'command': [sys.executable, '/usr/local/etc/jupyterhub/refresh-token.py']
}
]
c.JupyterHub.admin_users = {"refresh-token"}
c.JupyterHub.api_tokens = {
os.environ['JUPYTERHUB_API_KEY']: "refresh-token",
}
extraFiles:
refresh-token.py:
mountPath: /usr/local/etc/jupyterhub/refresh-token.py
stringData: |
"""A token refresh service authenticating with the Hub.
This service serves `/services/refresh-token/`,
authenticated with the Hub,
showing the user their own info.
"""
import json
import os
import requests
import socket
from jupyterhub.services.auth import HubAuthenticated
from jupyterhub.utils import url_path_join
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application, HTTPError, RequestHandler, authenticated
from urllib.parse import urlparse
debug = os.environ.get('NEXTCLOUD_DEBUG_OAUTH', 'false').lower() in ['true', '1', 'yes']
def my_debug(s):
if debug:
with open("/proc/1/fd/1", "a") as stdout:
print(s, file=stdout)
class RefreshHandler(HubAuthenticated, RequestHandler):
def api_request(self, method, url, **kwargs):
my_debug(f'{self.hub_auth}')
url = url_path_join(self.hub_auth.api_url, url)
allow_404 = kwargs.pop('allow_404', False)
headers = kwargs.setdefault('headers', {})
headers.setdefault('Authorization', f'token {self.hub_auth.api_token}')
try:
r = requests.request(method, url, **kwargs)
except requests.ConnectionError as e:
my_debug(f'Error connecting to {url}: {e}')
msg = f'Failed to connect to Hub API at {url}.'
msg += f' Is the Hub accessible at this URL (from host: {socket.gethostname()})?'
if '127.0.0.1' in url:
msg += ' Make sure to set c.JupyterHub.hub_ip to an IP accessible to' + \
' single-user servers if the servers are not on the same host as the Hub.'
raise HTTPError(500, msg)
data = None
if r.status_code == 404 and allow_404:
pass
elif r.status_code == 403:
my_debug(
'Lacking permission to check authorization with JupyterHub,' +
f' my auth token may have expired: [{r.status_code}] {r.reason}'
)
my_debug(r.text)
raise HTTPError(
500,
'Permission failure checking authorization, I may need a new token'
)
elif r.status_code >= 500:
my_debug(f'Upstream failure verifying auth token: [{r.status_code}] {r.reason}')
my_debug(r.text)
raise HTTPError(
502, 'Failed to check authorization (upstream problem)')
elif r.status_code >= 400:
my_debug(f'Failed to check authorization: [{r.status_code}] {r.reason}')
my_debug(r.text)
raise HTTPError(500, 'Failed to check authorization')
else:
data = r.json()
return data
@authenticated
def get(self):
user_model = self.get_current_user()
# Fetch current auth state
user_data = self.api_request('GET', url_path_join('users', user_model['name']))
auth_state = user_data['auth_state']
access_token = auth_state['access_token']
token_expires = auth_state['token_expires']
self.set_header('content-type', 'application/json')
self.write(json.dumps({'access_token': access_token, 'token_expires': token_expires}, indent=1, sort_keys=True))
class PingHandler(RequestHandler):
def get(self):
my_debug(f"DEBUG: In ping get")
self.set_header('content-type', 'application/json')
self.write(json.dumps({'ping': 1}))
def main():
app = Application([
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + 'tokens', RefreshHandler),
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + '/?', PingHandler),
])
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port)
IOLoop.current().start()
if __name__ == '__main__':
main()
networkPolicy:
ingress:
- ports:
- port: 8082
from:
- podSelector:
matchLabels:
hub.jupyter.org/network-access-hub: "true"
service:
extraPorts:
- port: 8082
targetPort: 8082
name: refresh-token
extraEnv:
NEXTCLOUD_DEBUG_OAUTH: "no"
NEXTCLOUD_HOST: vr.drive.test.sunet.se
JUPYTER_HOST: vr-jupyter.drive.test.sunet.se
JUPYTERHUB_API_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: api-key
JUPYTERHUB_CRYPT_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: crypt-key
NEXTCLOUD_CLIENT_ID:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-id
NEXTCLOUD_CLIENT_SECRET:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-secret
networkPolicy:
enabled: false
proxy:
chp:
networkPolicy:
egress:
- to:
- podSelector:
matchLabels:
app: jupyterhub
component: hub
ports:
- port: 8082
singleuser:
image:
name: docker.sunet.se/drive/jupyter-custom
tag: lab-4.0.10-sunet4
storage:
dynamic:
storageClass: csi-sc-cinderplugin
extraEnv:
JUPYTER_ENABLE_LAB: "yes"
JUPYTER_HOST: vr-jupyter.drive.test.sunet.se
NEXTCLOUD_HOST: vr.drive.test.sunet.se
extraFiles:
jupyter_notebook_config:
mountPath: /home/jovyan/.jupyter/jupyter_server_config.py
stringData: |
import os
c = get_config()
c.NotebookApp.allow_origin = '*'
c.NotebookApp.tornado_settings = {
'headers': { 'Content-Security-Policy': "frame-ancestors *;" }
}
os.system('/usr/local/bin/nc-sync')
mode: 0644

View file

@ -0,0 +1,30 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: drive-ingress
namespace: portal
annotations:
kubernetes.io/ingress.class: nginx
spec:
defaultBackend:
service:
name: portal-node
port:
number: 8080
tls:
- hosts:
- drive.test.sunet.se
secretName: drive-tls-secret
ingressClassName: nginx
rules:
- host: drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-node
port:
number: 8080

View file

@ -0,0 +1,9 @@
resources:
- drive-ingress.yml
- portal-cert-manager.yml
- portal-deployment.yml
- portal-ingress.yml
- portal-namespace.yml
- portal-service.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

View file

@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: drive@sunet.se
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx

View file

@ -0,0 +1,30 @@
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: portal-node
namespace: portal
creationTimestamp:
labels:
app: portal-node
spec:
replicas: 3
selector:
matchLabels:
app: portal-node
template:
metadata:
creationTimestamp:
labels:
app: portal-node
spec:
containers:
- name: portal
image: docker.sunet.se/drive/portal:0.1.2-3
imagePullPolicy: Always
resources: {}
env:
- name: DRIVE_DOMAIN
value: "drive.test.sunet.se"
strategy: {}
status: {}

View file

@ -0,0 +1,30 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal-ingress
namespace: portal
annotations:
kubernetes.io/ingress.class: nginx
spec:
defaultBackend:
service:
name: portal-node
port:
number: 8080
tls:
- hosts:
- portal.drive.test.sunet.se
secretName: tls-secret
ingressClassName: nginx
rules:
- host: portal.drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-node
port:
number: 8080

View file

@ -0,0 +1,8 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: portal
spec:
finalizers:
- kubernetes

View file

@ -0,0 +1,25 @@
---
apiVersion: v1
items:
- apiVersion: v1
kind: Service
metadata:
labels:
app: portal-node
name: portal-node
namespace: portal
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: portal-node
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
kind: List
metadata:
resourceVersion: ""
selfLink: ""

View file

@ -0,0 +1,32 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: drive-ingress
namespace: portal
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: portal-node
port:
number: 8080
ingressClassName: nginx
tls:
- hosts:
- drive.sunet.se
secretName: drive-tls-secret
rules:
- host: drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-node
port:
number: 8080

View file

@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: drive-ingress.yml
- path: portal-ingress.yml
- path: portal-deployment.yml

View file

@ -0,0 +1,27 @@
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: portal-node
namespace: portal
creationTimestamp:
labels:
app: portal-node
spec:
replicas: 3
selector:
matchLabels:
app: portal-node
template:
metadata:
creationTimestamp:
labels:
app: portal-node
spec:
containers:
- name: portal
env:
- name: DRIVE_DOMAIN
value: "drive.sunet.se"
strategy: {}
status: {}

View file

@ -0,0 +1,32 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal-ingress
namespace: portal
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: portal-node
port:
number: 8080
ingressClassName: nginx
tls:
- hosts:
- portal.drive.sunet.se
secretName: tls-secret
rules:
- host: portal.drive.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-node
port:
number: 8080

View file

@ -0,0 +1,32 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: drive-ingress
namespace: portal
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: portal-node
port:
number: 8080
ingressClassName: nginx
tls:
- hosts:
- drive.test.sunet.se
secretName: drive-tls-secret
rules:
- host: drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-node
port:
number: 8080

View file

@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: drive-ingress.yml
- path: portal-ingress.yml
- path: portal-deployment.yml

View file

@ -0,0 +1,27 @@
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: portal-node
namespace: portal
creationTimestamp:
labels:
app: portal-node
spec:
replicas: 3
selector:
matchLabels:
app: portal-node
template:
metadata:
creationTimestamp:
labels:
app: portal-node
spec:
containers:
- name: portal
env:
- name: DRIVE_DOMAIN
value: "drive.test.sunet.se"
strategy: {}
status: {}

View file

@ -0,0 +1,32 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal-ingress
namespace: portal
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
defaultBackend:
service:
name: portal-node
port:
number: 8080
ingressClassName: nginx
tls:
- hosts:
- portal.drive.test.sunet.se
secretName: tls-secret
rules:
- host: portal.drive.test.sunet.se
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-node
port:
number: 8080

View file

@ -300,6 +300,13 @@ data:
transaction_persistent=1 transaction_persistent=1
active=1 active=1
}, },
{
username="nextcloud_richir"
password="{{RICHIR_PASSWORD}}"
default_hostgroup=10
transaction_persistent=1
active=1
},
{ {
username="nextcloud_rkh" username="nextcloud_rkh"
password="{{RKH_PASSWORD}}" password="{{RKH_PASSWORD}}"

View file

@ -247,6 +247,11 @@ spec:
secretKeyRef: secretKeyRef:
name: proxysql-secret name: proxysql-secret
key: "proxysql_oru_password" key: "proxysql_oru_password"
- name: RICHIR_PASSWORD
valueFrom:
secretKeyRef:
name: proxysql-secret
key: "proxysql_richir_password"
- name: RKH_PASSWORD - name: RKH_PASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:

View file

@ -19,35 +19,34 @@ spec:
spec: spec:
containers: containers:
- name: doris - name: doris
image: docker.sunet.se/rds/doris-rds:ci-RDS-Connectors-13 image: docker.sunet.se/rds/doris-rds:git-15de3c5b9
env: env:
- name: ASPNETCORE_ENVIRONMENT - name: Logging__LogLevel__Default
value: Development value: Debug
- name: ASPNETCORE_URLS - name: ScieboRds__ConnectorServiceName
value: http://+:80 value: layer1-port-doris
- name: Domain
value: sunet.se
- name: ScieboRds__TokenStorageUrl - name: ScieboRds__TokenStorageUrl
value: http://layer3-token-storage value: http://layer3-token-storage
- name: S3__Url - name: Doris__ApiKey
value: dummy
- name: ManifestIndex__Url
value: https://snd-storage-metadata-index-test-snd-dev.apps.k8s.gu.se
- name: ManifestIndex__ApiKey
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: doris-api-key name: doris-gu-secrets
key: "api-key" key: "api-key"
- name: S3__AccessKey - name: Doris__DorisApiEnabled
value: 'true'
- name: Doris__PrincipalDomain
value: gu.se
- name: Doris__ApiUrl
value: https://dev.snd.se/doris/api/rocrate
- name: NextCloud__BaseUrl
value: https://gu.drive.test.sunet.se
- name: NextCloud__User
value: _doris_datasets
- name: NextCloud__Password
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: doris-s3-key name: doris-gu-secret
key: "s3-key" key: "nextcloudpw"
- name: S3__SecretKey
valueFrom:
secretKeyRef:
name: doris-s3-secret
key: "s3-secret"
resources: {} resources: {}
strategy: {} strategy: {}
status: {} status: {}

View file

@ -1,49 +0,0 @@
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: layer1-gu-port-doris
namespace: helmrds
labels:
app: layer1-gu-port-doris
spec:
replicas: 1
selector:
matchLabels:
app: layer1-gu-port-doris
template:
metadata:
creationTimestamp:
labels:
app: layer1-gu-port-doris
spec:
containers:
- name: doris
image: docker.sunet.se/rds/doris-rds:git-15de3c5b9
env:
- name: ScieboRds__TokenStorageUrl
value: http://layer3-token-storage
- name: Doris__ApiKey
valueFrom:
secretKeyRef:
name: doris-gu-secrets
key: "api-key"
- name: Doris__DorisApiEnabled
value: true
- name: Doris__PrincipalDomain
value: gu.se
- name: Doris__ApiUrl
value: https://dev.snd.se/doris/api/rocrate
- name: NextCloud__BaseUrl
value: https://gu.drive.test.sunet.se
- name: NextCloud__User
value: _doris_datasets
- name: NextCloud__Password
valueFrom:
secretKeyRef:
name: doris-gu-secret
key: "nextcloudpw"
resources: {}
strategy: {}
status: {}

View file

@ -12,7 +12,7 @@ items:
ports: ports:
- port: 80 - port: 80
protocol: TCP protocol: TCP
targetPort: 80 targetPort: 8080
selector: selector:
app: layer1-port-doris app: layer1-port-doris
sessionAffinity: None sessionAffinity: None

11
rds/base/gu-service.yml Normal file
View file

@ -0,0 +1,11 @@
---
apiVersion: v1
kind: Service
metadata:
name: gu-drive
namespace: helmrds
spec:
type: ExternalName
externalName: gu.drive.test.sunet.se
ports:
- port: 443

View file

@ -3,6 +3,7 @@ resources:
- doris-deployment.yml - doris-deployment.yml
- rds-ingress.yml - rds-ingress.yml
- sunet-service.yml - sunet-service.yml
- gu-service.yml
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization

View file

@ -64,11 +64,11 @@ layer0-web:
environment: environment:
SECRET_KEY: IAMLAYER0WEBSECRET SECRET_KEY: IAMLAYER0WEBSECRET
EMBED_MODE: true EMBED_MODE: true
layer1-port-doris: # layer1-port-doris:
enabled: false # enabled: false
environment: # environment:
DISPLAYNAME: Doris # DISPLAYNAME: Doris Connector
METADATA_PROFILE: './metadata_profile.json' # METADATA_PROFILE: './metadata_profile.json'
layer1-port-owncloud: layer1-port-owncloud:
enabled: true enabled: true
layer1-port-zenodo: layer1-port-zenodo:

View file

@ -5,9 +5,7 @@ metadata:
name: describo-ingress name: describo-ingress
namespace: helmrds namespace: helmrds
annotations: annotations:
kubernetes.io/ingress.class: traefik kubernetes.io/ingress.class: nginx
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
defaultBackend: defaultBackend:
service: service:
@ -18,7 +16,7 @@ spec:
- hosts: - hosts:
- describo.drive.test.sunet.se - describo.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
ingressClassName: nginx
rules: rules:
- host: describo.drive.test.sunet.se - host: describo.drive.test.sunet.se
http: http:

View file

@ -0,0 +1,11 @@
---
apiVersion: v1
kind: Service
metadata:
name: gu-drive
namespace: helmrds
spec:
type: ExternalName
externalName: gu.drive.test.sunet.se
ports:
- port: 443

View file

@ -6,3 +6,4 @@ patches:
- path: describo-ingress.yml - path: describo-ingress.yml
- path: rds-ingress.yml - path: rds-ingress.yml
- path: sunet-service.yml - path: sunet-service.yml
- path: gu-service.yml

View file

@ -5,9 +5,7 @@ metadata:
name: rds-ingress name: rds-ingress
namespace: helmrds namespace: helmrds
annotations: annotations:
kubernetes.io/ingress.class: traefik kubernetes.io/ingress.class: nginx
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
defaultBackend: defaultBackend:
service: service:
@ -18,7 +16,7 @@ spec:
- hosts: - hosts:
- rds.drive.test.sunet.se - rds.drive.test.sunet.se
secretName: tls-secret secretName: tls-secret
ingressClassName: nginx
rules: rules:
- host: rds.drive.test.sunet.se - host: rds.drive.test.sunet.se
http: http:

View file

@ -0,0 +1,38 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
ci/
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
# MacOS
.DS_Store
# helm-unittest
./tests
.debug
__snapshot__
# helm-docs
README.md.gotmpl

View file

@ -0,0 +1,11 @@
apiVersion: v2
appVersion: v1beta2-1.6.1-3.5.0
description: A Helm chart for Spark on Kubernetes operator
home: https://github.com/kubeflow/spark-operator
keywords:
- spark
maintainers:
- email: yuchaoran2011@gmail.com
name: yuchaoran2011
name: spark-operator
version: 1.4.2

View file

@ -0,0 +1,146 @@
# spark-operator
![Version: 1.4.2](https://img.shields.io/badge/Version-1.4.2-informational?style=flat-square) ![AppVersion: v1beta2-1.6.1-3.5.0](https://img.shields.io/badge/AppVersion-v1beta2--1.6.1--3.5.0-informational?style=flat-square)
A Helm chart for Spark on Kubernetes operator
**Homepage:** <https://github.com/kubeflow/spark-operator>
## Introduction
This chart bootstraps a [Kubernetes Operator for Apache Spark](https://github.com/kubeflow/spark-operator) deployment using the [Helm](https://helm.sh) package manager.
## Prerequisites
- Helm >= 3
- Kubernetes >= 1.16
## Previous Helm Chart
The previous `spark-operator` Helm chart hosted at [helm/charts](https://github.com/helm/charts) has been moved to this repository in accordance with the [Deprecation timeline](https://github.com/helm/charts#deprecation-timeline). Note that a few things have changed between this version and the old version:
- This repository **only** supports Helm chart installations using Helm 3+ since the `apiVersion` on the chart has been marked as `v2`.
- Previous versions of the Helm chart have not been migrated, and the version has been set to `1.0.0` at the onset. If you are looking for old versions of the chart, it's best to run `helm pull incubator/sparkoperator --version <your-version>` until you are ready to move to this repository's version.
- Several configuration properties have been changed, carefully review the [values](#values) section below to make sure you're aligned with the new values.
## Usage
### Add Helm Repo
```shell
helm repo add spark-operator https://kubeflow.github.io/spark-operator
helm repo update
```
See [helm repo](https://helm.sh/docs/helm/helm_repo) for command documentation.
### Install the chart
```shell
helm install [RELEASE_NAME] spark-operator/spark-operator
```
For example, if you want to create a release with name `spark-operator` in the `default` namespace:
```shell
helm install spark-operator spark-operator/spark-operator
```
Note that `helm` will fail to install if the namespace doesn't exist. Either create the namespace beforehand or pass the `--create-namespace` flag to the `helm install` command.
```shell
helm install spark-operator spark-operator/spark-operator \
--namespace spark-operator \
--create-namespace
```
See [helm install](https://helm.sh/docs/helm/helm_install) for command documentation.
### Upgrade the chart
```shell
helm upgrade [RELEASE_NAME] spark-operator/spark-operator [flags]
```
See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade) for command documentation.
### Uninstall the chart
```shell
helm uninstall [RELEASE_NAME]
```
This removes all the Kubernetes resources associated with the chart and deletes the release, except for the `crds`, those will have to be removed manually.
See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall) for command documentation.
## Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | Affinity for pod assignment |
| batchScheduler.enable | bool | `false` | Enable batch scheduler for spark jobs scheduling. If enabled, users can specify batch scheduler name in spark application |
| commonLabels | object | `{}` | Common labels to add to the resources |
| controllerThreads | int | `10` | Operator concurrency, higher values might increase memory usage |
| envFrom | list | `[]` | Pod environment variable sources |
| fullnameOverride | string | `""` | String to override release name |
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
| image.repository | string | `"docker.io/kubeflow/spark-operator"` | Image repository |
| image.tag | string | `""` | if set, override the image tag whose default is the chart appVersion. |
| imagePullSecrets | list | `[]` | Image pull secrets |
| ingressUrlFormat | string | `""` | Ingress URL format. Requires the UI service to be enabled by setting `uiService.enable` to true. |
| istio.enabled | bool | `false` | When using `istio`, spark jobs need to run without a sidecar to properly terminate |
| labelSelectorFilter | string | `""` | A comma-separated list of key=value, or key labels to filter resources during watch and list based on the specified labels. |
| leaderElection.lockName | string | `"spark-operator-lock"` | Leader election lock name. Ref: https://github.com/kubeflow/spark-operator/blob/master/docs/user-guide.md#enabling-leader-election-for-high-availability. |
| leaderElection.lockNamespace | string | `""` | Optionally store the lock in another namespace. Defaults to operator's namespace |
| logLevel | int | `2` | Set higher levels for more verbose logging |
| metrics.enable | bool | `true` | Enable prometheus metric scraping |
| metrics.endpoint | string | `"/metrics"` | Metrics serving endpoint |
| metrics.port | int | `10254` | Metrics port |
| metrics.portName | string | `"metrics"` | Metrics port name |
| metrics.prefix | string | `""` | Metric prefix, will be added to all exported metrics |
| nameOverride | string | `""` | String to partially override `spark-operator.fullname` template (will maintain the release name) |
| nodeSelector | object | `{}` | Node labels for pod assignment |
| podAnnotations | object | `{}` | Additional annotations to add to the pod |
| podLabels | object | `{}` | Additional labels to add to the pod |
| podMonitor | object | `{"enable":false,"jobLabel":"spark-operator-podmonitor","labels":{},"podMetricsEndpoint":{"interval":"5s","scheme":"http"}}` | Prometheus pod monitor for operator's pod. |
| podMonitor.enable | bool | `false` | If enabled, a pod monitor for operator's pod will be submitted. Note that prometheus metrics should be enabled as well. |
| podMonitor.jobLabel | string | `"spark-operator-podmonitor"` | The label to use to retrieve the job name from |
| podMonitor.labels | object | `{}` | Pod monitor labels |
| podMonitor.podMetricsEndpoint | object | `{"interval":"5s","scheme":"http"}` | Prometheus metrics endpoint properties. `metrics.portName` will be used as a port |
| podSecurityContext | object | `{}` | Pod security context |
| priorityClassName | string | `""` | A priority class to be used for running spark-operator pod. |
| rbac.annotations | object | `{}` | Optional annotations for rbac |
| rbac.create | bool | `false` | **DEPRECATED** use `createRole` and `createClusterRole` |
| rbac.createClusterRole | bool | `true` | Create and use RBAC `ClusterRole` resources |
| rbac.createRole | bool | `true` | Create and use RBAC `Role` resources |
| replicaCount | int | `1` | Desired number of pods, leaderElection will be enabled if this is greater than 1 |
| resourceQuotaEnforcement.enable | bool | `false` | Whether to enable the ResourceQuota enforcement for SparkApplication resources. Requires the webhook to be enabled by setting `webhook.enable` to true. Ref: https://github.com/kubeflow/spark-operator/blob/master/docs/user-guide.md#enabling-resource-quota-enforcement. |
| resources | object | `{}` | Pod resource requests and limits Note, that each job submission will spawn a JVM within the Spark Operator Pod using "/usr/local/openjdk-11/bin/java -Xmx128m". Kubernetes may kill these Java processes at will to enforce resource limits. When that happens, you will see the following error: 'failed to run spark-submit for SparkApplication [...]: signal: killed' - when this happens, you may want to increase memory limits. |
| resyncInterval | int | `30` | Operator resync interval. Note that the operator will respond to events (e.g. create, update) unrelated to this setting |
| securityContext | object | `{}` | Operator container security context |
| serviceAccounts.spark.annotations | object | `{}` | Optional annotations for the spark service account |
| serviceAccounts.spark.create | bool | `true` | Create a service account for spark apps |
| serviceAccounts.spark.name | string | `""` | Optional name for the spark service account |
| serviceAccounts.sparkoperator.annotations | object | `{}` | Optional annotations for the operator service account |
| serviceAccounts.sparkoperator.create | bool | `true` | Create a service account for the operator |
| serviceAccounts.sparkoperator.name | string | `""` | Optional name for the operator service account |
| sidecars | list | `[]` | Sidecar containers |
| sparkJobNamespaces | list | `[""]` | List of namespaces where to run spark jobs |
| tolerations | list | `[]` | List of node taints to tolerate |
| uiService.enable | bool | `true` | Enable UI service creation for Spark application |
| volumeMounts | list | `[]` | |
| volumes | list | `[]` | |
| webhook.enable | bool | `false` | Enable webhook server |
| webhook.namespaceSelector | string | `""` | The webhook server will only operate on namespaces with this label, specified in the form key1=value1,key2=value2. Empty string (default) will operate on all namespaces |
| webhook.objectSelector | string | `""` | The webhook will only operate on resources with this label/s, specified in the form key1=value1,key2=value2, OR key in (value1,value2). Empty string (default) will operate on all objects |
| webhook.port | int | `8080` | Webhook service port |
| webhook.portName | string | `"webhook"` | Webhook container port name and service target port name |
| webhook.timeout | int | `30` | The annotations applied to init job, required to restore certs deleted by the cleanup job during upgrade |
## Maintainers
| Name | Email | Url |
| ---- | ------ | --- |
| yuchaoran2011 | <yuchaoran2011@gmail.com> | |

Some files were not shown because too many files have changed in this diff Show more