mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-07-28 09:11:18 +00:00
Merge branch 'master' into 2020-05-ardan
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
# This file is based on the following manifest:
|
||||||
|
# https://github.com/kubernetes/dashboard/blob/master/aio/deploy/recommended.yaml
|
||||||
|
# It adds the "skip login" flag, as well as an insecure hack to defeat SSL.
|
||||||
|
# As its name implies, it is INSECURE and you should not use it in production,
|
||||||
|
# or on clusters that contain any kind of important or sensitive data, or on
|
||||||
|
# clusters that have a life span of more than a few hours.
|
||||||
|
|
||||||
# Copyright 2017 The Kubernetes Authors.
|
# Copyright 2017 The Kubernetes Authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -187,7 +194,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: kubernetes-dashboard
|
- name: kubernetes-dashboard
|
||||||
image: kubernetesui/dashboard:v2.0.0-rc2
|
image: kubernetesui/dashboard:v2.0.0
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8443
|
- containerPort: 8443
|
||||||
@@ -226,7 +233,7 @@ spec:
|
|||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
serviceAccountName: kubernetes-dashboard
|
serviceAccountName: kubernetes-dashboard
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
"beta.kubernetes.io/os": linux
|
"kubernetes.io/os": linux
|
||||||
# Comment the following tolerations if Dashboard must not be deployed on master
|
# Comment the following tolerations if Dashboard must not be deployed on master
|
||||||
tolerations:
|
tolerations:
|
||||||
- key: node-role.kubernetes.io/master
|
- key: node-role.kubernetes.io/master
|
||||||
@@ -272,7 +279,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: dashboard-metrics-scraper
|
- name: dashboard-metrics-scraper
|
||||||
image: kubernetesui/metrics-scraper:v1.0.2
|
image: kubernetesui/metrics-scraper:v1.0.4
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8000
|
- containerPort: 8000
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
@@ -293,7 +300,7 @@ spec:
|
|||||||
runAsGroup: 2001
|
runAsGroup: 2001
|
||||||
serviceAccountName: kubernetes-dashboard
|
serviceAccountName: kubernetes-dashboard
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
"beta.kubernetes.io/os": linux
|
"kubernetes.io/os": linux
|
||||||
# Comment the following tolerations if Dashboard must not be deployed on master
|
# Comment the following tolerations if Dashboard must not be deployed on master
|
||||||
tolerations:
|
tolerations:
|
||||||
- key: node-role.kubernetes.io/master
|
- key: node-role.kubernetes.io/master
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# This is a copy of the following file:
|
||||||
|
# https://github.com/kubernetes/dashboard/blob/master/aio/deploy/recommended.yaml
|
||||||
|
|
||||||
# Copyright 2017 The Kubernetes Authors.
|
# Copyright 2017 The Kubernetes Authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -12,19 +15,12 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# ------------------- Dashboard Secret ------------------- #
|
|
||||||
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
name: kubernetes-dashboard
|
||||||
k8s-app: kubernetes-dashboard
|
|
||||||
name: kubernetes-dashboard-certs
|
|
||||||
namespace: kube-system
|
|
||||||
type: Opaque
|
|
||||||
|
|
||||||
---
|
---
|
||||||
# ------------------- Dashboard Service Account ------------------- #
|
|
||||||
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
@@ -32,62 +28,147 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
k8s-app: kubernetes-dashboard
|
k8s-app: kubernetes-dashboard
|
||||||
name: kubernetes-dashboard
|
name: kubernetes-dashboard
|
||||||
namespace: kube-system
|
namespace: kubernetes-dashboard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 443
|
||||||
|
targetPort: 8443
|
||||||
|
selector:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-certs
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
type: Opaque
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-csrf
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
csrf: ""
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-key-holder
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
type: Opaque
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-settings
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
|
||||||
---
|
---
|
||||||
# ------------------- Dashboard Role & Role Binding ------------------- #
|
|
||||||
|
|
||||||
kind: Role
|
kind: Role
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: kubernetes-dashboard-minimal
|
labels:
|
||||||
namespace: kube-system
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
rules:
|
rules:
|
||||||
# Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["secrets"]
|
|
||||||
verbs: ["create"]
|
|
||||||
# Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["configmaps"]
|
|
||||||
verbs: ["create"]
|
|
||||||
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
|
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["secrets"]
|
resources: ["secrets"]
|
||||||
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
|
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
|
||||||
verbs: ["get", "update", "delete"]
|
verbs: ["get", "update", "delete"]
|
||||||
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
|
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["configmaps"]
|
resources: ["configmaps"]
|
||||||
resourceNames: ["kubernetes-dashboard-settings"]
|
resourceNames: ["kubernetes-dashboard-settings"]
|
||||||
verbs: ["get", "update"]
|
verbs: ["get", "update"]
|
||||||
# Allow Dashboard to get metrics from heapster.
|
# Allow Dashboard to get metrics.
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services"]
|
||||||
resourceNames: ["heapster"]
|
resourceNames: ["heapster", "dashboard-metrics-scraper"]
|
||||||
verbs: ["proxy"]
|
verbs: ["proxy"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services/proxy"]
|
resources: ["services/proxy"]
|
||||||
resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
|
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
|
||||||
verbs: ["get"]
|
verbs: ["get"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
rules:
|
||||||
|
# Allow Metrics Scraper to get metrics from the Metrics server
|
||||||
|
- apiGroups: ["metrics.k8s.io"]
|
||||||
|
resources: ["pods", "nodes"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: kubernetes-dashboard-minimal
|
labels:
|
||||||
namespace: kube-system
|
k8s-app: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: Role
|
kind: Role
|
||||||
name: kubernetes-dashboard-minimal
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kubernetes-dashboard
|
name: kubernetes-dashboard
|
||||||
namespace: kube-system
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
|
||||||
---
|
---
|
||||||
# ------------------- Dashboard Deployment ------------------- #
|
|
||||||
|
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
@@ -95,7 +176,7 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
k8s-app: kubernetes-dashboard
|
k8s-app: kubernetes-dashboard
|
||||||
name: kubernetes-dashboard
|
name: kubernetes-dashboard
|
||||||
namespace: kube-system
|
namespace: kubernetes-dashboard
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
revisionHistoryLimit: 10
|
revisionHistoryLimit: 10
|
||||||
@@ -108,55 +189,117 @@ spec:
|
|||||||
k8s-app: kubernetes-dashboard
|
k8s-app: kubernetes-dashboard
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: kubernetes-dashboard
|
- name: kubernetes-dashboard
|
||||||
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
|
image: kubernetesui/dashboard:v2.0.0
|
||||||
ports:
|
imagePullPolicy: Always
|
||||||
- containerPort: 8443
|
ports:
|
||||||
protocol: TCP
|
- containerPort: 8443
|
||||||
args:
|
protocol: TCP
|
||||||
- --auto-generate-certificates
|
args:
|
||||||
# Uncomment the following line to manually specify Kubernetes API server Host
|
- --auto-generate-certificates
|
||||||
# If not specified, Dashboard will attempt to auto discover the API server and connect
|
- --namespace=kubernetes-dashboard
|
||||||
# to it. Uncomment only if the default does not work.
|
# Uncomment the following line to manually specify Kubernetes API server Host
|
||||||
# - --apiserver-host=http://my-address:port
|
# If not specified, Dashboard will attempt to auto discover the API server and connect
|
||||||
volumeMounts:
|
# to it. Uncomment only if the default does not work.
|
||||||
- name: kubernetes-dashboard-certs
|
# - --apiserver-host=http://my-address:port
|
||||||
mountPath: /certs
|
volumeMounts:
|
||||||
# Create on-disk volume to store exec logs
|
- name: kubernetes-dashboard-certs
|
||||||
- mountPath: /tmp
|
mountPath: /certs
|
||||||
name: tmp-volume
|
# Create on-disk volume to store exec logs
|
||||||
livenessProbe:
|
- mountPath: /tmp
|
||||||
httpGet:
|
name: tmp-volume
|
||||||
scheme: HTTPS
|
livenessProbe:
|
||||||
path: /
|
httpGet:
|
||||||
port: 8443
|
scheme: HTTPS
|
||||||
initialDelaySeconds: 30
|
path: /
|
||||||
timeoutSeconds: 30
|
port: 8443
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 30
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsUser: 1001
|
||||||
|
runAsGroup: 2001
|
||||||
volumes:
|
volumes:
|
||||||
- name: kubernetes-dashboard-certs
|
- name: kubernetes-dashboard-certs
|
||||||
secret:
|
secret:
|
||||||
secretName: kubernetes-dashboard-certs
|
secretName: kubernetes-dashboard-certs
|
||||||
- name: tmp-volume
|
- name: tmp-volume
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
serviceAccountName: kubernetes-dashboard
|
serviceAccountName: kubernetes-dashboard
|
||||||
|
nodeSelector:
|
||||||
|
"kubernetes.io/os": linux
|
||||||
# Comment the following tolerations if Dashboard must not be deployed on master
|
# Comment the following tolerations if Dashboard must not be deployed on master
|
||||||
tolerations:
|
tolerations:
|
||||||
- key: node-role.kubernetes.io/master
|
- key: node-role.kubernetes.io/master
|
||||||
effect: NoSchedule
|
effect: NoSchedule
|
||||||
|
|
||||||
---
|
---
|
||||||
# ------------------- Dashboard Service ------------------- #
|
|
||||||
|
|
||||||
kind: Service
|
kind: Service
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
k8s-app: kubernetes-dashboard
|
k8s-app: dashboard-metrics-scraper
|
||||||
name: kubernetes-dashboard
|
name: dashboard-metrics-scraper
|
||||||
namespace: kube-system
|
namespace: kubernetes-dashboard
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 443
|
- port: 8000
|
||||||
targetPort: 8443
|
targetPort: 8000
|
||||||
selector:
|
selector:
|
||||||
k8s-app: kubernetes-dashboard
|
k8s-app: dashboard-metrics-scraper
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
kind: Deployment
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: dashboard-metrics-scraper
|
||||||
|
name: dashboard-metrics-scraper
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 10
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
k8s-app: dashboard-metrics-scraper
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: dashboard-metrics-scraper
|
||||||
|
annotations:
|
||||||
|
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: dashboard-metrics-scraper
|
||||||
|
image: kubernetesui/metrics-scraper:v1.0.4
|
||||||
|
ports:
|
||||||
|
- containerPort: 8000
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
scheme: HTTP
|
||||||
|
path: /
|
||||||
|
port: 8000
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 30
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp
|
||||||
|
name: tmp-volume
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsUser: 1001
|
||||||
|
runAsGroup: 2001
|
||||||
|
serviceAccountName: kubernetes-dashboard
|
||||||
|
nodeSelector:
|
||||||
|
"kubernetes.io/os": linux
|
||||||
|
# Comment the following tolerations if Dashboard must not be deployed on master
|
||||||
|
tolerations:
|
||||||
|
- key: node-role.kubernetes.io/master
|
||||||
|
effect: NoSchedule
|
||||||
|
volumes:
|
||||||
|
- name: tmp-volume
|
||||||
|
emptyDir: {}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ spec:
|
|||||||
initContainers:
|
initContainers:
|
||||||
- name: git
|
- name: git
|
||||||
image: alpine
|
image: alpine
|
||||||
command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
command: [ "sh", "-c", "apk add git && sleep 5 && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: www
|
- name: www
|
||||||
mountPath: /www/
|
mountPath: /www/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: policy/v1beta1
|
||||||
kind: PodSecurityPolicy
|
kind: PodSecurityPolicy
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
|||||||
@@ -8,24 +8,24 @@ metadata:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: users:jean.doe
|
name: user=jean.doe
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [ certificates.k8s.io ]
|
- apiGroups: [ certificates.k8s.io ]
|
||||||
resources: [ certificatesigningrequests ]
|
resources: [ certificatesigningrequests ]
|
||||||
verbs: [ create ]
|
verbs: [ create ]
|
||||||
- apiGroups: [ certificates.k8s.io ]
|
- apiGroups: [ certificates.k8s.io ]
|
||||||
resourceNames: [ users:jean.doe ]
|
resourceNames: [ user=jean.doe ]
|
||||||
resources: [ certificatesigningrequests ]
|
resources: [ certificatesigningrequests ]
|
||||||
verbs: [ get, create, delete, watch ]
|
verbs: [ get, create, delete, watch ]
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: users:jean.doe
|
name: user=jean.doe
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
name: users:jean.doe
|
name: user=jean.doe
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: jean.doe
|
name: jean.doe
|
||||||
@@ -246,6 +246,14 @@ EOF"
|
|||||||
helm completion bash | sudo tee /etc/bash_completion.d/helm
|
helm completion bash | sudo tee /etc/bash_completion.d/helm
|
||||||
fi"
|
fi"
|
||||||
|
|
||||||
|
# Install kustomize
|
||||||
|
pssh "
|
||||||
|
if [ ! -x /usr/local/bin/kustomize ]; then
|
||||||
|
curl -L https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.1_linux_amd64.tar.gz |
|
||||||
|
sudo tar -C /usr/local/bin -zx kustomize
|
||||||
|
echo complete -C /usr/local/bin/kustomize kustomize | sudo tee /etc/bash_completion.d/kustomize
|
||||||
|
fi"
|
||||||
|
|
||||||
# Install ship
|
# Install ship
|
||||||
pssh "
|
pssh "
|
||||||
if [ ! -x /usr/local/bin/ship ]; then
|
if [ ! -x /usr/local/bin/ship ]; then
|
||||||
|
|||||||
@@ -132,11 +132,33 @@ For a user named `jean.doe`, we will have:
|
|||||||
|
|
||||||
- ServiceAccount `jean.doe` in Namespace `users`
|
- ServiceAccount `jean.doe` in Namespace `users`
|
||||||
|
|
||||||
- CertificateSigningRequest `users:jean.doe`
|
- CertificateSigningRequest `user=jean.doe`
|
||||||
|
|
||||||
- ClusterRole `users:jean.doe` giving read/write access to that CSR
|
- ClusterRole `user=jean.doe` giving read/write access to that CSR
|
||||||
|
|
||||||
- ClusterRoleBinding `users:jean.doe` binding ClusterRole and ServiceAccount
|
- ClusterRoleBinding `user=jean.doe` binding ClusterRole and ServiceAccount
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
class: extra-details
|
||||||
|
|
||||||
|
## About resource name constraints
|
||||||
|
|
||||||
|
- Most Kubernetes identifiers and names are fairly restricted
|
||||||
|
|
||||||
|
- They generally are DNS-1123 *labels* or *subdomains* (from [RFC 1123](https://tools.ietf.org/html/rfc1123))
|
||||||
|
|
||||||
|
- A label is lowercase letters, numbers, dashes; can't start or finish with a dash
|
||||||
|
|
||||||
|
- A subdomain is one or multiple labels separated by dots
|
||||||
|
|
||||||
|
- Some resources have more relaxed constraints, and can be "path segment names"
|
||||||
|
|
||||||
|
(uppercase are allowed, as well as some characters like `#:?!,_`)
|
||||||
|
|
||||||
|
- This includes RBAC objects (like Roles, RoleBindings...) and CSRs
|
||||||
|
|
||||||
|
- See the [Identifiers and Names](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md) design document and the [Object Names and IDs](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#path-segment-names) documentation page for more details
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -153,7 +175,7 @@ For a user named `jean.doe`, we will have:
|
|||||||
|
|
||||||
- Create the ServiceAccount, ClusterRole, ClusterRoleBinding for `jean.doe`:
|
- Create the ServiceAccount, ClusterRole, ClusterRoleBinding for `jean.doe`:
|
||||||
```bash
|
```bash
|
||||||
kubectl apply -f ~/container.training/k8s/users:jean.doe.yaml
|
kubectl apply -f ~/container.training/k8s/user=jean.doe.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
]
|
]
|
||||||
@@ -195,7 +217,13 @@ For a user named `jean.doe`, we will have:
|
|||||||
|
|
||||||
- Add a new context using that identity:
|
- Add a new context using that identity:
|
||||||
```bash
|
```bash
|
||||||
kubectl config set-context jean.doe --user=token:jean.doe --cluster=kubernetes
|
kubectl config set-context jean.doe --user=token:jean.doe --cluster=`kubernetes`
|
||||||
|
```
|
||||||
|
(Make sure to adapt the cluster name if yours is different!)
|
||||||
|
|
||||||
|
- Use that context:
|
||||||
|
```bash
|
||||||
|
kubectl config use-context jean.doe
|
||||||
```
|
```
|
||||||
|
|
||||||
]
|
]
|
||||||
@@ -216,7 +244,7 @@ For a user named `jean.doe`, we will have:
|
|||||||
|
|
||||||
- Try to access "our" CertificateSigningRequest:
|
- Try to access "our" CertificateSigningRequest:
|
||||||
```bash
|
```bash
|
||||||
kubectl get csr users:jean.doe
|
kubectl get csr user=jean.doe
|
||||||
```
|
```
|
||||||
(This should tell us "NotFound")
|
(This should tell us "NotFound")
|
||||||
|
|
||||||
@@ -273,7 +301,7 @@ The command above generates:
|
|||||||
apiVersion: certificates.k8s.io/v1beta1
|
apiVersion: certificates.k8s.io/v1beta1
|
||||||
kind: CertificateSigningRequest
|
kind: CertificateSigningRequest
|
||||||
metadata:
|
metadata:
|
||||||
name: users:jean.doe
|
name: user=jean.doe
|
||||||
spec:
|
spec:
|
||||||
request: $(base64 -w0 < csr.pem)
|
request: $(base64 -w0 < csr.pem)
|
||||||
usages:
|
usages:
|
||||||
@@ -324,12 +352,12 @@ The command above generates:
|
|||||||
|
|
||||||
- Inspect the CSR:
|
- Inspect the CSR:
|
||||||
```bash
|
```bash
|
||||||
kubectl describe csr users:jean.doe
|
kubectl describe csr user=jean.doe
|
||||||
```
|
```
|
||||||
|
|
||||||
- Approve it:
|
- Approve it:
|
||||||
```bash
|
```bash
|
||||||
kubectl certificate approve users:jean.doe
|
kubectl certificate approve user=jean.doe
|
||||||
```
|
```
|
||||||
|
|
||||||
]
|
]
|
||||||
@@ -347,7 +375,7 @@ The command above generates:
|
|||||||
|
|
||||||
- Retrieve the updated CSR object and extract the certificate:
|
- Retrieve the updated CSR object and extract the certificate:
|
||||||
```bash
|
```bash
|
||||||
kubectl get csr users:jean.doe \
|
kubectl get csr user=jean.doe \
|
||||||
-o jsonpath={.status.certificate} \
|
-o jsonpath={.status.certificate} \
|
||||||
| base64 -d > cert.pem
|
| base64 -d > cert.pem
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ This creates a basic chart in the directory `helmcoins`.
|
|||||||
helm install COMPONENT-NAME CHART-DIRECTORY
|
helm install COMPONENT-NAME CHART-DIRECTORY
|
||||||
```
|
```
|
||||||
|
|
||||||
- We can also use the following command, which is idempotent:
|
- We can also use the following command, which is *idempotent*:
|
||||||
```bash
|
```bash
|
||||||
helm upgrade COMPONENT-NAME CHART-DIRECTORY --install
|
helm upgrade COMPONENT-NAME CHART-DIRECTORY --install
|
||||||
```
|
```
|
||||||
@@ -139,6 +139,28 @@ This creates a basic chart in the directory `helmcoins`.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
class: extra-details
|
||||||
|
|
||||||
|
## "Idempotent"
|
||||||
|
|
||||||
|
- Idempotent = that can be applied multiple times without changing the result
|
||||||
|
|
||||||
|
(the word is commonly used in maths and computer science)
|
||||||
|
|
||||||
|
- In this context, this means:
|
||||||
|
|
||||||
|
- if the action (installing the chart) wasn't done, do it
|
||||||
|
|
||||||
|
- if the action was already done, don't do anything
|
||||||
|
|
||||||
|
- Ideally, when such an action fails, it can be retried safely
|
||||||
|
|
||||||
|
(as opposed to, e.g., installing a new release each time we run it)
|
||||||
|
|
||||||
|
- Other example: `kubectl -f some-file.yaml`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Checking what we've done
|
## Checking what we've done
|
||||||
|
|
||||||
- Let's see if DockerCoins is working!
|
- Let's see if DockerCoins is working!
|
||||||
|
|||||||
@@ -18,6 +18,25 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## CNCF graduation status
|
||||||
|
|
||||||
|
- On April 30th 2020, Helm was the 10th project to *graduate* within the CNCF
|
||||||
|
|
||||||
|
.emoji[🎉]
|
||||||
|
|
||||||
|
(alongside Containerd, Prometheus, and Kubernetes itself)
|
||||||
|
|
||||||
|
- This is an acknowledgement by the CNCF for projects that
|
||||||
|
|
||||||
|
*demonstrate thriving adoption, an open governance process,
|
||||||
|
<br/>
|
||||||
|
and a strong commitment to community, sustainability, and inclusivity.*
|
||||||
|
|
||||||
|
- See [CNCF announcement](https://www.cncf.io/announcement/2020/04/30/cloud-native-computing-foundation-announces-helm-graduation/)
|
||||||
|
and [Helm announcement](https://helm.sh/blog/celebrating-helms-cncf-graduation/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Helm concepts
|
## Helm concepts
|
||||||
|
|
||||||
- `helm` is a CLI tool
|
- `helm` is a CLI tool
|
||||||
|
|||||||
@@ -8,45 +8,164 @@
|
|||||||
|
|
||||||
- They are left untouched by Kustomize
|
- They are left untouched by Kustomize
|
||||||
|
|
||||||
- Kustomize lets us define *overlays* that extend or change the resource files
|
- Kustomize lets us define *kustomizations*
|
||||||
|
|
||||||
|
- A *kustomization* is conceptually similar to a *layer*
|
||||||
|
|
||||||
|
- Technically, a *kustomization* is a file named `kustomization.yaml`
|
||||||
|
|
||||||
|
(or a directory containing that files + additional files)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Differences with Helm
|
## What's in a kustomization
|
||||||
|
|
||||||
- Helm charts use placeholders `{{ like.this }}`
|
- A kustomization can do any combination of the following:
|
||||||
|
|
||||||
- Kustomize "bases" are standard Kubernetes YAML
|
- include other kustomizations
|
||||||
|
|
||||||
- It is possible to use an existing set of YAML as a Kustomize base
|
- include Kubernetes resources defined in YAML files
|
||||||
|
|
||||||
- As a result, writing a Helm chart is more work ...
|
- patch Kubernetes resources (change values)
|
||||||
|
|
||||||
- ... But Helm charts are also more powerful; e.g. they can:
|
- add labels or annotations to all resources
|
||||||
|
|
||||||
- use flags to conditionally include resources or blocks
|
- specify ConfigMaps and Secrets from literal values or local files
|
||||||
|
|
||||||
- check if a given Kubernetes API group is supported
|
(... And a few more advanced features that we won't cover today!)
|
||||||
|
|
||||||
- [and much more](https://helm.sh/docs/chart_template_guide/)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Kustomize concepts
|
## A simple kustomization
|
||||||
|
|
||||||
- Kustomize needs a `kustomization.yaml` file
|
This features a Deployment, Service, and Ingress (in separate files),
|
||||||
|
and a couple of patches (to change the number of replicas and the hostname
|
||||||
|
used in the Ingress).
|
||||||
|
|
||||||
- That file can be a *base* or a *variant*
|
```yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- scale-deployment.yaml
|
||||||
|
- ingress-hostname.yaml
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
```
|
||||||
|
|
||||||
- If it's a *base*:
|
On the next slide, let's see a more complex example ...
|
||||||
|
|
||||||
- it lists YAML resource files to use
|
---
|
||||||
|
|
||||||
- If it's a *variant* (or *overlay*):
|
```yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
commonLabels:
|
||||||
|
add-this-to-all-my-resources: please
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- prod-scaling.yaml
|
||||||
|
- prod-healthchecks.yaml
|
||||||
|
bases:
|
||||||
|
- api/
|
||||||
|
- frontend/
|
||||||
|
- db/
|
||||||
|
- github.com/example/app?ref=tag-or-branch
|
||||||
|
resources:
|
||||||
|
- ingress.yaml
|
||||||
|
- permissions.yaml
|
||||||
|
configMapGenerator:
|
||||||
|
- name: appconfig
|
||||||
|
files:
|
||||||
|
- global.conf
|
||||||
|
- local.conf=prod.conf
|
||||||
|
```
|
||||||
|
|
||||||
- it refers to (at least) one *base*
|
---
|
||||||
|
|
||||||
- and some *patches*
|
## Glossary
|
||||||
|
|
||||||
|
- A *base* is a kustomization that is referred to by other kustomizations
|
||||||
|
|
||||||
|
- An *overlay* is a kustomization that refers to other kustomizations
|
||||||
|
|
||||||
|
- A kustomization can be both a base and an overlay at the same time
|
||||||
|
|
||||||
|
(a kustomization can refer to another, which can refer to a third)
|
||||||
|
|
||||||
|
- A *patch* describes how to alter an existing resource
|
||||||
|
|
||||||
|
(e.g. to change the image in a Deployment; or scaling parameters; etc.)
|
||||||
|
|
||||||
|
- A *variant* is the final outcome of applying bases + overlays
|
||||||
|
|
||||||
|
(See the [kustomize glossary](https://github.com/kubernetes-sigs/kustomize/blob/master/docs/glossary.md) for more definitions!)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What Kustomize *cannot* do
|
||||||
|
|
||||||
|
- By design, there are a number of things that Kustomize won't do
|
||||||
|
|
||||||
|
- For instance:
|
||||||
|
|
||||||
|
- using command-line arguments or environment variables to generate a variant
|
||||||
|
|
||||||
|
- overlays can only *add* resources, not *remove* them
|
||||||
|
|
||||||
|
- See the full list of [eschewed features](https://github.com/kubernetes-sigs/kustomize/blob/master/docs/eschewedFeatures.md) for more details
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kustomize workflows
|
||||||
|
|
||||||
|
- The Kustomize documentation proposes two different workflows
|
||||||
|
|
||||||
|
- *Bespoke configuration*
|
||||||
|
|
||||||
|
- base and overlays managed by the same team
|
||||||
|
|
||||||
|
- *Off-the-shelf configuration* (OTS)
|
||||||
|
|
||||||
|
- base and overlays managed by different teams
|
||||||
|
|
||||||
|
- base is regularly updated by "upstream" (e.g. a vendor)
|
||||||
|
|
||||||
|
- our overlays and patches should (hopefully!) apply cleanly
|
||||||
|
|
||||||
|
- we may regularly update the base, or use a remote base
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Remote bases
|
||||||
|
|
||||||
|
- Kustomize can fetch remote bases using Hashicorp go-getter library
|
||||||
|
|
||||||
|
- Examples:
|
||||||
|
|
||||||
|
github.com/jpetazzo/kubercoins (remote git repository)
|
||||||
|
|
||||||
|
github.com/jpetazzo/kubercoins?ref=kustomize (specific tag or branch)
|
||||||
|
|
||||||
|
https://releases.hello.io/k/1.0.zip (remote archive)
|
||||||
|
|
||||||
|
https://releases.hello.io/k/1.0.zip//some-subdir (subdirectory in archive)
|
||||||
|
|
||||||
|
- See [hashicorp/go-getter URL format docs](https://github.com/hashicorp/go-getter#url-format) for more examples
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Managing `kustomization.yaml`
|
||||||
|
|
||||||
|
- There are many ways to manage `kustomization.yaml` files, including:
|
||||||
|
|
||||||
|
- web wizards like [Replicated Ship](https://www.replicated.com/ship/)
|
||||||
|
|
||||||
|
- the `kustomize` CLI
|
||||||
|
|
||||||
|
- opening the file with our favorite text editor
|
||||||
|
|
||||||
|
- Let's see these in action!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -200,7 +319,62 @@
|
|||||||
|
|
||||||
Note: it might take a minute or two for the worker to start.
|
Note: it might take a minute or two for the worker to start.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Working with the `kustomize` CLI
|
||||||
|
|
||||||
|
- This is another way to get started
|
||||||
|
|
||||||
|
- General workflow:
|
||||||
|
|
||||||
|
`kustomize create` to generate an empty `kustomization.yaml` file
|
||||||
|
|
||||||
|
`kustomize edit add resource` to add Kubernetes YAML files to it
|
||||||
|
|
||||||
|
`kustomize edit add patch` to add patches to said resources
|
||||||
|
|
||||||
|
`kustomize build | kubectl apply -f-` or `kubectl apply -k .`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `kubectl apply -k`
|
||||||
|
|
||||||
|
- Kustomize has been integrated in `kubectl`
|
||||||
|
|
||||||
|
- The `kustomize` tool is still needed if we want to use `create`, `edit`, ...
|
||||||
|
|
||||||
|
- Also, warning: `kubectl apply -k` is a slightly older version than `kustomize`!
|
||||||
|
|
||||||
|
- In recent versions of `kustomize`, bases can be listed in `resources`
|
||||||
|
|
||||||
|
(and `kustomize edit add base` will add its arguments to `resources`)
|
||||||
|
|
||||||
|
- `kubectl apply -k` requires bases to be listed in `bases`
|
||||||
|
|
||||||
|
(so after using `kustomize edit add base`, we need to fix `kustomization.yaml`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Differences with Helm
|
||||||
|
|
||||||
|
- Helm charts use placeholders `{{ like.this }}`
|
||||||
|
|
||||||
|
- Kustomize "bases" are standard Kubernetes YAML
|
||||||
|
|
||||||
|
- It is possible to use an existing set of YAML as a Kustomize base
|
||||||
|
|
||||||
|
- As a result, writing a Helm chart is more work ...
|
||||||
|
|
||||||
|
- ... But Helm charts are also more powerful; e.g. they can:
|
||||||
|
|
||||||
|
- use flags to conditionally include resources or blocks
|
||||||
|
|
||||||
|
- check if a given Kubernetes API group is supported
|
||||||
|
|
||||||
|
- [and much more](https://helm.sh/docs/chart_template_guide/)
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
:EN:- Packaging and running apps with Kustomize
|
:EN:- Packaging and running apps with Kustomize
|
||||||
:FR:- *Packaging* d'applications avec Kustomize
|
:FR:- *Packaging* d'applications avec Kustomize
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
- Create a Deployment:
|
- Create a Deployment:
|
||||||
```bash
|
```bash
|
||||||
kubectl create deployment web --image=nginx
|
kubectl create deployment clock --image=jpetazzo/clock
|
||||||
```
|
```
|
||||||
|
|
||||||
- Look at its annotations and labels:
|
- Look at its annotations and labels:
|
||||||
```bash
|
```bash
|
||||||
kubectl describe deployment web
|
kubectl describe deployment clock
|
||||||
```
|
```
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Exactly what we need!
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Installing Stern
|
## Checking if Stern is installed
|
||||||
|
|
||||||
- Run `stern` (without arguments) to check if it's installed:
|
- Run `stern` (without arguments) to check if it's installed:
|
||||||
|
|
||||||
@@ -57,7 +57,17 @@ Exactly what we need!
|
|||||||
stern pod-query [flags]
|
stern pod-query [flags]
|
||||||
```
|
```
|
||||||
|
|
||||||
- If it is not installed, the easiest method is to download a [binary release](https://github.com/wercker/stern/releases)
|
- If it's missing, let's see how to install it
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installing Stern
|
||||||
|
|
||||||
|
- Stern is written in Go, and Go programs are usually shipped as a single binary
|
||||||
|
|
||||||
|
- We just need to download that binary and put it in our `PATH`!
|
||||||
|
|
||||||
|
- Binary releases are available [here](https://github.com/wercker/stern/releases) on GitHub
|
||||||
|
|
||||||
- The following commands will install Stern on a Linux Intel 64 bit machine:
|
- The following commands will install Stern on a Linux Intel 64 bit machine:
|
||||||
```bash
|
```bash
|
||||||
@@ -66,7 +76,7 @@ Exactly what we need!
|
|||||||
sudo chmod +x /usr/local/bin/stern
|
sudo chmod +x /usr/local/bin/stern
|
||||||
```
|
```
|
||||||
|
|
||||||
- On OS X, just `brew install stern`
|
- On macOS, we can also `brew install stern` or `port install stern`
|
||||||
|
|
||||||
<!-- ##VERSION## -->
|
<!-- ##VERSION## -->
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,7 @@
|
|||||||
|
|
||||||
- Try to create a Deployment:
|
- Try to create a Deployment:
|
||||||
```bash
|
```bash
|
||||||
kubectl run testpsp2 --image=nginx
|
kubectl create deployment testpsp2 --image=nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
- Look at existing resources:
|
- Look at existing resources:
|
||||||
@@ -350,7 +350,7 @@ We can get hints at what's happening by looking at the ReplicaSet and Events.
|
|||||||
|
|
||||||
- Create a Deployment as well:
|
- Create a Deployment as well:
|
||||||
```bash
|
```bash
|
||||||
kubectl run testpsp4 --image=nginx
|
kubectl create deployment testpsp4 --image=nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
- Confirm that the Deployment is *not* creating any Pods:
|
- Confirm that the Deployment is *not* creating any Pods:
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ spec:
|
|||||||
initContainers:
|
initContainers:
|
||||||
- name: git
|
- name: git
|
||||||
image: alpine
|
image: alpine
|
||||||
command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
command: [ "sh", "-c", "apk add git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: www
|
- name: www
|
||||||
mountPath: /www/
|
mountPath: /www/
|
||||||
@@ -417,9 +417,12 @@ spec:
|
|||||||
|
|
||||||
.exercise[
|
.exercise[
|
||||||
|
|
||||||
- Repeat the same operation as earlier
|
- Create the pod:
|
||||||
|
```bash
|
||||||
|
kubectl create -f ~/container.training/k8s/nginx-4-with-init.yaml
|
||||||
|
```
|
||||||
|
|
||||||
(try to send HTTP requests as soon as the pod comes up)
|
- Try to send HTTP requests as soon as the pod comes up
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
```key ^D```
|
```key ^D```
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ def flatten(titles):
|
|||||||
def generatefromyaml(manifest, filename):
|
def generatefromyaml(manifest, filename):
|
||||||
manifest = yaml.safe_load(manifest)
|
manifest = yaml.safe_load(manifest)
|
||||||
|
|
||||||
|
for k in manifest:
|
||||||
|
override = os.environ.get("OVERRIDE_"+k)
|
||||||
|
if override:
|
||||||
|
manifest[k] = override
|
||||||
|
|
||||||
if "zip" not in manifest:
|
if "zip" not in manifest:
|
||||||
if manifest["slides"].endswith('/'):
|
if manifest["slides"].endswith('/'):
|
||||||
manifest["zip"] = manifest["slides"] + "slides.zip"
|
manifest["zip"] = manifest["slides"] + "slides.zip"
|
||||||
|
|||||||
Reference in New Issue
Block a user