Compare commits
173 commits
mandersson
...
main
Author | SHA1 | Date | |
---|---|---|---|
3a7706fcf7 | |||
d5bad300ba | |||
f97d835cbf | |||
f52102c642 | |||
d55157ab68 | |||
3998b7417a | |||
1d60bac661 | |||
a260fed464 | |||
75153298db | |||
f01ec30d64 | |||
311cadd280 | |||
e0f94b308e | |||
93ce560985 | |||
02a7ac8d5c | |||
c31722a50e | |||
d80e9a65b6 | |||
c9ad7d7bab | |||
0a43f3965e | |||
3e43c4dfb8 | |||
9de204737a | |||
030de7dd64 | |||
a1e5cce33e | |||
fb2e06cc64 | |||
fa413ff7ee | |||
3622887a3e | |||
e22ad6faf9 | |||
330e9c22d3 | |||
3d8a5443e9 | |||
d4839fe725 | |||
7b196bb081 | |||
d4b6326c54 | |||
9af09cc676 | |||
5f456ba249 | |||
f4ce5010eb | |||
238a4098f5 | |||
0b22d32221 | |||
a76d5f1292 | |||
5cb51541e0 | |||
acf1971976 | |||
05e94f10f0 | |||
d054334edd | |||
a82ca5eb11 | |||
7fc4893396 | |||
9ef35ee859 | |||
b99be7ecc3 | |||
814bf644a9 | |||
368a6021fe | |||
790480f443 | |||
1ed7aec45f | |||
fc0a70edf7 | |||
558c0fc882 | |||
b5f529ffbd | |||
3a2f65a6eb | |||
edd32217d3 | |||
876b07bd0a | |||
675dc269c3 | |||
236a4bcc87 | |||
520f8f0861 | |||
98a2939475 | |||
0a6f1bd02a | |||
48e8fdd512 | |||
618452c1d3 | |||
e5ccfe8ce0 | |||
87c38bb9f3 | |||
31169707e7 | |||
b20951f12b | |||
fcafe5502c | |||
427be9456b | |||
8a294a768e | |||
b0449a0e25 | |||
6f66eda86d | |||
7686d8f4c5 | |||
b8d95b6104 | |||
b2f5515024 | |||
e20aaee976 | |||
fbb960b64b | |||
6d1c4f6562 | |||
8fd92bea74 | |||
ecbf71e0f1 | |||
f8977d44cf | |||
36ebac5ec1 | |||
15757c0383 | |||
8992dcec17 | |||
7c8db87856 | |||
b4da89ff87 | |||
561ee6a29f | |||
50d2d1047c | |||
21401f0490 | |||
b7638d9a12 | |||
8f97f3f839 | |||
238621e2d7 | |||
bb2755d031 | |||
d749ed838e | |||
1c082c4c32 | |||
4f519b3399 | |||
5785023ff1 | |||
1fe4a77fee | |||
57df5e7aa8 | |||
6a93585dbf | |||
04e4fbc0c8 | |||
fa259a2d7c | |||
29d8638215 | |||
42e500e2cb | |||
f2a850278c | |||
8a9ede5c3a | |||
b706c72110 | |||
81262d2af1 | |||
32afc32ebb | |||
70c3f1537b | |||
0a505b59ff | |||
31388e392b | |||
2a2325e109 | |||
a69449ede1 | |||
874f216848 | |||
a6c7d4e2f0 | |||
a9cbc314bb | |||
0bb0636d61 | |||
325b05d352 | |||
43c368211e | |||
6f477d9c1b | |||
fca1f166e0 | |||
427e71606a | |||
cd9fbdf1d5 | |||
73db86588c | |||
aaae51d17b | |||
ff93521ac3 | |||
af6fdfd154 | |||
f0bb76f6aa | |||
343a09c93e | |||
ed27635841 | |||
6919487a06 | |||
cb22a0d919 | |||
f6f2047535 | |||
a589c1ed76 | |||
dfc0ed9d89 | |||
a9e3c68d28 | |||
544b99a843 | |||
0e7417ddee | |||
57d27855db | |||
39b411e3aa | |||
0609270a81 | |||
16da1df16b | |||
036ef590d2 | |||
e925058169 | |||
b09b0e3237 | |||
9f6220e1a7 | |||
79949532c7 | |||
da9a983596 | |||
e5c66613b3 | |||
923f67db76 | |||
85a55ec7a1 | |||
2bd544568e | |||
bfdc489cea | |||
8927c853ba | |||
4cbeee1a32 | |||
ab5b6a3e11 | |||
7eb3369a04 | |||
d9cd80d8b0 | |||
33c6a68cd6 | |||
3faace2b35 | |||
175741f8ef | |||
a19e4c71af | |||
944c114c40 | |||
9376178752 | |||
01a2c8d258 | |||
4d7c577c79 | |||
8f8c6704ea | |||
d7afb8190a | |||
f7085e1a72 | |||
58d973c5f2 | |||
5aebe67702 | |||
d250b8a654 | |||
7cf1e79698 |
131 changed files with 13739 additions and 854 deletions
45
applicationsets/applicationset.yaml
Normal file
45
applicationsets/applicationset.yaml
Normal 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
|
15
argocd-nginx/base/argocd-cert-issuer.yaml
Normal file
15
argocd-nginx/base/argocd-cert-issuer.yaml
Normal 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
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
resources:
|
resources:
|
||||||
- argocd-ingress.yaml
|
- argocd-ingress.yaml
|
||||||
|
- argocd-cert-issuer.yaml
|
||||||
|
|
|
@ -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
|
||||||
|
|
30
argocd-nginx/overlays/prod/drive/argocd-ingress.yaml
Normal file
30
argocd-nginx/overlays/prod/drive/argocd-ingress.yaml
Normal 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
|
6
argocd-nginx/overlays/prod/drive/kustomization.yaml
Normal file
6
argocd-nginx/overlays/prod/drive/kustomization.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: [../../../base]
|
||||||
|
patches:
|
||||||
|
- path: argocd-ingress.yaml
|
30
argocd-nginx/overlays/prod/sunet/argocd-ingress.yaml
Normal file
30
argocd-nginx/overlays/prod/sunet/argocd-ingress.yaml
Normal 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
|
6
argocd-nginx/overlays/prod/sunet/kustomization.yaml
Normal file
6
argocd-nginx/overlays/prod/sunet/kustomization.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: [../../../base]
|
||||||
|
patches:
|
||||||
|
- path: argocd-ingress.yaml
|
30
argocd-nginx/overlays/prod/vr/argocd-ingress.yaml
Normal file
30
argocd-nginx/overlays/prod/vr/argocd-ingress.yaml
Normal 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
|
6
argocd-nginx/overlays/prod/vr/kustomization.yaml
Normal file
6
argocd-nginx/overlays/prod/vr/kustomization.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: [../../../base]
|
||||||
|
patches:
|
||||||
|
- path: argocd-ingress.yaml
|
30
argocd-nginx/overlays/test/drive/argocd-ingress.yaml
Normal file
30
argocd-nginx/overlays/test/drive/argocd-ingress.yaml
Normal 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
|
6
argocd-nginx/overlays/test/drive/kustomization.yaml
Normal file
6
argocd-nginx/overlays/test/drive/kustomization.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: [../../../base]
|
||||||
|
patches:
|
||||||
|
- path: argocd-ingress.yaml
|
|
@ -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
|
||||||
|
|
30
argocd-nginx/overlays/test/vr/argocd-ingress.yaml
Normal file
30
argocd-nginx/overlays/test/vr/argocd-ingress.yaml
Normal 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
|
6
argocd-nginx/overlays/test/vr/kustomization.yaml
Normal file
6
argocd-nginx/overlays/test/vr/kustomization.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: [../../../base]
|
||||||
|
patches:
|
||||||
|
- path: argocd-ingress.yaml
|
60
backups/base/backup-cronjob.yaml
Normal file
60
backups/base/backup-cronjob.yaml
Normal 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;"]
|
4
backups/base/kustomization.yaml
Normal file
4
backups/base/kustomization.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
kind: Kustomization
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
resources: ['backup-cronjob.yaml']
|
40
backups/overlays/test/xrootd/backup-cronjob.yaml
Normal file
40
backups/overlays/test/xrootd/backup-cronjob.yaml
Normal 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"
|
7
backups/overlays/test/xrootd/kustomization.yaml
Normal file
7
backups/overlays/test/xrootd/kustomization.yaml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
kind: Kustomization
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
resources: [../../../base]
|
||||||
|
patches:
|
||||||
|
- path: backup-cronjob.yaml
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -1,8 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: apcu-configmap
|
|
||||||
data:
|
|
||||||
apcu.ini: |
|
|
||||||
extension=apcu.so
|
|
||||||
apc.enable_cli=1
|
|
|
@ -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
|
|
26
customers/base/env-configmap.yml
Normal file
26
customers/base/env-configmap.yml
Normal 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'
|
73
customers/base/files/000-default.conf
Normal file
73
customers/base/files/000-default.conf
Normal 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
|
||||||
|
|
157
customers/base/files/apache-php.ini
Normal file
157
customers/base/files/apache-php.ini
Normal 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
|
||||||
|
|
3
customers/base/files/apcu.ini
Normal file
3
customers/base/files/apcu.ini
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
extension=apcu.so
|
||||||
|
apc.enable_cli=1
|
||||||
|
|
157
customers/base/files/cli-php.ini
Normal file
157
customers/base/files/cli-php.ini
Normal 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
|
||||||
|
|
107
customers/base/files/config.php
Normal file
107
customers/base/files/config.php
Normal 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}}',
|
||||||
|
);
|
||||||
|
|
14
customers/base/files/nc-upgrade
Normal file
14
customers/base/files/nc-upgrade
Normal 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
|
||||||
|
|
|
@ -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
|
||||||
|
|
15
customers/base/nextcloud-cert-issuer.yml
Normal file
15
customers/base/nextcloud-cert-issuer.yml
Normal 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
|
||||||
|
|
|
@ -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}}',
|
|
||||||
);
|
|
|
@ -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: {}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
|
10
customers/overlays/nordunet/test/env-configmap.yml
Normal file
10
customers/overlays/nordunet/test/env-configmap.yml
Normal 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'
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
10
customers/overlays/richir/test/env-configmap.yml
Normal file
10
customers/overlays/richir/test/env-configmap.yml
Normal 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'
|
8
customers/overlays/richir/test/kustomization.yaml
Normal file
8
customers/overlays/richir/test/kustomization.yaml
Normal 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
|
8
customers/overlays/richir/test/nextcloud-deployment.yml
Normal file
8
customers/overlays/richir/test/nextcloud-deployment.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
kind: StatefulSet
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: customer-node
|
||||||
|
labels:
|
||||||
|
app: customer-node
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
26
customers/overlays/richir/test/nextcloud-ingress.yml
Normal file
26
customers/overlays/richir/test/nextcloud-ingress.yml
Normal 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
|
10
customers/overlays/vinnova/test/env-configmap.yml
Normal file
10
customers/overlays/vinnova/test/env-configmap.yml
Normal 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'
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
30
health/overlays/sunet-prod/health-ingress.yml
Normal file
30
health/overlays/sunet-prod/health-ingress.yml
Normal 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
|
6
health/overlays/sunet-prod/kustomization.yaml
Normal file
6
health/overlays/sunet-prod/kustomization.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
patches:
|
||||||
|
- path: health-ingress.yml
|
15
jupyter/base/jupyterhub-cert-issuer.yaml
Normal file
15
jupyter/base/jupyterhub-cert-issuer.yaml
Normal 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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
33
jupyter/overlays/prod/sunet/jupyterhub-ingress.yml
Normal file
33
jupyter/overlays/prod/sunet/jupyterhub-ingress.yml
Normal 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
|
|
@ -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:
|
16
jupyter/overlays/prod/sunet/kustomization.yaml
Normal file
16
jupyter/overlays/prod/sunet/kustomization.yaml
Normal 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
|
337
jupyter/overlays/prod/sunet/values/values.yaml
Normal file
337
jupyter/overlays/prod/sunet/values/values.yaml
Normal 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
|
30
jupyter/overlays/prod/vr/jupyterhub-ingress.yml
Normal file
30
jupyter/overlays/prod/vr/jupyterhub-ingress.yml
Normal 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
|
25
jupyter/overlays/prod/vr/jupyterhub-service.yml
Normal file
25
jupyter/overlays/prod/vr/jupyterhub-service.yml
Normal 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: ""
|
||||||
|
|
16
jupyter/overlays/prod/vr/kustomization.yaml
Normal file
16
jupyter/overlays/prod/vr/kustomization.yaml
Normal 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
|
337
jupyter/overlays/prod/vr/values/values.yaml
Normal file
337
jupyter/overlays/prod/vr/values/values.yaml
Normal 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
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
30
jupyter/overlays/test/vr/jupyterhub-ingress.yml
Normal file
30
jupyter/overlays/test/vr/jupyterhub-ingress.yml
Normal 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
|
24
jupyter/overlays/test/vr/jupyterhub-service.yml
Normal file
24
jupyter/overlays/test/vr/jupyterhub-service.yml
Normal 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: ""
|
16
jupyter/overlays/test/vr/kustomization.yaml
Normal file
16
jupyter/overlays/test/vr/kustomization.yaml
Normal 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
|
337
jupyter/overlays/test/vr/values/values.yaml
Normal file
337
jupyter/overlays/test/vr/values/values.yaml
Normal 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
|
30
portal/base/drive-ingress.yml
Normal file
30
portal/base/drive-ingress.yml
Normal 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
|
9
portal/base/kustomization.yaml
Normal file
9
portal/base/kustomization.yaml
Normal 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
|
15
portal/base/portal-cert-manager.yml
Normal file
15
portal/base/portal-cert-manager.yml
Normal 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
|
||||||
|
|
30
portal/base/portal-deployment.yml
Normal file
30
portal/base/portal-deployment.yml
Normal 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: {}
|
30
portal/base/portal-ingress.yml
Normal file
30
portal/base/portal-ingress.yml
Normal 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
|
8
portal/base/portal-namespace.yml
Normal file
8
portal/base/portal-namespace.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: portal
|
||||||
|
spec:
|
||||||
|
finalizers:
|
||||||
|
- kubernetes
|
25
portal/base/portal-service.yml
Normal file
25
portal/base/portal-service.yml
Normal 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: ""
|
32
portal/overlays/prod/drive-ingress.yml
Normal file
32
portal/overlays/prod/drive-ingress.yml
Normal 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
|
8
portal/overlays/prod/kustomization.yaml
Normal file
8
portal/overlays/prod/kustomization.yaml
Normal 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
|
27
portal/overlays/prod/portal-deployment.yml
Normal file
27
portal/overlays/prod/portal-deployment.yml
Normal 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: {}
|
32
portal/overlays/prod/portal-ingress.yml
Normal file
32
portal/overlays/prod/portal-ingress.yml
Normal 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
|
32
portal/overlays/test/drive-ingress.yml
Normal file
32
portal/overlays/test/drive-ingress.yml
Normal 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
|
8
portal/overlays/test/kustomization.yaml
Normal file
8
portal/overlays/test/kustomization.yaml
Normal 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
|
27
portal/overlays/test/portal-deployment.yml
Normal file
27
portal/overlays/test/portal-deployment.yml
Normal 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: {}
|
32
portal/overlays/test/portal-ingress.yml
Normal file
32
portal/overlays/test/portal-ingress.yml
Normal 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
|
|
@ -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}}"
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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: {}
|
||||||
|
|
|
@ -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: {}
|
|
|
@ -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
11
rds/base/gu-service.yml
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
11
rds/overlays/test/gu-service.yml
Normal file
11
rds/overlays/test/gu-service.yml
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
38
spark/base/charts/spark-operator/.helmignore
Normal file
38
spark/base/charts/spark-operator/.helmignore
Normal 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
|
11
spark/base/charts/spark-operator/Chart.yaml
Normal file
11
spark/base/charts/spark-operator/Chart.yaml
Normal 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
|
146
spark/base/charts/spark-operator/README.md
Normal file
146
spark/base/charts/spark-operator/README.md
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
# spark-operator
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
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
Loading…
Add table
Reference in a new issue