generated from onedr0p/cluster-template
-
-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Helm chart jupyterhub to 4.0.0 #7631
Open
renovate
wants to merge
1
commit into
main
Choose a base branch
from
renovate/jupyterhub-4.x
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Signed-off-by: Zee Aslam <h3mmy@users.noreply.github.com>
bloopy-boi
bot
added
size/XS
Denotes a PR that changes 0-9 lines, ignoring generated files.
area/cluster
Changes made in the cluster directory
labels
Nov 7, 2024
Path: @@ -1,2215 +1 @@
----
-# Source: jupyterhub/templates/hub/netpol.yaml
-apiVersion: networking.k8s.io/v1
-kind: NetworkPolicy
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- podSelector:
- matchLabels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- policyTypes:
- - Ingress
- - Egress
- # IMPORTANT:
- # NetworkPolicy's ingress "from" and egress "to" rule specifications require
- # great attention to detail. A quick summary is:
- #
- # 1. You can provide "from"/"to" rules that provide access either ports or a
- # subset of ports.
- # 2. You can for each "from"/"to" rule provide any number of
- # "sources"/"destinations" of four different kinds.
- # - podSelector - targets pods with a certain label in the same namespace as the NetworkPolicy
- # - namespaceSelector - targets all pods running in namespaces with a certain label
- # - namespaceSelector and podSelector - targets pods with a certain label running in namespaces with a certain label
- # - ipBlock - targets network traffic from/to a set of IP address ranges
- #
- # Read more at: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
- #
- ingress:
- # allowed pods (hub.jupyter.org/network-access-hub) --> hub
- - ports:
- - port: http
- from:
- # source 1 - labeled pods
- - podSelector:
- matchLabels:
- hub.jupyter.org/network-access-hub: "true"
- egress:
- # hub --> proxy
- - to:
- - podSelector:
- matchLabels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8001
- # hub --> singleuser-server
- - to:
- - podSelector:
- matchLabels:
- component: singleuser-server
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8888
- # Allow outbound connections to the DNS port in the private IP ranges
- - ports:
- - protocol: UDP
- port: 53
- - protocol: TCP
- port: 53
- to:
- - ipBlock:
- cidr: 10.0.0.0/8
- - ipBlock:
- cidr: 172.16.0.0/12
- - ipBlock:
- cidr: 192.168.0.0/16
- # Allow outbound connections to non-private IP ranges
- - to:
- - ipBlock:
- cidr: 0.0.0.0/0
- except:
- # As part of this rule, don't:
- # - allow outbound connections to private IP
- - 10.0.0.0/8
- - 172.16.0.0/12
- - 192.168.0.0/16
- # - allow outbound connections to the cloud metadata server
- - 169.254.169.254/32
- # Allow outbound connections to private IP ranges
- - to:
- - ipBlock:
- cidr: 10.0.0.0/8
- - ipBlock:
- cidr: 172.16.0.0/12
- - ipBlock:
- cidr: 192.168.0.0/16
- # Allow outbound connections to the cloud metadata server
- - to:
- - ipBlock:
- cidr: 169.254.169.254/32
----
-# Source: jupyterhub/templates/proxy/netpol.yaml
-apiVersion: networking.k8s.io/v1
-kind: NetworkPolicy
-metadata:
- name: proxy
- labels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- podSelector:
- matchLabels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- policyTypes:
- - Ingress
- - Egress
- # IMPORTANT:
- # NetworkPolicy's ingress "from" and egress "to" rule specifications require
- # great attention to detail. A quick summary is:
- #
- # 1. You can provide "from"/"to" rules that provide access either ports or a
- # subset of ports.
- # 2. You can for each "from"/"to" rule provide any number of
- # "sources"/"destinations" of four different kinds.
- # - podSelector - targets pods with a certain label in the same namespace as the NetworkPolicy
- # - namespaceSelector - targets all pods running in namespaces with a certain label
- # - namespaceSelector and podSelector - targets pods with a certain label running in namespaces with a certain label
- # - ipBlock - targets network traffic from/to a set of IP address ranges
- #
- # Read more at: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
- #
- ingress:
- # allow incoming traffic to these ports independent of source
- - ports:
- - port: http
- - port: https
- # allowed pods (hub.jupyter.org/network-access-proxy-http) --> proxy (http/https port)
- - ports:
- - port: http
- from:
- # source 1 - labeled pods
- - podSelector:
- matchLabels:
- hub.jupyter.org/network-access-proxy-http: "true"
- # allowed pods (hub.jupyter.org/network-access-proxy-api) --> proxy (api port)
- - ports:
- - port: api
- from:
- # source 1 - labeled pods
- - podSelector:
- matchLabels:
- hub.jupyter.org/network-access-proxy-api: "true"
- egress:
- # proxy --> hub
- - to:
- - podSelector:
- matchLabels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8081
- # proxy --> singleuser-server
- - to:
- - podSelector:
- matchLabels:
- component: singleuser-server
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8888
- # Allow outbound connections to the DNS port in the private IP ranges
- - ports:
- - protocol: UDP
- port: 53
- - protocol: TCP
- port: 53
- to:
- - ipBlock:
- cidr: 10.0.0.0/8
- - ipBlock:
- cidr: 172.16.0.0/12
- - ipBlock:
- cidr: 192.168.0.0/16
- # Allow outbound connections to non-private IP ranges
- - to:
- - ipBlock:
- cidr: 0.0.0.0/0
- except:
- # As part of this rule, don't:
- # - allow outbound connections to private IP
- - 10.0.0.0/8
- - 172.16.0.0/12
- - 192.168.0.0/16
- # - allow outbound connections to the cloud metadata server
- - 169.254.169.254/32
- # Allow outbound connections to private IP ranges
- - to:
- - ipBlock:
- cidr: 10.0.0.0/8
- - ipBlock:
- cidr: 172.16.0.0/12
- - ipBlock:
- cidr: 192.168.0.0/16
- # Allow outbound connections to the cloud metadata server
- - to:
- - ipBlock:
- cidr: 169.254.169.254/32
----
-# Source: jupyterhub/templates/singleuser/netpol.yaml
-apiVersion: networking.k8s.io/v1
-kind: NetworkPolicy
-metadata:
- name: singleuser
- labels:
- component: singleuser
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- podSelector:
- matchLabels:
- component: singleuser-server
- app: jupyterhub
- release: jupyterhub
- policyTypes:
- - Ingress
- - Egress
- # IMPORTANT:
- # NetworkPolicy's ingress "from" and egress "to" rule specifications require
- # great attention to detail. A quick summary is:
- #
- # 1. You can provide "from"/"to" rules that provide access either ports or a
- # subset of ports.
- # 2. You can for each "from"/"to" rule provide any number of
- # "sources"/"destinations" of four different kinds.
- # - podSelector - targets pods with a certain label in the same namespace as the NetworkPolicy
- # - namespaceSelector - targets all pods running in namespaces with a certain label
- # - namespaceSelector and podSelector - targets pods with a certain label running in namespaces with a certain label
- # - ipBlock - targets network traffic from/to a set of IP address ranges
- #
- # Read more at: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
- #
- ingress:
- # allowed pods (hub.jupyter.org/network-access-singleuser) --> singleuser-server
- - ports:
- - port: notebook-port
- from:
- # source 1 - labeled pods
- - podSelector:
- matchLabels:
- hub.jupyter.org/network-access-singleuser: "true"
- egress:
- # singleuser-server --> hub
- - to:
- - podSelector:
- matchLabels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8081
- # singleuser-server --> proxy
- # singleuser-server --> autohttps
- #
- # While not critical for core functionality, a user or library code may rely
- # on communicating with the proxy or autohttps pods via a k8s Service it can
- # detected from well known environment variables.
- #
- - to:
- - podSelector:
- matchLabels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8000
- - to:
- - podSelector:
- matchLabels:
- component: autohttps
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8080
- - port: 8443
- # Allow outbound connections to the DNS port in the private IP ranges
- - ports:
- - protocol: UDP
- port: 53
- - protocol: TCP
- port: 53
- to:
- - ipBlock:
- cidr: 10.0.0.0/8
- - ipBlock:
- cidr: 172.16.0.0/12
- - ipBlock:
- cidr: 192.168.0.0/16
- # Allow outbound connections to non-private IP ranges
- - to:
- - ipBlock:
- cidr: 0.0.0.0/0
- except:
- # As part of this rule, don't:
- # - allow outbound connections to private IP
- - 10.0.0.0/8
- - 172.16.0.0/12
- - 192.168.0.0/16
- # - allow outbound connections to the cloud metadata server
- - 169.254.169.254/32
----
-# Source: jupyterhub/templates/scheduling/user-placeholder/pdb.yaml
-apiVersion: policy/v1beta1
-kind: PodDisruptionBudget
-metadata:
- name: user-placeholder
- labels:
- component: user-placeholder
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- minAvailable: 0
- selector:
- matchLabels:
- component: user-placeholder
- app: jupyterhub
- release: jupyterhub
----
-# Source: jupyterhub/templates/scheduling/user-scheduler/pdb.yaml
-apiVersion: policy/v1beta1
-kind: PodDisruptionBudget
-metadata:
- name: user-scheduler
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- maxUnavailable: 1
- selector:
- matchLabels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
----
-# Source: jupyterhub/templates/hub/serviceaccount.yaml
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
----
-# Source: jupyterhub/templates/scheduling/user-scheduler/serviceaccount.yaml
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- name: user-scheduler
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
----
-# Source: jupyterhub/templates/hub/secret.yaml
-kind: Secret
-apiVersion: v1
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-type: Opaque
-data:
- values.yaml: "Q2hhcnQ6CiAgTmFtZToganVweXRlcmh1YgogIFZlcnNpb246IDIuMC4wClJlbGVhc2U6CiAgTmFtZToganVweXRlcmh1YgogIE5hbWVzcGFjZTogZGVmYXVsdAogIFNlcnZpY2U6IEhlbG0KY3VsbDoKICBhZG1pblVzZXJzOiB0cnVlCiAgY29uY3VycmVuY3k6IDEwCiAgZW5hYmxlZDogdHJ1ZQogIGV2ZXJ5OiA2MDAKICBtYXhBZ2U6IDAKICByZW1vdmVOYW1lZFNlcnZlcnM6IGZhbHNlCiAgdGltZW91dDogMzYwMAogIHVzZXJzOiBmYWxzZQpjdXN0b206IHt9CmRlYnVnOgogIGVuYWJsZWQ6IGZhbHNlCmZ1bGxuYW1lT3ZlcnJpZGU6ICIiCmdsb2JhbDoKICBzYWZlVG9TaG93VmFsdWVzOiBmYWxzZQpodWI6CiAgYWN0aXZlU2VydmVyTGltaXQ6IG51bGwKICBhbGxvd05hbWVkU2VydmVyczogZmFsc2UKICBhbm5vdGF0aW9uczoge30KICBhcmdzOiBbXQogIGF1dGhlbnRpY2F0ZVByb21ldGhldXM6IGZhbHNlCiAgYmFzZVVybDogLwogIGNvbW1hbmQ6IFtdCiAgY29uY3VycmVudFNwYXduTGltaXQ6IDY0CiAgY29uZmlnOgogICAgQXV0aGVudGljYXRvcjoKICAgICAgYWRtaW5fdXNlcnM6CiAgICAgIC0gJHtKSFVCX0FETUlOfQogICAgICAtICR7SkhVQl9BRE1JTjJ9CiAgICAgIC0gJHtKSFVCX0FETUlOM30KICAgIEdlbmVyaWNPQXV0aGVudGljYXRvcjoKICAgICAgYXV0aG9yaXplX3VybDogaHR0cHM6Ly9hdXRoLiR7WFlaX0RPTUFJTn0vYXBwbGljYXRpb24vby9hdXRob3JpemUvCiAgICAgIGNsaWVudF9pZDogJHtKSFVCX09BVVRIX0NMSUVOVF9JRH0KICAgICAgY2xpZW50X3NlY3JldDogJHtKSFVCX09BVVRIX0NMSUVOVF9TRUNSRVR9CiAgICAgIG9hdXRoX2NhbGxiYWNrX3VybDogaHR0cHM6Ly9qaHViLiR7WFlaX0RPTUFJTn0vaHViL29hdXRoX2NhbGxiYWNrCiAgICAgIHNjb3BlOgogICAgICAtIG9wZW5pZAogICAgICAtIHByb2ZpbGUKICAgICAgLSBlbWFpbAogICAgICB0b2tlbl91cmw6IGh0dHBzOi8vYXV0aC4ke1hZWl9ET01BSU59L2FwcGxpY2F0aW9uL28vdG9rZW4vCiAgICAgIHVzZXJkYXRhX3VybDogaHR0cHM6Ly9hdXRoLiR7WFlaX0RPTUFJTn0vYXBwbGljYXRpb24vby91c2VyaW5mby8KICAgICAgdXNlcm5hbWVfa2V5OiBwcmVmZXJyZWRfdXNlcm5hbWUKICAgIEp1cHl0ZXJIdWI6CiAgICAgIGFkbWluX2FjY2VzczogdHJ1ZQogICAgICBhdXRoZW50aWNhdG9yX2NsYXNzOiBnZW5lcmljLW9hdXRoCiAgY29uc2VjdXRpdmVGYWlsdXJlTGltaXQ6IDUKICBjb250YWluZXJTZWN1cml0eUNvbnRleHQ6CiAgICBhbGxvd1ByaXZpbGVnZUVzY2FsYXRpb246IGZhbHNlCiAgICBydW5Bc0dyb3VwOiAxMDAwCiAgICBydW5Bc1VzZXI6IDEwMDAKICBjb29raWVTZWNyZXQ6IG51bGwKICBkYjoKICAgIHBhc3N3b3JkOiBudWxsCiAgICBwdmM6CiAgICAgIGFjY2Vzc01vZGVzOgogICAgICAtIFJlYWRXcml0ZU9uY2UKICAgICAgYW5ub3RhdGlvbnM6IHt9CiAgICAgIHNlbGVjdG9yOiB7fQogICAgICBzdG9yYWdlOiAxR2kKICAgICAgc3RvcmFnZUNsYXNzTmFtZTogbnVsbAogICAgICBzdWJQYXRoOiBudWxsCiAgICB0eXBlOiBteXNxbAogICAgdXBncmFkZTogbnVsbAogICAgdXJsOiAke0pVUFlURVJfREJfVVJMfQogIGRlcGxveW1lbnRTdHJhdGVneToKICAgIHR5cGU6IFJlY3JlYXRlCiAgZXhpc3RpbmdTZWNyZXQ6IG51bGwKICBleHRyYUNvbmZpZzoge30KICBleHRyYUNvbnRhaW5lcnM6IFtdCiAgZXh0cmFFbnY6IHt9CiAgZXh0cmFGaWxlczoge30KICBleHRyYVBvZFNwZWM6IHt9CiAgZXh0cmFWb2x1bWVNb3VudHM6IFtdCiAgZXh0cmFWb2x1bWVzOiBbXQogIGltYWdlOgogICAgbmFtZToganVweXRlcmh1Yi9rOHMtaHViCiAgICBwdWxsUG9saWN5OiBudWxsCiAgICBwdWxsU2VjcmV0czogW10KICAgIHRhZzogMi4wLjAKICBpbml0Q29udGFpbmVyczogW10KICBsYWJlbHM6IHt9CiAgbGlmZWN5Y2xlOiB7fQogIGxpdmVuZXNzUHJvYmU6CiAgICBlbmFibGVkOiB0cnVlCiAgICBmYWlsdXJlVGhyZXNob2xkOiAzMAogICAgaW5pdGlhbERlbGF5U2Vjb25kczogMzAwCiAgICBwZXJpb2RTZWNvbmRzOiAxMAogICAgdGltZW91dFNlY29uZHM6IDMKICBsb2FkUm9sZXM6IHt9CiAgbmFtZWRTZXJ2ZXJMaW1pdFBlclVzZXI6IG51bGwKICBuZXR3b3JrUG9saWN5OgogICAgYWxsb3dlZEluZ3Jlc3NQb3J0czogW10KICAgIGVncmVzczogW10KICAgIGVncmVzc0FsbG93UnVsZXM6CiAgICAgIGNsb3VkTWV0YWRhdGFTZXJ2ZXI6IHRydWUKICAgICAgZG5zUG9ydHNQcml2YXRlSVBzOiB0cnVlCiAgICAgIG5vblByaXZhdGVJUHM6IHRydWUKICAgICAgcHJpdmF0ZUlQczogdHJ1ZQogICAgZW5hYmxlZDogdHJ1ZQogICAgaW5ncmVzczogW10KICAgIGludGVyTmFtZXNwYWNlQWNjZXNzTGFiZWxzOiBpZ25vcmUKICBub2RlU2VsZWN0b3I6CiAgICBrdWJlcm5ldGVzLmlvL2FyY2g6IGFtZDY0CiAgcGRiOgogICAgZW5hYmxlZDogZmFsc2UKICAgIG1heFVuYXZhaWxhYmxlOiBudWxsCiAgICBtaW5BdmFpbGFibGU6IDEKICBwb2RTZWN1cml0eUNvbnRleHQ6CiAgICBmc0dyb3VwOiAxMDAwCiAgcmVhZGluZXNzUHJvYmU6CiAgICBlbmFibGVkOiB0cnVlCiAgICBmYWlsdXJlVGhyZXNob2xkOiAxMDAwCiAgICBpbml0aWFsRGVsYXlTZWNvbmRzOiAwCiAgICBwZXJpb2RTZWNvbmRzOiAyCiAgICB0aW1lb3V0U2Vjb25kczogMQogIHJlZGlyZWN0VG9TZXJ2ZXI6IG51bGwKICByZXNvdXJjZXM6IHt9CiAgcmV2aXNpb25IaXN0b3J5TGltaXQ6IG51bGwKICBzZXJ2aWNlOgogICAgYW5ub3RhdGlvbnM6IHt9CiAgICBleHRyYVBvcnRzOiBbXQogICAgbG9hZEJhbGFuY2VySVA6IG51bGwKICAgIHBvcnRzOgogICAgICBub2RlUG9ydDogbnVsbAogICAgdHlwZTogQ2x1c3RlcklQCiAgc2VydmljZUFjY291bnQ6CiAgICBhbm5vdGF0aW9uczoge30KICAgIGNyZWF0ZTogdHJ1ZQogICAgbmFtZTogbnVsbAogIHNlcnZpY2VzOiB7fQogIHNodXRkb3duT25Mb2dvdXQ6IG51bGwKICB0ZW1wbGF0ZVBhdGhzOiBbXQogIHRlbXBsYXRlVmFyczoge30KICB0b2xlcmF0aW9uczogW10KaW1hZ2VQdWxsU2VjcmV0OgogIGF1dG9tYXRpY1JlZmVyZW5jZUluamVjdGlvbjogdHJ1ZQogIGNyZWF0ZTogZmFsc2UKICBlbWFpbDogbnVsbAogIHBhc3N3b3JkOiBudWxsCiAgcmVnaXN0cnk6IG51bGwKICB1c2VybmFtZTogbnVsbAppbWFnZVB1bGxTZWNyZXRzOiBbXQppbmdyZXNzOgogIGFubm90YXRpb25zOgogICAgY2VydC1tYW5hZ2VyLmlvL2NsdXN0ZXItaXNzdWVyOiBsZXRzZW5jcnlwdC1wcm9kdWN0aW9uCiAgICBoYWppbWFyaS5pby9hcHBOYW1lOiBqdXB5dGVyaHViCiAgICBoYWppbWFyaS5pby9lbmFibGU6ICJ0cnVlIgogICAgaGFqaW1hcmkuaW8vaWNvbjogY2hhcnQtc2NhdHRlci1wbG90CiAgICBoYWppbWFyaS5pby9pbnN0YW5jZTogYmxvb3AteHl6CiAgICBrdWJlcm5ldGVzLmlvL2luZ3Jlc3MuY2xhc3M6IHRyYWVmaWsKICAgIHRyYWVmaWsuaW5ncmVzcy5rdWJlcm5ldGVzLmlvL3JvdXRlci5lbnRyeXBvaW50czogd2Vic2VjdXJlCiAgICB0cmFlZmlrLmluZ3Jlc3Mua3ViZXJuZXRlcy5pby9yb3V0ZXIubWlkZGxld2FyZXM6IG5ldHdvcmtpbmctY2hhaW4tbm8tYXV0aEBrdWJlcm5ldGVzY3JkCiAgZW5hYmxlZDogdHJ1ZQogIGhvc3RzOgogIC0gamh1Yi4ke1hZWl9ET01BSU59CiAgaW5ncmVzc0NsYXNzTmFtZTogbnVsbAogIHBhdGhTdWZmaXg6IG51bGwKICBwYXRoVHlwZTogUHJlZml4CiAgdGxzOgogIC0gaG9zdHM6CiAgICAtIGpodWIuJHtYWVpfRE9NQUlOfQogICAgc2VjcmV0TmFtZTogdGxzLmpodWIKcHJlUHVsbGVyOgogIGFubm90YXRpb25zOiB7fQogIGNvbnRhaW5lclNlY3VyaXR5Q29udGV4dDoKICAgIGFsbG93UHJpdmlsZWdlRXNjYWxhdGlvbjogZmFsc2UKICAgIHJ1bkFzR3JvdXA6IDY1NTM0CiAgICBydW5Bc1VzZXI6IDY1NTM0CiAgY29udGludW91czoKICAgIGVuYWJsZWQ6IHRydWUKICBleHRyYUltYWdlczoge30KICBleHRyYVRvbGVyYXRpb25zOiBbXQogIGhvb2s6CiAgICBjb250YWluZXJTZWN1cml0eUNvbnRleHQ6CiAgICAgIGFsbG93UHJpdmlsZWdlRXNjYWxhdGlvbjogZmFsc2UKICAgICAgcnVuQXNHcm91cDogNjU1MzQKICAgICAgcnVuQXNVc2VyOiA2NTUzNAogICAgZW5hYmxlZDogdHJ1ZQogICAgaW1hZ2U6CiAgICAgIG5hbWU6IGp1cHl0ZXJodWIvazhzLWltYWdlLWF3YWl0ZXIKICAgICAgcHVsbFBvbGljeTogbnVsbAogICAgICBwdWxsU2VjcmV0czogW10KICAgICAgdGFnOiAyLjAuMAogICAgbm9kZVNlbGVjdG9yOgogICAgICBrdWJlcm5ldGVzLmlvL2FyY2g6IGFtZDY0CiAgICBwb2RTY2hlZHVsaW5nV2FpdER1cmF0aW9uOiAxMAogICAgcHVsbE9ubHlPbkNoYW5nZXM6IHRydWUKICAgIHJlc291cmNlczoge30KICAgIHNlcnZpY2VBY2NvdW50OgogICAgICBhbm5vdGF0aW9uczoge30KICAgICAgY3JlYXRlOiB0cnVlCiAgICAgIG5hbWU6IG51bGwKICAgIHRvbGVyYXRpb25zOiBbXQogIGxhYmVsczoge30KICBwYXVzZToKICAgIGNvbnRhaW5lclNlY3VyaXR5Q29udGV4dDoKICAgICAgYWxsb3dQcml2aWxlZ2VFc2NhbGF0aW9uOiBmYWxzZQogICAgICBydW5Bc0dyb3VwOiA2NTUzNAogICAgICBydW5Bc1VzZXI6IDY1NTM0CiAgICBpbWFnZToKICAgICAgbmFtZTogazhzLmdjci5pby9wYXVzZQogICAgICBwdWxsUG9saWN5OiBudWxsCiAgICAgIHB1bGxTZWNyZXRzOiBbXQogICAgICB0YWc6ICIzLjgiCiAgcHVsbFByb2ZpbGVMaXN0SW1hZ2VzOiB0cnVlCiAgcmVzb3VyY2VzOiB7fQogIHJldmlzaW9uSGlzdG9yeUxpbWl0OiBudWxsCnByb3h5OgogIGFubm90YXRpb25zOiB7fQogIGNocDoKICAgIGNvbnRhaW5lclNlY3VyaXR5Q29udGV4dDoKICAgICAgYWxsb3dQcml2aWxlZ2VFc2NhbGF0aW9uOiBmYWxzZQogICAgICBydW5Bc0dyb3VwOiA2NTUzNAogICAgICBydW5Bc1VzZXI6IDY1NTM0CiAgICBkZWZhdWx0VGFyZ2V0OiBudWxsCiAgICBlcnJvclRhcmdldDogbnVsbAogICAgZXh0cmFDb21tYW5kTGluZUZsYWdzOiBbXQogICAgZXh0cmFFbnY6IHt9CiAgICBleHRyYVBvZFNwZWM6IHt9CiAgICBpbWFnZToKICAgICAgbmFtZToganVweXRlcmh1Yi9jb25maWd1cmFibGUtaHR0cC1wcm94eQogICAgICBwdWxsUG9saWN5OiBudWxsCiAgICAgIHB1bGxTZWNyZXRzOiBbXQogICAgICB0YWc6IDQuNS4zCiAgICBsaXZlbmVzc1Byb2JlOgogICAgICBlbmFibGVkOiB0cnVlCiAgICAgIGZhaWx1cmVUaHJlc2hvbGQ6IDMwCiAgICAgIGluaXRpYWxEZWxheVNlY29uZHM6IDYwCiAgICAgIHBlcmlvZFNlY29uZHM6IDEwCiAgICAgIHRpbWVvdXRTZWNvbmRzOiAzCiAgICBuZXR3b3JrUG9saWN5OgogICAgICBhbGxvd2VkSW5ncmVzc1BvcnRzOgogICAgICAtIGh0dHAKICAgICAgLSBodHRwcwogICAgICBlZ3Jlc3M6IFtdCiAgICAgIGVncmVzc0FsbG93UnVsZXM6CiAgICAgICAgY2xvdWRNZXRhZGF0YVNlcnZlcjogdHJ1ZQogICAgICAgIGRuc1BvcnRzUHJpdmF0ZUlQczogdHJ1ZQogICAgICAgIG5vblByaXZhdGVJUHM6IHRydWUKICAgICAgICBwcml2YXRlSVBzOiB0cnVlCiAgICAgIGVuYWJsZWQ6IHRydWUKICAgICAgaW5ncmVzczogW10KICAgICAgaW50ZXJOYW1lc3BhY2VBY2Nlc3NMYWJlbHM6IGlnbm9yZQogICAgbm9kZVNlbGVjdG9yOiB7fQogICAgcGRiOgogICAgICBlbmFibGVkOiBmYWxzZQogICAgICBtYXhVbmF2YWlsYWJsZTogbnVsbAogICAgICBtaW5BdmFpbGFibGU6IDEKICAgIHJlYWRpbmVzc1Byb2JlOgogICAgICBlbmFibGVkOiB0cnVlCiAgICAgIGZhaWx1cmVUaHJlc2hvbGQ6IDEwMDAKICAgICAgaW5pdGlhbERlbGF5U2Vjb25kczogMAogICAgICBwZXJpb2RTZWNvbmRzOiAyCiAgICAgIHRpbWVvdXRTZWNvbmRzOiAxCiAgICByZXNvdXJjZXM6IHt9CiAgICByZXZpc2lvbkhpc3RvcnlMaW1pdDogbnVsbAogICAgdG9sZXJhdGlvbnM6IFtdCiAgZGVwbG95bWVudFN0cmF0ZWd5OgogICAgcm9sbGluZ1VwZGF0ZTogbnVsbAogICAgdHlwZTogUmVjcmVhdGUKICBodHRwczoKICAgIGVuYWJsZWQ6IGZhbHNlCiAgICBob3N0czogW10KICAgIGxldHNlbmNyeXB0OgogICAgICBhY21lU2VydmVyOiBodHRwczovL2FjbWUtdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvZGlyZWN0b3J5CiAgICAgIGNvbnRhY3RFbWFpbDogbnVsbAogICAgbWFudWFsOgogICAgICBjZXJ0OiBudWxsCiAgICAgIGtleTogbnVsbAogICAgc2VjcmV0OgogICAgICBjcnQ6IHRscy5jcnQKICAgICAga2V5OiB0bHMua2V5CiAgICAgIG5hbWU6IG51bGwKICAgIHR5cGU6IGxldHNlbmNyeXB0CiAgbGFiZWxzOiB7fQogIHNlY3JldFN5bmM6CiAgICBjb250YWluZXJTZWN1cml0eUNvbnRleHQ6CiAgICAgIGFsbG93UHJpdmlsZWdlRXNjYWxhdGlvbjogZmFsc2UKICAgICAgcnVuQXNHcm91cDogNjU1MzQKICAgICAgcnVuQXNVc2VyOiA2NTUzNAogICAgaW1hZ2U6CiAgICAgIG5hbWU6IGp1cHl0ZXJodWIvazhzLXNlY3JldC1zeW5jCiAgICAgIHB1bGxQb2xpY3k6IG51bGwKICAgICAgcHVsbFNlY3JldHM6IFtdCiAgICAgIHRhZzogMi4wLjAKICAgIHJlc291cmNlczoge30KICBzZWNyZXRUb2tlbjogbnVsbAogIHNlcnZpY2U6CiAgICBhbm5vdGF0aW9uczoge30KICAgIGRpc2FibGVIdHRwUG9ydDogZmFsc2UKICAgIGV4dHJhUG9ydHM6IFtdCiAgICBsYWJlbHM6IHt9CiAgICBsb2FkQmFsYW5jZXJJUDogbnVsbAogICAgbG9hZEJhbGFuY2VyU291cmNlUmFuZ2VzOiBbXQogICAgbm9kZVBvcnRzOgogICAgICBodHRwOiBudWxsCiAgICAgIGh0dHBzOiBudWxsCiAgICB0eXBlOiBMb2FkQmFsYW5jZXIKICB0cmFlZmlrOgogICAgY29udGFpbmVyU2VjdXJpdHlDb250ZXh0OgogICAgICBhbGxvd1ByaXZpbGVnZUVzY2FsYXRpb246IGZhbHNlCiAgICAgIHJ1bkFzR3JvdXA6IDY1NTM0CiAgICAgIHJ1bkFzVXNlcjogNjU1MzQKICAgIGV4dHJhRHluYW1pY0NvbmZpZzoge30KICAgIGV4dHJhRW52OiB7fQogICAgZXh0cmFJbml0Q29udGFpbmVyczogW10KICAgIGV4dHJhUG9kU3BlYzoge30KICAgIGV4dHJhUG9ydHM6IFtdCiAgICBleHRyYVN0YXRpY0NvbmZpZzoge30KICAgIGV4dHJhVm9sdW1lTW91bnRzOiBbXQogICAgZXh0cmFWb2x1bWVzOiBbXQogICAgaHN0czoKICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IGZhbHNlCiAgICAgIG1heEFnZTogMTU3MjQ4MDAKICAgICAgcHJlbG9hZDogZmFsc2UKICAgIGltYWdlOgogICAgICBuYW1lOiB0cmFlZmlrCiAgICAgIHB1bGxQb2xpY3k6IG51bGwKICAgICAgcHVsbFNlY3JldHM6IFtdCiAgICAgIHRhZzogdjIuOC40CiAgICBsYWJlbHM6IHt9CiAgICBuZXR3b3JrUG9saWN5OgogICAgICBhbGxvd2VkSW5ncmVzc1BvcnRzOgogICAgICAtIGh0dHAKICAgICAgLSBodHRwcwogICAgICBlZ3Jlc3M6IFtdCiAgICAgIGVncmVzc0FsbG93UnVsZXM6CiAgICAgICAgY2xvdWRNZXRhZGF0YVNlcnZlcjogdHJ1ZQogICAgICAgIGRuc1BvcnRzUHJpdmF0ZUlQczogdHJ1ZQogICAgICAgIG5vblByaXZhdGVJUHM6IHRydWUKICAgICAgICBwcml2YXRlSVBzOiB0cnVlCiAgICAgIGVuYWJsZWQ6IHRydWUKICAgICAgaW5ncmVzczogW10KICAgICAgaW50ZXJOYW1lc3BhY2VBY2Nlc3NMYWJlbHM6IGlnbm9yZQogICAgbm9kZVNlbGVjdG9yOiB7fQogICAgcGRiOgogICAgICBlbmFibGVkOiBmYWxzZQogICAgICBtYXhVbmF2YWlsYWJsZTogbnVsbAogICAgICBtaW5BdmFpbGFibGU6IDEKICAgIHJlc291cmNlczoge30KICAgIHJldmlzaW9uSGlzdG9yeUxpbWl0OiBudWxsCiAgICBzZXJ2aWNlQWNjb3VudDoKICAgICAgYW5ub3RhdGlvbnM6IHt9CiAgICAgIGNyZWF0ZTogdHJ1ZQogICAgICBuYW1lOiBudWxsCiAgICB0b2xlcmF0aW9uczogW10KcmJhYzoKICBjcmVhdGU6IHRydWUKc2NoZWR1bGluZzoKICBjb3JlUG9kczoKICAgIG5vZGVBZmZpbml0eToKICAgICAgbWF0Y2hOb2RlUHVycG9zZTogcHJlZmVyCiAgICB0b2xlcmF0aW9uczoKICAgIC0gZWZmZWN0OiBOb1NjaGVkdWxlCiAgICAgIGtleTogaHViLmp1cHl0ZXIub3JnL2RlZGljYXRlZAogICAgICBvcGVyYXRvcjogRXF1YWwKICAgICAgdmFsdWU6IGNvcmUKICAgIC0gZWZmZWN0OiBOb1NjaGVkdWxlCiAgICAgIGtleTogaHViLmp1cHl0ZXIub3JnX2RlZGljYXRlZAogICAgICBvcGVyYXRvcjogRXF1YWwKICAgICAgdmFsdWU6IGNvcmUKICBwb2RQcmlvcml0eToKICAgIGRlZmF1bHRQcmlvcml0eTogMAogICAgZW5hYmxlZDogZmFsc2UKICAgIGdsb2JhbERlZmF1bHQ6IGZhbHNlCiAgICBpbWFnZVB1bGxlclByaW9yaXR5OiAtNQogICAgdXNlclBsYWNlaG9sZGVyUHJpb3JpdHk6IC0xMAogIHVzZXJQbGFjZWhvbGRlcjoKICAgIGFubm90YXRpb25zOiB7fQogICAgY29udGFpbmVyU2VjdXJpdHlDb250ZXh0OgogICAgICBhbGxvd1ByaXZpbGVnZUVzY2FsYXRpb246IGZhbHNlCiAgICAgIHJ1bkFzR3JvdXA6IDY1NTM0CiAgICAgIHJ1bkFzVXNlcjogNjU1MzQKICAgIGVuYWJsZWQ6IHRydWUKICAgIGltYWdlOgogICAgICBuYW1lOiBrOHMuZ2NyLmlvL3BhdXNlCiAgICAgIHB1bGxQb2xpY3k6IG51bGwKICAgICAgcHVsbFNlY3JldHM6IFtdCiAgICAgIHRhZzogIjMuOCIKICAgIGxhYmVsczoge30KICAgIHJlcGxpY2FzOiAwCiAgICByZXNvdXJjZXM6IHt9CiAgICByZXZpc2lvbkhpc3RvcnlMaW1pdDogbnVsbAogIHVzZXJQb2RzOgogICAgbm9kZUFmZmluaXR5OgogICAgICBtYXRjaE5vZGVQdXJwb3NlOiBwcmVmZXIKICAgIHRvbGVyYXRpb25zOgogICAgLSBlZmZlY3Q6IE5vU2NoZWR1bGUKICAgICAga2V5OiBodWIuanVweXRlci5vcmcvZGVkaWNhdGVkCiAgICAgIG9wZXJhdG9yOiBFcXVhbAogICAgICB2YWx1ZTogdXNlcgogICAgLSBlZmZlY3Q6IE5vU2NoZWR1bGUKICAgICAga2V5OiBodWIuanVweXRlci5vcmdfZGVkaWNhdGVkCiAgICAgIG9wZXJhdG9yOiBFcXVhbAogICAgICB2YWx1ZTogdXNlcgogIHVzZXJTY2hlZHVsZXI6CiAgICBhbm5vdGF0aW9uczoge30KICAgIGNvbnRhaW5lclNlY3VyaXR5Q29udGV4dDoKICAgICAgYWxsb3dQcml2aWxlZ2VFc2NhbGF0aW9uOiBmYWxzZQogICAgICBydW5Bc0dyb3VwOiA2NTUzNAogICAgICBydW5Bc1VzZXI6IDY1NTM0CiAgICBlbmFibGVkOiB0cnVlCiAgICBleHRyYVBvZFNwZWM6IHt9CiAgICBpbWFnZToKICAgICAgbmFtZTogazhzLmdjci5pby9rdWJlLXNjaGVkdWxlcgogICAgICBwdWxsUG9saWN5OiBudWxsCiAgICAgIHB1bGxTZWNyZXRzOiBbXQogICAgICB0YWc6IHYxLjIzLjEwCiAgICBsYWJlbHM6IHt9CiAgICBsb2dMZXZlbDogNAogICAgbm9kZVNlbGVjdG9yOiB7fQogICAgcGRiOgogICAgICBlbmFibGVkOiB0cnVlCiAgICAgIG1heFVuYXZhaWxhYmxlOiAxCiAgICAgIG1pbkF2YWlsYWJsZTogbnVsbAogICAgcGx1Z2luQ29uZmlnOgogICAgLSBhcmdzOgogICAgICAgIHNjb3JpbmdTdHJhdGVneToKICAgICAgICAgIHJlc291cmNlczoKICAgICAgICAgIC0gbmFtZTogY3B1CiAgICAgICAgICAgIHdlaWdodDogMQogICAgICAgICAgLSBuYW1lOiBtZW1vcnkKICAgICAgICAgICAgd2VpZ2h0OiAxCiAgICAgICAgICB0eXBlOiBNb3N0QWxsb2NhdGVkCiAgICAgIG5hbWU6IE5vZGVSZXNvdXJjZXNGaXQKICAgIHBsdWdpbnM6CiAgICAgIHNjb3JlOgogICAgICAgIGRpc2FibGVkOgogICAgICAgIC0gbmFtZTogTm9kZVJlc291cmNlc0JhbGFuY2VkQWxsb2NhdGlvbgogICAgICAgIC0gbmFtZTogTm9kZUFmZmluaXR5CiAgICAgICAgLSBuYW1lOiBJbnRlclBvZEFmZmluaXR5CiAgICAgICAgLSBuYW1lOiBOb2RlUmVzb3VyY2VzRml0CiAgICAgICAgLSBuYW1lOiBJbWFnZUxvY2FsaXR5CiAgICAgICAgZW5hYmxlZDoKICAgICAgICAtIG5hbWU6IE5vZGVBZmZpbml0eQogICAgICAgICAgd2VpZ2h0OiAxNDYzMQogICAgICAgIC0gbmFtZTogSW50ZXJQb2RBZmZpbml0eQogICAgICAgICAgd2VpZ2h0OiAxMzMxCiAgICAgICAgLSBuYW1lOiBOb2RlUmVzb3VyY2VzRml0CiAgICAgICAgICB3ZWlnaHQ6IDEyMQogICAgICAgIC0gbmFtZTogSW1hZ2VMb2NhbGl0eQogICAgICAgICAgd2VpZ2h0OiAxMQogICAgcmVwbGljYXM6IDIKICAgIHJlc291cmNlczoge30KICAgIHJldmlzaW9uSGlzdG9yeUxpbWl0OiBudWxsCiAgICBzZXJ2aWNlQWNjb3VudDoKICAgICAgYW5ub3RhdGlvbnM6IHt9CiAgICAgIGNyZWF0ZTogdHJ1ZQogICAgICBuYW1lOiBudWxsCiAgICB0b2xlcmF0aW9uczogW10Kc2luZ2xldXNlcjoKICBhbGxvd1ByaXZpbGVnZUVzY2FsYXRpb246IGZhbHNlCiAgY2xvdWRNZXRhZGF0YToKICAgIGJsb2NrV2l0aElwdGFibGVzOiB0cnVlCiAgICBpcDogMTY5LjI1NC4xNjkuMjU0CiAgY21kOiBqdXB5dGVyaHViLXNpbmdsZXVzZXIKICBjcHU6CiAgICBndWFyYW50ZWU6IDAuMDUKICAgIGxpbWl0OiA0CiAgZGVmYXVsdFVybDogL2xhYgogIGV2ZW50czogdHJ1ZQogIGV4dHJhQW5ub3RhdGlvbnM6IHt9CiAgZXh0cmFDb250YWluZXJzOiBbXQogIGV4dHJhRW52OgogICAgSlVQWVRFUkhVQl9TSU5HTEVVU0VSX0FQUDoganVweXRlcl9zZXJ2ZXIuc2VydmVyYXBwLlNlcnZlckFwcAogIGV4dHJhRmlsZXM6IHt9CiAgZXh0cmFMYWJlbHM6CiAgICBodWIuanVweXRlci5vcmcvbmV0d29yay1hY2Nlc3MtaHViOiAidHJ1ZSIKICBleHRyYU5vZGVBZmZpbml0eToKICAgIHByZWZlcnJlZDogW10KICAgIHJlcXVpcmVkOgogICAgLSBtYXRjaEV4cHJlc3Npb25zOgogICAgICAtIGtleToga3ViZXJuZXRlcy5pby9hcmNoCiAgICAgICAgb3BlcmF0b3I6IEluCiAgICAgICAgdmFsdWVzOgogICAgICAgIC0gYW1kNjQKICAgICAgICAtIGkzODYKICAgICAgICAtIGk2ODYKICAgICAgICAtIHg4NgogIGV4dHJhUG9kQWZmaW5pdHk6CiAgICBwcmVmZXJyZWQ6IFtdCiAgICByZXF1aXJlZDogW10KICBleHRyYVBvZEFudGlBZmZpbml0eToKICAgIHByZWZlcnJlZDogW10KICAgIHJlcXVpcmVkOiBbXQogIGV4dHJhUG9kQ29uZmlnOiB7fQogIGV4dHJhUmVzb3VyY2U6CiAgICBndWFyYW50ZWVzOiB7fQogICAgbGltaXRzOiB7fQogIGV4dHJhVG9sZXJhdGlvbnM6IFtdCiAgZnNHaWQ6IDEwMAogIGltYWdlOgogICAgbmFtZToganVweXRlci9zY2lweS1ub3RlYm9vawogICAgcHVsbFBvbGljeTogbnVsbAogICAgcHVsbFNlY3JldHM6IFtdCiAgICB0YWc6IDgyY2U3Mzc4OWJhNAogIGluaXRDb250YWluZXJzOiBbXQogIGxpZmVjeWNsZUhvb2tzOiB7fQogIG1lbW9yeToKICAgIGd1YXJhbnRlZTogNTEyTQogICAgbGltaXQ6IDhHCiAgbmV0d29ya1BvbGljeToKICAgIGFsbG93ZWRJbmdyZXNzUG9ydHM6IFtdCiAgICBlZ3Jlc3M6IFtdCiAgICBlZ3Jlc3NBbGxvd1J1bGVzOgogICAgICBjbG91ZE1ldGFkYXRhU2VydmVyOiBmYWxzZQogICAgICBkbnNQb3J0c1ByaXZhdGVJUHM6IHRydWUKICAgICAgbm9uUHJpdmF0ZUlQczogdHJ1ZQogICAgICBwcml2YXRlSVBzOiBmYWxzZQogICAgZW5hYmxlZDogdHJ1ZQogICAgaW5ncmVzczogW10KICAgIGludGVyTmFtZXNwYWNlQWNjZXNzTGFiZWxzOiBpZ25vcmUKICBuZXR3b3JrVG9vbHM6CiAgICBpbWFnZToKICAgICAgbmFtZToganVweXRlcmh1Yi9rOHMtbmV0d29yay10b29scwogICAgICBwdWxsUG9saWN5OiBudWxsCiAgICAgIHB1bGxTZWNyZXRzOiBbXQogICAgICB0YWc6IDIuMC4wCiAgICByZXNvdXJjZXM6IHt9CiAgbm9kZVNlbGVjdG9yOiB7fQogIHBvZE5hbWVUZW1wbGF0ZTogbnVsbAogIHByb2ZpbGVMaXN0OgogIC0gZGVzY3JpcHRpb246ICdUbyBhdm9pZCB0b28gbXVjaCBiZWxscyBhbmQgd2hpc3RsZXM6IFB5dGhvbi4nCiAgICBkaXNwbGF5X25hbWU6IE1pbmltYWwgZW52aXJvbm1lbnQKICAgIGt1YmVzcGF3bmVyX292ZXJyaWRlOgogICAgICBpbWFnZToganVweXRlci9taW5pbWFsLW5vdGVib29rOjgyY2U3Mzc4OWJhNAogIC0gZGVmYXVsdDogdHJ1ZQogICAgZGVzY3JpcHRpb246ICdJZiB5b3Ugd2FudCB0aGUgYWRkaXRpb25hbCBiZWxscyBhbmQgd2hpc3RsZXM6IFB5dGhvbiwgUiwgYW5kIEp1bGlhLicKICAgIGRpc3BsYXlfbmFtZTogRGF0YXNjaWVuY2UgZW52aXJvbm1lbnQKICAtIGRlc2NyaXB0aW9uOiBUaGUgSnVweXRlciBTdGFja3Mgc3BhcmsgaW1hZ2UhCiAgICBkaXNwbGF5X25hbWU6IFNwYXJrIGVudmlyb25tZW50CiAgICBrdWJlc3Bhd25lcl9vdmVycmlkZToKICAgICAgaW1hZ2U6IGp1cHl0ZXIvYWxsLXNwYXJrLW5vdGVib29rOjIzNDNlMzNkZWM0NgogIC0gZGVzY3JpcHRpb246IERhdGFzY2llbmNlIEVudmlyb25tZW50IHdpdGggU2FtcGxlIE5vdGVib29rcwogICAgZGlzcGxheV9uYW1lOiBMZWFybmluZyBEYXRhIFNjaWVuY2UKICAgIGt1YmVzcGF3bmVyX292ZXJyaWRlOgogICAgICBpbWFnZToganVweXRlci9kYXRhc2NpZW5jZS1ub3RlYm9vazoyMzQzZTMzZGVjNDYKICBzZXJ2aWNlQWNjb3VudE5hbWU6IG51bGwKICBzdGFydFRpbWVvdXQ6IDMwMAogIHN0b3JhZ2U6CiAgICBjYXBhY2l0eTogMTVHaQogICAgZHluYW1pYzoKICAgICAgcHZjTmFtZVRlbXBsYXRlOiBjbGFpbS17dXNlcm5hbWV9e3NlcnZlcm5hbWV9CiAgICAgIHN0b3JhZ2VBY2Nlc3NNb2RlczoKICAgICAgLSBSZWFkV3JpdGVPbmNlCiAgICAgIHN0b3JhZ2VDbGFzczogY2VwaC1ibG9jawogICAgICB2b2x1bWVOYW1lVGVtcGxhdGU6IHZvbHVtZS17dXNlcm5hbWV9e3NlcnZlcm5hbWV9CiAgICBleHRyYUxhYmVsczoge30KICAgIGV4dHJhVm9sdW1lTW91bnRzOiBbXQogICAgZXh0cmFWb2x1bWVzOiBbXQogICAgaG9tZU1vdW50UGF0aDogL2hvbWUvam92eWFuCiAgICBzdGF0aWM6CiAgICAgIHB2Y05hbWU6IG51bGwKICAgICAgc3ViUGF0aDogJ3t1c2VybmFtZX0nCiAgICB0eXBlOiBkeW5hbWljCiAgdWlkOiAxMDAw"
- # Any JupyterHub Services api_tokens are exposed in this k8s Secret as a
- # convinience for external services running in the k8s cluster that could
- # mount them directly from this k8s Secret.
- # During Helm template rendering, these values that can be autogenerated for
- # users are set using the following logic:
- #
- # 1. Use chart configuration's value
- # 2. Use k8s Secret's value
- # 3. Use a new autogenerated value
- #
- # hub.config.ConfigurableHTTPProxy.auth_token: for hub to proxy-api authorization (JupyterHub.proxy_auth_token is deprecated)
- # hub.config.JupyterHub.cookie_secret: for cookie encryption
- # hub.config.CryptKeeper.keys: for auth state encryption
- #
- hub.config.ConfigurableHTTPProxy.auth_token: "NEpNYThjcVhyZjRiMjVNYzgyNFJReVllRUR1cGI5UUttcEFtdGVJS3cyYllhSlJYTzE5eFNaMzJxTnEyY1FJQQ=="
- hub.config.JupyterHub.cookie_secret: "NDFmN2JhMDNhMTEyN2ViNTE5OTlmMDJlMGRmNDM2MTZmNjI4MTVjNDE2MDQzNDIzZGFlMDZhNTVhYzIwZWNjNA=="
- hub.config.CryptKeeper.keys: "ZWU3NDQ4OTA0ZTExYmZiMDJlNzMwMjdmZmZmZDUzMTliY2Q1ZmExYWU3MTBkNTE1OTZjMTJlNWJjYTdlNTY0Yw=="
----
-# Source: jupyterhub/templates/hub/configmap.yaml
-kind: ConfigMap
-apiVersion: v1
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-data:
- fullname: ""
- fullname-dash: ""
- hub: "hub"
- hub-serviceaccount: "hub"
- hub-existing-secret: ""
- hub-existing-secret-or-default: "hub"
- hub-pvc: "hub-db-dir"
- proxy: "proxy"
- proxy-api: "proxy-api"
- proxy-http: "proxy-http"
- proxy-public: "proxy-public"
- proxy-public-tls: "proxy-public-tls-acme"
- proxy-public-manual-tls: "proxy-public-manual-tls"
- autohttps: "autohttps"
- autohttps-serviceaccount: "autohttps"
- user-scheduler-deploy: "user-scheduler"
- user-scheduler-serviceaccount: "user-scheduler"
- user-scheduler-lock: "user-scheduler-lock"
- user-placeholder: "user-placeholder"
- image-puller-priority: "jupyterhub-image-puller-priority"
- hook-image-awaiter: "hook-image-awaiter"
- hook-image-awaiter-serviceaccount: "hook-image-awaiter"
- hook-image-puller: "hook-image-puller"
- continuous-image-puller: "continuous-image-puller"
- singleuser: "singleuser"
- image-pull-secret: "image-pull-secret"
- ingress: "jupyterhub"
- priority: "jupyterhub-default-priority"
- user-placeholder-priority: "jupyterhub-user-placeholder-priority"
- user-scheduler: "jupyterhub-user-scheduler"
- jupyterhub_config.py: |
- import glob
- import os
- import re
- import sys
- from binascii import a2b_hex
-
- from jupyterhub.utils import url_path_join
- from kubernetes_asyncio import client
- from tornado.httpclient import AsyncHTTPClient
-
- # Make sure that modules placed in the same directory as the jupyterhub config are added to the pythonpath
- configuration_directory = os.path.dirname(os.path.realpath(__file__))
- sys.path.insert(0, configuration_directory)
-
- from z2jh import (
- get_config,
- get_name,
- get_name_env,
- get_secret_value,
- set_config_if_not_none,
- )
-
-
- def camelCaseify(s):
- """convert snake_case to camelCase
-
- For the common case where some_value is set from someValue
- so we don't have to specify the name twice.
- """
- return re.sub(r"_([a-z])", lambda m: m.group(1).upper(), s)
-
-
- # Configure JupyterHub to use the curl backend for making HTTP requests,
- # rather than the pure-python implementations. The default one starts
- # being too slow to make a large number of requests to the proxy API
- # at the rate required.
- AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
-
- c.JupyterHub.spawner_class = "kubespawner.KubeSpawner"
-
- # Connect to a proxy running in a different pod. Note that *_SERVICE_*
- # environment variables are set by Kubernetes for Services
- c.ConfigurableHTTPProxy.api_url = (
- f'http://{get_name("proxy-api")}:{get_name_env("proxy-api", "_SERVICE_PORT")}'
- )
- c.ConfigurableHTTPProxy.should_start = False
-
- # Do not shut down user pods when hub is restarted
- c.JupyterHub.cleanup_servers = False
-
- # Check that the proxy has routes appropriately setup
- c.JupyterHub.last_activity_interval = 60
-
- # Don't wait at all before redirecting a spawning user to the progress page
- c.JupyterHub.tornado_settings = {
- "slow_spawn_timeout": 0,
- }
-
-
- # configure the hub db connection
- db_type = get_config("hub.db.type")
- if db_type == "sqlite-pvc":
- c.JupyterHub.db_url = "sqlite:///jupyterhub.sqlite"
- elif db_type == "sqlite-memory":
- c.JupyterHub.db_url = "sqlite://"
- else:
- set_config_if_not_none(c.JupyterHub, "db_url", "hub.db.url")
- db_password = get_secret_value("hub.db.password", None)
- if db_password is not None:
- if db_type == "mysql":
- os.environ["MYSQL_PWD"] = db_password
- elif db_type == "postgres":
- os.environ["PGPASSWORD"] = db_password
- else:
- print(f"Warning: hub.db.password is ignored for hub.db.type={db_type}")
-
-
- # c.JupyterHub configuration from Helm chart's configmap
- for trait, cfg_key in (
- ("concurrent_spawn_limit", None),
- ("active_server_limit", None),
- ("base_url", None),
- ("allow_named_servers", None),
- ("named_server_limit_per_user", None),
- ("authenticate_prometheus", None),
- ("redirect_to_server", None),
- ("shutdown_on_logout", None),
- ("template_paths", None),
- ("template_vars", None),
- ):
- if cfg_key is None:
- cfg_key = camelCaseify(trait)
- set_config_if_not_none(c.JupyterHub, trait, "hub." + cfg_key)
-
- # hub_bind_url configures what the JupyterHub process within the hub pod's
- # container should listen to.
- hub_container_port = 8081
- c.JupyterHub.hub_bind_url = f"http://:{hub_container_port}"
-
- # hub_connect_url is the URL for connecting to the hub for use by external
- # JupyterHub services such as the proxy. Note that *_SERVICE_* environment
- # variables are set by Kubernetes for Services.
- c.JupyterHub.hub_connect_url = (
- f'http://{get_name("hub")}:{get_name_env("hub", "_SERVICE_PORT")}'
- )
-
- # implement common labels
- # this duplicates the jupyterhub.commonLabels helper
- common_labels = c.KubeSpawner.common_labels = {}
- common_labels["app"] = get_config(
- "nameOverride",
- default=get_config("Chart.Name", "jupyterhub"),
- )
- common_labels["heritage"] = "jupyterhub"
- chart_name = get_config("Chart.Name")
- chart_version = get_config("Chart.Version")
- if chart_name and chart_version:
- common_labels["chart"] = "{}-{}".format(
- chart_name,
- chart_version.replace("+", "_"),
- )
- release = get_config("Release.Name")
- if release:
- common_labels["release"] = release
-
- c.KubeSpawner.namespace = os.environ.get("POD_NAMESPACE", "default")
-
- # Max number of consecutive failures before the Hub restarts itself
- # requires jupyterhub 0.9.2
- set_config_if_not_none(
- c.Spawner,
- "consecutive_failure_limit",
- "hub.consecutiveFailureLimit",
- )
-
- for trait, cfg_key in (
- ("pod_name_template", None),
- ("start_timeout", None),
- ("image_pull_policy", "image.pullPolicy"),
- # ('image_pull_secrets', 'image.pullSecrets'), # Managed manually below
- ("events_enabled", "events"),
- ("extra_labels", None),
- ("extra_annotations", None),
- # ("allow_privilege_escalation", None), # Managed manually below
- ("uid", None),
- ("fs_gid", None),
- ("service_account", "serviceAccountName"),
- ("storage_extra_labels", "storage.extraLabels"),
- # ("tolerations", "extraTolerations"), # Managed manually below
- ("node_selector", None),
- ("node_affinity_required", "extraNodeAffinity.required"),
- ("node_affinity_preferred", "extraNodeAffinity.preferred"),
- ("pod_affinity_required", "extraPodAffinity.required"),
- ("pod_affinity_preferred", "extraPodAffinity.preferred"),
- ("pod_anti_affinity_required", "extraPodAntiAffinity.required"),
- ("pod_anti_affinity_preferred", "extraPodAntiAffinity.preferred"),
- ("lifecycle_hooks", None),
- ("init_containers", None),
- ("extra_containers", None),
- ("mem_limit", "memory.limit"),
- ("mem_guarantee", "memory.guarantee"),
- ("cpu_limit", "cpu.limit"),
- ("cpu_guarantee", "cpu.guarantee"),
- ("extra_resource_limits", "extraResource.limits"),
- ("extra_resource_guarantees", "extraResource.guarantees"),
- ("environment", "extraEnv"),
- ("profile_list", None),
- ("extra_pod_config", None),
- ):
- if cfg_key is None:
- cfg_key = camelCaseify(trait)
- set_config_if_not_none(c.KubeSpawner, trait, "singleuser." + cfg_key)
-
- image = get_config("singleuser.image.name")
- if image:
- tag = get_config("singleuser.image.tag")
- if tag:
- image = f"{image}:{tag}"
-
- c.KubeSpawner.image = image
-
- # allow_privilege_escalation defaults to False in KubeSpawner 2+. Since its a
- # property where None, False, and True all are valid values that users of the
- # Helm chart may want to set, we can't use the set_config_if_not_none helper
- # function as someone may want to override the default False value to None.
- #
- c.KubeSpawner.allow_privilege_escalation = get_config(
- "singleuser.allowPrivilegeEscalation"
- )
-
- # Combine imagePullSecret.create (single), imagePullSecrets (list), and
- # singleuser.image.pullSecrets (list).
- image_pull_secrets = []
- if get_config("imagePullSecret.automaticReferenceInjection") and get_config(
- "imagePullSecret.create"
- ):
- image_pull_secrets.append(get_name("image-pull-secret"))
- if get_config("imagePullSecrets"):
- image_pull_secrets.extend(get_config("imagePullSecrets"))
- if get_config("singleuser.image.pullSecrets"):
- image_pull_secrets.extend(get_config("singleuser.image.pullSecrets"))
- if image_pull_secrets:
- c.KubeSpawner.image_pull_secrets = image_pull_secrets
-
- # scheduling:
- if get_config("scheduling.userScheduler.enabled"):
- c.KubeSpawner.scheduler_name = get_name("user-scheduler")
- if get_config("scheduling.podPriority.enabled"):
- c.KubeSpawner.priority_class_name = get_name("priority")
-
- # add node-purpose affinity
- match_node_purpose = get_config("scheduling.userPods.nodeAffinity.matchNodePurpose")
- if match_node_purpose:
- node_selector = dict(
- matchExpressions=[
- dict(
- key="hub.jupyter.org/node-purpose",
- operator="In",
- values=["user"],
- )
- ],
- )
- if match_node_purpose == "prefer":
- c.KubeSpawner.node_affinity_preferred.append(
- dict(
- weight=100,
- preference=node_selector,
- ),
- )
- elif match_node_purpose == "require":
- c.KubeSpawner.node_affinity_required.append(node_selector)
- elif match_node_purpose == "ignore":
- pass
- else:
- raise ValueError(
- f"Unrecognized value for matchNodePurpose: {match_node_purpose}"
- )
-
- # Combine the common tolerations for user pods with singleuser tolerations
- scheduling_user_pods_tolerations = get_config("scheduling.userPods.tolerations", [])
- singleuser_extra_tolerations = get_config("singleuser.extraTolerations", [])
- tolerations = scheduling_user_pods_tolerations + singleuser_extra_tolerations
- if tolerations:
- c.KubeSpawner.tolerations = tolerations
-
- # Configure dynamically provisioning pvc
- storage_type = get_config("singleuser.storage.type")
- if storage_type == "dynamic":
- pvc_name_template = get_config("singleuser.storage.dynamic.pvcNameTemplate")
- c.KubeSpawner.pvc_name_template = pvc_name_template
- volume_name_template = get_config("singleuser.storage.dynamic.volumeNameTemplate")
- c.KubeSpawner.storage_pvc_ensure = True
- set_config_if_not_none(
- c.KubeSpawner, "storage_class", "singleuser.storage.dynamic.storageClass"
- )
- set_config_if_not_none(
- c.KubeSpawner,
- "storage_access_modes",
- "singleuser.storage.dynamic.storageAccessModes",
- )
- set_config_if_not_none(
- c.KubeSpawner, "storage_capacity", "singleuser.storage.capacity"
- )
-
- # Add volumes to singleuser pods
- c.KubeSpawner.volumes = [
- {
- "name": volume_name_template,
- "persistentVolumeClaim": {"claimName": pvc_name_template},
- }
- ]
- c.KubeSpawner.volume_mounts = [
- {
- "mountPath": get_config("singleuser.storage.homeMountPath"),
- "name": volume_name_template,
- }
- ]
- elif storage_type == "static":
- pvc_claim_name = get_config("singleuser.storage.static.pvcName")
- c.KubeSpawner.volumes = [
- {"name": "home", "persistentVolumeClaim": {"claimName": pvc_claim_name}}
- ]
-
- c.KubeSpawner.volume_mounts = [
- {
- "mountPath": get_config("singleuser.storage.homeMountPath"),
- "name": "home",
- "subPath": get_config("singleuser.storage.static.subPath"),
- }
- ]
-
- # Inject singleuser.extraFiles as volumes and volumeMounts with data loaded from
- # the dedicated k8s Secret prepared to hold the extraFiles actual content.
- extra_files = get_config("singleuser.extraFiles", {})
- if extra_files:
- volume = {
- "name": "files",
- }
- items = []
- for file_key, file_details in extra_files.items():
- # Each item is a mapping of a key in the k8s Secret to a path in this
- # abstract volume, the goal is to enable us to set the mode /
- # permissions only though so we don't change the mapping.
- item = {
- "key": file_key,
- "path": file_key,
- }
- if "mode" in file_details:
- item["mode"] = file_details["mode"]
- items.append(item)
- volume["secret"] = {
- "secretName": get_name("singleuser"),
- "items": items,
- }
- c.KubeSpawner.volumes.append(volume)
-
- volume_mounts = []
- for file_key, file_details in extra_files.items():
- volume_mounts.append(
- {
- "mountPath": file_details["mountPath"],
- "subPath": file_key,
- "name": "files",
- }
- )
- c.KubeSpawner.volume_mounts.extend(volume_mounts)
-
- # Inject extraVolumes / extraVolumeMounts
- c.KubeSpawner.volumes.extend(get_config("singleuser.storage.extraVolumes", []))
- c.KubeSpawner.volume_mounts.extend(
- get_config("singleuser.storage.extraVolumeMounts", [])
- )
-
- c.JupyterHub.services = []
- c.JupyterHub.load_roles = []
-
- # jupyterhub-idle-culler's permissions are scoped to what it needs only, see
- # https://github.com/jupyterhub/jupyterhub-idle-culler#permissions.
- #
- if get_config("cull.enabled", False):
- jupyterhub_idle_culler_role = {
- "name": "jupyterhub-idle-culler",
- "scopes": [
- "list:users",
- "read:users:activity",
- "read:servers",
- "delete:servers",
- # "admin:users", # dynamically added if --cull-users is passed
- ],
- # assign the role to a jupyterhub service, so it gains these permissions
- "services": ["jupyterhub-idle-culler"],
- }
-
- cull_cmd = ["python3", "-m", "jupyterhub_idle_culler"]
- base_url = c.JupyterHub.get("base_url", "/")
- cull_cmd.append("--url=http://localhost:8081" + url_path_join(base_url, "hub/api"))
-
- cull_timeout = get_config("cull.timeout")
- if cull_timeout:
- cull_cmd.append(f"--timeout={cull_timeout}")
-
- cull_every = get_config("cull.every")
- if cull_every:
- cull_cmd.append(f"--cull-every={cull_every}")
-
- cull_concurrency = get_config("cull.concurrency")
- if cull_concurrency:
- cull_cmd.append(f"--concurrency={cull_concurrency}")
-
- if get_config("cull.users"):
- cull_cmd.append("--cull-users")
- jupyterhub_idle_culler_role["scopes"].append("admin:users")
-
- if not get_config("cull.adminUsers"):
- cull_cmd.append("--cull-admin-users=false")
-
- if get_config("cull.removeNamedServers"):
- cull_cmd.append("--remove-named-servers")
-
- cull_max_age = get_config("cull.maxAge")
- if cull_max_age:
- cull_cmd.append(f"--max-age={cull_max_age}")
-
- c.JupyterHub.services.append(
- {
- "name": "jupyterhub-idle-culler",
- "command": cull_cmd,
- }
- )
- c.JupyterHub.load_roles.append(jupyterhub_idle_culler_role)
-
- for key, service in get_config("hub.services", {}).items():
- # c.JupyterHub.services is a list of dicts, but
- # hub.services is a dict of dicts to make the config mergable
- service.setdefault("name", key)
-
- # As the api_token could be exposed in hub.existingSecret, we need to read
- # it it from there or fall back to the chart managed k8s Secret's value.
- service.pop("apiToken", None)
- service["api_token"] = get_secret_value(f"hub.services.{key}.apiToken")
-
- c.JupyterHub.services.append(service)
-
- for key, role in get_config("hub.loadRoles", {}).items():
- # c.JupyterHub.load_roles is a list of dicts, but
- # hub.loadRoles is a dict of dicts to make the config mergable
- role.setdefault("name", key)
-
- c.JupyterHub.load_roles.append(role)
-
- # respect explicit null command (distinct from unspecified)
- # this avoids relying on KubeSpawner.cmd's default being None
- _unspecified = object()
- specified_cmd = get_config("singleuser.cmd", _unspecified)
- if specified_cmd is not _unspecified:
- c.Spawner.cmd = specified_cmd
-
- set_config_if_not_none(c.Spawner, "default_url", "singleuser.defaultUrl")
-
- cloud_metadata = get_config("singleuser.cloudMetadata", {})
-
- if cloud_metadata.get("blockWithIptables") == True:
- # Use iptables to block access to cloud metadata by default
- network_tools_image_name = get_config("singleuser.networkTools.image.name")
- network_tools_image_tag = get_config("singleuser.networkTools.image.tag")
- network_tools_resources = get_config("singleuser.networkTools.resources")
- ip_block_container = client.V1Container(
- name="block-cloud-metadata",
- image=f"{network_tools_image_name}:{network_tools_image_tag}",
- command=[
- "iptables",
- "-A",
- "OUTPUT",
- "-d",
- cloud_metadata.get("ip", "169.254.169.254"),
- "-j",
- "DROP",
- ],
- security_context=client.V1SecurityContext(
- privileged=True,
- run_as_user=0,
- capabilities=client.V1Capabilities(add=["NET_ADMIN"]),
- ),
- resources=network_tools_resources,
- )
-
- c.KubeSpawner.init_containers.append(ip_block_container)
-
-
- if get_config("debug.enabled", False):
- c.JupyterHub.log_level = "DEBUG"
- c.Spawner.debug = True
-
- # load potentially seeded secrets
- #
- # NOTE: ConfigurableHTTPProxy.auth_token is set through an environment variable
- # that is set using the chart managed secret.
- c.JupyterHub.cookie_secret = get_secret_value("hub.config.JupyterHub.cookie_secret")
- # NOTE: CryptKeeper.keys should be a list of strings, but we have encoded as a
- # single string joined with ; in the k8s Secret.
- #
- c.CryptKeeper.keys = get_secret_value("hub.config.CryptKeeper.keys").split(";")
-
- # load hub.config values, except potentially seeded secrets already loaded
- for app, cfg in get_config("hub.config", {}).items():
- if app == "JupyterHub":
- cfg.pop("proxy_auth_token", None)
- cfg.pop("cookie_secret", None)
- cfg.pop("services", None)
- elif app == "ConfigurableHTTPProxy":
- cfg.pop("auth_token", None)
- elif app == "CryptKeeper":
- cfg.pop("keys", None)
- c[app].update(cfg)
-
- # load /usr/local/etc/jupyterhub/jupyterhub_config.d config files
- config_dir = "/usr/local/etc/jupyterhub/jupyterhub_config.d"
- if os.path.isdir(config_dir):
- for file_path in sorted(glob.glob(f"{config_dir}/*.py")):
- file_name = os.path.basename(file_path)
- print(f"Loading {config_dir} config: {file_name}")
- with open(file_path) as f:
- file_content = f.read()
- # compiling makes debugging easier: https://stackoverflow.com/a/437857
- exec(compile(source=file_content, filename=file_name, mode="exec"))
-
- # execute hub.extraConfig entries
- for key, config_py in sorted(get_config("hub.extraConfig", {}).items()):
- print(f"Loading extra config: {key}")
- exec(config_py)
- z2jh.py: |
- """
- Utility methods for use in jupyterhub_config.py and dynamic subconfigs.
-
- Methods here can be imported by extraConfig in values.yaml
- """
- import os
- from collections.abc import Mapping
- from functools import lru_cache
-
- import yaml
-
-
- # memoize so we only load config once
- @lru_cache
- def _load_config():
- """Load the Helm chart configuration used to render the Helm templates of
- the chart from a mounted k8s Secret, and merge in values from an optionally
- mounted secret (hub.existingSecret)."""
-
- cfg = {}
- for source in ("secret/values.yaml", "existing-secret/values.yaml"):
- path = f"/usr/local/etc/jupyterhub/{source}"
- if os.path.exists(path):
- print(f"Loading {path}")
- with open(path) as f:
- values = yaml.safe_load(f)
- cfg = _merge_dictionaries(cfg, values)
- else:
- print(f"No config at {path}")
- return cfg
-
-
- @lru_cache
- def _get_config_value(key):
- """Load value from the k8s ConfigMap given a key."""
-
- path = f"/usr/local/etc/jupyterhub/config/{key}"
- if os.path.exists(path):
- with open(path) as f:
- return f.read()
- else:
- raise Exception(f"{path} not found!")
-
-
- @lru_cache
- def get_secret_value(key, default="never-explicitly-set"):
- """Load value from the user managed k8s Secret or the default k8s Secret
- given a key."""
-
- for source in ("existing-secret", "secret"):
- path = f"/usr/local/etc/jupyterhub/{source}/{key}"
- if os.path.exists(path):
- with open(path) as f:
- return f.read()
- if default != "never-explicitly-set":
- return default
- raise Exception(f"{key} not found in either k8s Secret!")
-
-
- def get_name(name):
- """Returns the fullname of a resource given its short name"""
- return _get_config_value(name)
-
-
- def get_name_env(name, suffix=""):
- """Returns the fullname of a resource given its short name along with a
- suffix, converted to uppercase with dashes replaced with underscores. This
- is useful to reference named services associated environment variables, such
- as PROXY_PUBLIC_SERVICE_PORT."""
- env_key = _get_config_value(name) + suffix
- env_key = env_key.upper().replace("-", "_")
- return os.environ[env_key]
-
-
- def _merge_dictionaries(a, b):
- """Merge two dictionaries recursively.
-
- Simplified From https://stackoverflow.com/a/7205107
- """
- merged = a.copy()
- for key in b:
- if key in a:
- if isinstance(a[key], Mapping) and isinstance(b[key], Mapping):
- merged[key] = _merge_dictionaries(a[key], b[key])
- else:
- merged[key] = b[key]
- else:
- merged[key] = b[key]
- return merged
-
-
- def get_config(key, default=None):
- """
- Find a config item of a given name & return it
-
- Parses everything as YAML, so lists and dicts are available too
-
- get_config("a.b.c") returns config['a']['b']['c']
- """
- value = _load_config()
- # resolve path in yaml
- for level in key.split("."):
- if not isinstance(value, dict):
- # a parent is a scalar or null,
- # can't resolve full path
- return default
- if level not in value:
- return default
- else:
- value = value[level]
- return value
-
-
- def set_config_if_not_none(cparent, name, key):
- """
- Find a config item of a given name, set the corresponding Jupyter
- configuration item if not None
- """
- data = get_config(key)
- if data is not None:
- setattr(cparent, name, data)
- checksum_hook-image-puller: "7bd6dc13e81a89aea6a4102dbd990324c34467773180d9be72c685039612ff37"
----
-# Source: jupyterhub/templates/scheduling/user-scheduler/configmap.yaml
-kind: ConfigMap
-apiVersion: v1
-metadata:
- name: user-scheduler
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-data:
- config.yaml: |
- # WARNING: The tag of this image is hardcoded, and the
- # "scheduling.userScheduler.plugins" configuration of the Helm
- # chart that generated this resource manifest wasn't respected. If
- # you install the Helm chart in a k8s cluster versioned 1.21 or
- # higher, your configuration will be respected.
- apiVersion: kubescheduler.config.k8s.io/v1beta1
- kind: KubeSchedulerConfiguration
- leaderElection:
- resourceLock: endpoints
- resourceName: user-scheduler-lock
- resourceNamespace: "default"
- profiles:
- - schedulerName: jupyterhub-user-scheduler
- plugins:
- score:
- disabled:
- - name: SelectorSpread
- - name: TaintToleration
- - name: PodTopologySpread
- - name: NodeResourcesBalancedAllocation
- - name: NodeResourcesLeastAllocated
- # Disable plugins to be allowed to enable them again with a
- # different weight and avoid an error.
- - name: NodePreferAvoidPods
- - name: NodeAffinity
- - name: InterPodAffinity
- - name: ImageLocality
- enabled:
- - name: NodePreferAvoidPods
- weight: 161051
- - name: NodeAffinity
- weight: 14631
- - name: InterPodAffinity
- weight: 1331
- - name: NodeResourcesMostAllocated
- weight: 121
- - name: ImageLocality
- weight: 11
----
-# Source: jupyterhub/templates/scheduling/user-scheduler/rbac.yaml
-kind: ClusterRole
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
- name: jupyterhub-user-scheduler
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-rules:
- # Copied from the system:kube-scheduler ClusterRole of the k8s version
- # matching the kube-scheduler binary we use. A modification has been made to
- # resourceName fields to remain relevant for how we have named our resources
- # in this Helm chart.
- #
- # NOTE: These rules have been:
- # - unchanged between 1.12 and 1.15
- # - changed in 1.16
- # - changed in 1.17
- # - unchanged between 1.18 and 1.20
- # - changed in 1.21: get/list/watch permission for namespace,
- # csidrivers, csistoragecapacities was added.
- # - unchanged between 1.22 and 1.23
- #
- # ref: https://github.com/kubernetes/kubernetes/blob/v1.23.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L705-L861
- - apiGroups:
- - ""
- - events.k8s.io
- resources:
- - events
- verbs:
- - create
- - patch
- - update
- - apiGroups:
- - coordination.k8s.io
- resources:
- - leases
- verbs:
- - create
- - apiGroups:
- - coordination.k8s.io
- resourceNames:
- - user-scheduler-lock
- resources:
- - leases
- verbs:
- - get
- - update
- - apiGroups:
- - ""
- resources:
- - endpoints
- verbs:
- - create
- - apiGroups:
- - ""
- resourceNames:
- - user-scheduler-lock
- resources:
- - endpoints
- verbs:
- - get
- - update
- - apiGroups:
- - ""
- resources:
- - nodes
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - pods
- verbs:
- - delete
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - bindings
- - pods/binding
- verbs:
- - create
- - apiGroups:
- - ""
- resources:
- - pods/status
- verbs:
- - patch
- - update
- - apiGroups:
- - ""
- resources:
- - replicationcontrollers
- - services
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - apps
- - extensions
- resources:
- - replicasets
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - apps
- resources:
- - statefulsets
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - policy
- resources:
- - poddisruptionbudgets
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - persistentvolumeclaims
- - persistentvolumes
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - authentication.k8s.io
- resources:
- - tokenreviews
- verbs:
- - create
- - apiGroups:
- - authorization.k8s.io
- resources:
- - subjectaccessreviews
- verbs:
- - create
- - apiGroups:
- - storage.k8s.io
- resources:
- - csinodes
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - namespaces
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - storage.k8s.io
- resources:
- - csidrivers
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - storage.k8s.io
- resources:
- - csistoragecapacities
- verbs:
- - get
- - list
- - watch
- # Copied from the system:volume-scheduler ClusterRole of the k8s version
- # matching the kube-scheduler binary we use.
- #
- # NOTE: These rules have not changed between 1.12 and 1.23.
- #
- # ref: https://github.com/kubernetes/kubernetes/blob/v1.23.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L1280-L1307
- - apiGroups:
- - ""
- resources:
- - persistentvolumes
- verbs:
- - get
- - list
- - patch
- - update
- - watch
- - apiGroups:
- - storage.k8s.io
- resources:
- - storageclasses
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - persistentvolumeclaims
- verbs:
- - get
- - list
- - patch
- - update
- - watch
----
-# Source: jupyterhub/templates/scheduling/user-scheduler/rbac.yaml
-kind: ClusterRoleBinding
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
- name: jupyterhub-user-scheduler
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-subjects:
- - kind: ServiceAccount
- name: user-scheduler
- namespace: "default"
-roleRef:
- kind: ClusterRole
- name: jupyterhub-user-scheduler
- apiGroup: rbac.authorization.k8s.io
----
-# Source: jupyterhub/templates/hub/rbac.yaml
-kind: Role
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-rules:
- - apiGroups: [""] # "" indicates the core API group
- resources: ["pods", "persistentvolumeclaims", "secrets", "services"]
- verbs: ["get", "watch", "list", "create", "delete"]
- - apiGroups: [""] # "" indicates the core API group
- resources: ["events"]
- verbs: ["get", "watch", "list"]
----
-# Source: jupyterhub/templates/hub/rbac.yaml
-kind: RoleBinding
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-subjects:
- - kind: ServiceAccount
- name: hub
- namespace: "default"
-roleRef:
- kind: Role
- name: hub
- apiGroup: rbac.authorization.k8s.io
----
-# Source: jupyterhub/templates/hub/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
- annotations:
- prometheus.io/scrape: "true"
- prometheus.io/path: /hub/metrics
- prometheus.io/port: "8081"
-spec:
- type: ClusterIP
- selector:
- component: hub
- app: jupyterhub
- release: jupyterhub
- ports:
- - name: hub
- port: 8081
- targetPort: http
----
-# Source: jupyterhub/templates/proxy/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: proxy-api
- labels:
- component: proxy-api
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- selector:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- ports:
- - port: 8001
- targetPort: api
----
-# Source: jupyterhub/templates/proxy/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: proxy-public
- labels:
- component: proxy-public
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- selector:
- component: proxy
- release: jupyterhub
- ports:
- - name: http
- port: 80
- targetPort: http
- type: LoadBalancer
----
-# Source: jupyterhub/templates/image-puller/daemonset-continuous.yaml
-apiVersion: apps/v1
-kind: DaemonSet
-metadata:
- name: continuous-image-puller
- labels:
- component: continuous-image-puller
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- selector:
- matchLabels:
- component: continuous-image-puller
- app: jupyterhub
- release: jupyterhub
- updateStrategy:
- type: RollingUpdate
- rollingUpdate:
- maxUnavailable: 100%
- template:
- metadata:
- labels:
- component: continuous-image-puller
- app: jupyterhub
- release: jupyterhub
- spec:
- tolerations:
- - effect: NoSchedule
- key: hub.jupyter.org/dedicated
- operator: Equal
- value: user
- - effect: NoSchedule
- key: hub.jupyter.org_dedicated
- operator: Equal
- value: user
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: kubernetes.io/arch
- operator: In
- values:
- - amd64
- - i386
- - i686
- - x86
- terminationGracePeriodSeconds: 0
- automountServiceAccountToken: false
- initContainers:
- - name: image-pull-metadata-block
- image: jupyterhub/k8s-network-tools:2.0.0
- command:
- - /bin/sh
- - -c
- - echo "Pulling complete"
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
- - name: image-pull-singleuser
- image: jupyter/scipy-notebook:82ce73789ba4
- command:
- - /bin/sh
- - -c
- - echo "Pulling complete"
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
- - name: image-pull-singleuser-profilelist-0
- image: jupyter/minimal-notebook:82ce73789ba4
- command:
- - /bin/sh
- - -c
- - echo "Pulling complete"
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
- - name: image-pull-singleuser-profilelist-2
- image: jupyter/all-spark-notebook:2343e33dec46
- command:
- - /bin/sh
- - -c
- - echo "Pulling complete"
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
- - name: image-pull-singleuser-profilelist-3
- image: jupyter/datascience-notebook:2343e33dec46
- command:
- - /bin/sh
- - -c
- - echo "Pulling complete"
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
- containers:
- - name: pause
- image: k8s.gcr.io/pause:3.8
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
----
-# Source: jupyterhub/templates/hub/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: hub
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- strategy:
- type: Recreate
- template:
- metadata:
- labels:
- component: hub
- app: jupyterhub
- release: jupyterhub
- hub.jupyter.org/network-access-proxy-api: "true"
- hub.jupyter.org/network-access-proxy-http: "true"
- hub.jupyter.org/network-access-singleuser: "true"
- annotations:
- checksum/config-map: 6c42046cf2c7bb4966e23d2b4bca93b63e447960fd787b3f62174b39ad49cbac
- checksum/secret: 96beafcb491ebade4c38d0f6aaf749c93905ae5fc71440a45b79e13070c8a168
- spec:
- nodeSelector:
- kubernetes.io/arch: amd64
- tolerations:
- - effect: NoSchedule
- key: hub.jupyter.org/dedicated
- operator: Equal
- value: core
- - effect: NoSchedule
- key: hub.jupyter.org_dedicated
- operator: Equal
- value: core
- affinity:
- nodeAffinity:
- preferredDuringSchedulingIgnoredDuringExecution:
- - weight: 100
- preference:
- matchExpressions:
- - key: hub.jupyter.org/node-purpose
- operator: In
- values: [core]
- volumes:
- - name: config
- configMap:
- name: hub
- - name: secret
- secret:
- secretName: hub
- serviceAccountName: hub
- securityContext:
- fsGroup: 1000
- containers:
- - name: hub
- image: jupyterhub/k8s-hub:2.0.0
- args:
- - jupyterhub
- - --config
- - /usr/local/etc/jupyterhub/jupyterhub_config.py
- volumeMounts:
- - mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.py
- subPath: jupyterhub_config.py
- name: config
- - mountPath: /usr/local/etc/jupyterhub/z2jh.py
- subPath: z2jh.py
- name: config
- - mountPath: /usr/local/etc/jupyterhub/config/
- name: config
- - mountPath: /usr/local/etc/jupyterhub/secret/
- name: secret
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 1000
- runAsUser: 1000
- env:
- - name: PYTHONUNBUFFERED
- value: "1"
- - name: HELM_RELEASE_NAME
- value: "jupyterhub"
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- - name: CONFIGPROXY_AUTH_TOKEN
- valueFrom:
- secretKeyRef:
- name: hub
- key: hub.config.ConfigurableHTTPProxy.auth_token
- ports:
- - name: http
- containerPort: 8081
- livenessProbe:
- initialDelaySeconds: 300
- periodSeconds: 10
- timeoutSeconds: 3
- failureThreshold: 30
- httpGet:
- path: /hub/health
- port: http
- readinessProbe:
- initialDelaySeconds: 0
- periodSeconds: 2
- timeoutSeconds: 1
- failureThreshold: 1000
- httpGet:
- path: /hub/health
- port: http
----
-# Source: jupyterhub/templates/proxy/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: proxy
- labels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- strategy:
- rollingUpdate: null
- type: Recreate
- template:
- metadata:
- labels:
- component: proxy
- app: jupyterhub
- release: jupyterhub
- hub.jupyter.org/network-access-hub: "true"
- hub.jupyter.org/network-access-singleuser: "true"
- annotations:
- # We want to restart proxy only if the auth token changes
- # Other changes to the hub config should not restart.
- # We truncate to 4 chars to avoid leaking auth token info,
- # since someone could brute force the hash to obtain the token
- #
- # Note that if auth_token has to be generated at random, it will be
- # generated at random here separately from being generated at random in
- # the k8s Secret template. This will cause this annotation to change to
- # match the k8s Secret during the first upgrade following an auth_token
- # was generated.
- checksum/auth-token: "dc85"
- checksum/proxy-secret: "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
- spec:
- terminationGracePeriodSeconds: 60
- tolerations:
- - effect: NoSchedule
- key: hub.jupyter.org/dedicated
- operator: Equal
- value: core
- - effect: NoSchedule
- key: hub.jupyter.org_dedicated
- operator: Equal
- value: core
- affinity:
- nodeAffinity:
- preferredDuringSchedulingIgnoredDuringExecution:
- - weight: 100
- preference:
- matchExpressions:
- - key: hub.jupyter.org/node-purpose
- operator: In
- values: [core]
- containers:
- - name: chp
- image: jupyterhub/configurable-http-proxy:4.5.3
- command:
- - configurable-http-proxy
- - "--ip="
- - "--api-ip="
- - --api-port=8001
- - --default-target=http://hub:$(HUB_SERVICE_PORT)
- - --error-target=http://hub:$(HUB_SERVICE_PORT)/hub/error
- - --port=8000
- env:
- - name: CONFIGPROXY_AUTH_TOKEN
- valueFrom:
- secretKeyRef:
- # NOTE: References the chart managed k8s Secret even if
- # hub.existingSecret is specified to avoid using the
- # lookup function on the user managed k8s Secret.
- name: hub
- key: hub.config.ConfigurableHTTPProxy.auth_token
- ports:
- - name: http
- containerPort: 8000
- - name: api
- containerPort: 8001
- livenessProbe:
- initialDelaySeconds: 60
- periodSeconds: 10
- timeoutSeconds: 3
- failureThreshold: 30
- httpGet:
- path: /_chp_healthz
- port: http
- scheme: HTTP
- readinessProbe:
- initialDelaySeconds: 0
- periodSeconds: 2
- timeoutSeconds: 1
- failureThreshold: 1000
- httpGet:
- path: /_chp_healthz
- port: http
- scheme: HTTP
- securityContext:
- allowPrivilegeEscalation: false
- runAsGroup: 65534
- runAsUser: 65534
----
-# Source: jupyterhub/templates/scheduling/user-scheduler/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: user-scheduler
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- heritage: Helm
-spec:
- replicas: 2
- selector:
- matchLabels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- template:
- metadata:
- labels:
- component: user-scheduler
- app: jupyterhub
- release: jupyterhub
- annotations:
- checksum/config-map: 76e4e4553a55e750120e64d77985197755aa50907fc8f007a8348bc75694c64b
- spec:
- serviceAccountName: user-scheduler
- tolerations:
- - effect: NoSchedule
- key: hub.jupyter.org/dedica...*[Comment body truncated]* |
🦙 MegaLinter status: ✅ SUCCESS
See detailed report in MegaLinter reports |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
area/cluster
Changes made in the cluster directory
renovate/helm
size/XS
Denotes a PR that changes 0-9 lines, ignoring generated files.
type/major
0 participants
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.0.0
->4.0.0
Warning
Some dependencies could not be looked up. Check the Dependency Dashboard for more information.
Release Notes
jupyterhub/zero-to-jupyterhub-k8s (jupyterhub)
v4.0.0
Compare Source
Please see the changelog for details.
v3.3.8
Compare Source
Please see the changelog for details.
v3.3.7
Compare Source
Please see the changelog for details.
v3.3.6
Compare Source
Please see the changelog for details.
v3.3.5
Compare Source
Please see the changelog for details.
v3.3.4
Compare Source
Please see the changelog for details.
v3.3.3
Compare Source
Please see the changelog for details.
v3.3.2
Compare Source
Please see the changelog for details.
v3.3.1
Compare Source
Please see the changelog for details.
v3.3.0
Compare Source
Please see the changelog for details.
v3.2.1
Compare Source
Please see the changelog for details.
v3.2.0
Compare Source
Please see the changelog for details.
v3.1.0
Compare Source
Please see the changelog for details.
v3.0.3
Compare Source
Please see the changelog for details.
v3.0.2
Compare Source
Please see the changelog for details.
v3.0.1
Compare Source
Please see the changelog for details.
v3.0.0
Compare Source
Please see the changelog for details.
Configuration
📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
This PR was generated by Mend Renovate. View the repository job log.