Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
30375b21
Commit
30375b21
authored
Feb 01, 2016
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #19776 from justinsb/aws_sync_kubeup_gce
Auto commit by PR queue bot
parents
2746b5e4
c556e8f0
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
283 additions
and
292 deletions
+283
-292
util.sh
cluster/aws/coreos/util.sh
+0
-3
common.sh
cluster/aws/templates/common.sh
+14
-8
extract-kube-env.sh
cluster/aws/templates/extract-kube-env.sh
+27
-0
format-disks.sh
cluster/aws/templates/format-disks.sh
+4
-6
util.sh
cluster/aws/util.sh
+19
-57
common.sh
cluster/common.sh
+219
-0
util.sh
cluster/gce/util.sh
+0
-218
No files found.
cluster/aws/coreos/util.sh
View file @
30375b21
...
@@ -53,6 +53,3 @@ function check-minion() {
...
@@ -53,6 +53,3 @@ function check-minion() {
echo
"working"
echo
"working"
}
}
function
yaml-quote
{
echo
"'
$(
echo
"
${
@
}
"
|
sed
-e
"s/'/''/g"
)
'"
}
cluster/aws/templates/common.sh
View file @
30375b21
...
@@ -14,9 +14,21 @@
...
@@ -14,9 +14,21 @@
# 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.
echo
"== Refreshing package database =="
until
apt-get update
;
do
echo
"== apt-get update failed, retrying =="
sleep
5
done
apt-get update
function
apt-get-install
{
apt-get
install
--yes
curl
# Forcibly install packages (options borrowed from Salt logs).
until
apt-get
-q
-y
-o
DPkg::Options::
=
--force-confold
-o
DPkg::Options::
=
--force-confdef
install
$@
;
do
echo
"== install of packages
$@
failed, retrying =="
sleep
5
done
}
apt-get-install curl
# Retry a download until we get it.
# Retry a download until we get it.
#
#
...
@@ -44,12 +56,6 @@ install-salt() {
...
@@ -44,12 +56,6 @@ install-salt() {
return
return
fi
fi
echo
"== Refreshing package database =="
until
apt-get update
;
do
echo
"== apt-get update failed, retrying =="
sleep
5
done
mkdir
-p
/var/cache/salt-install
mkdir
-p
/var/cache/salt-install
cd
/var/cache/salt-install
cd
/var/cache/salt-install
...
...
cluster/aws/templates/extract-kube-env.sh
0 → 100644
View file @
30375b21
#!/bin/bash
# Copyright 2016 The Kubernetes Authors All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apt-get-install python-yaml
# kube-env has all the environment variables we care about, in a flat yaml format
eval
"
$(
python
-c
'
import pipes,sys,yaml
for k,v in yaml.load(sys.stdin).iteritems():
print("""readonly {var}={value}""".format(var = k, value = pipes.quote(str(v))))
print("""export {var}""".format(var = k))
'
< kube-env.yaml
)
"
cluster/aws/templates/format-disks.sh
View file @
30375b21
...
@@ -47,8 +47,6 @@ done
...
@@ -47,8 +47,6 @@ done
move_docker
=
""
move_docker
=
""
move_kubelet
=
""
move_kubelet
=
""
apt-get update
docker_storage
=
${
DOCKER_STORAGE
:-
aufs
}
docker_storage
=
${
DOCKER_STORAGE
:-
aufs
}
# Format the ephemeral disks
# Format the ephemeral disks
...
@@ -66,7 +64,7 @@ else
...
@@ -66,7 +64,7 @@ else
done
done
if
[[
${
docker_storage
}
==
"btrfs"
]]
;
then
if
[[
${
docker_storage
}
==
"btrfs"
]]
;
then
apt-get
install
--yes
btrfs-tools
apt-get
-install
btrfs-tools
if
[[
${#
block_devices
[@]
}
==
1
]]
;
then
if
[[
${#
block_devices
[@]
}
==
1
]]
;
then
echo
"One ephemeral block device found; formatting with btrfs"
echo
"One ephemeral block device found; formatting with btrfs"
...
@@ -102,7 +100,7 @@ else
...
@@ -102,7 +100,7 @@ else
# In devicemapper mode, Docker can use LVM directly
# In devicemapper mode, Docker can use LVM directly
# Also, fewer code paths are good
# Also, fewer code paths are good
echo
"Using LVM2 and ext4"
echo
"Using LVM2 and ext4"
apt-get
install
--yes
lvm2
apt-get
-install
lvm2
# Don't output spurious "File descriptor X leaked on vgcreate invocation."
# Don't output spurious "File descriptor X leaked on vgcreate invocation."
# Known bug: e.g. Ubuntu #591823
# Known bug: e.g. Ubuntu #591823
...
@@ -165,10 +163,10 @@ if [[ ${docker_storage} == "btrfs" ]]; then
...
@@ -165,10 +163,10 @@ if [[ ${docker_storage} == "btrfs" ]]; then
elif
[[
${
docker_storage
}
==
"aufs-nolvm"
||
${
docker_storage
}
==
"aufs"
]]
;
then
elif
[[
${
docker_storage
}
==
"aufs-nolvm"
||
${
docker_storage
}
==
"aufs"
]]
;
then
# Install aufs kernel module
# Install aufs kernel module
# Fix issue #14162 with extra-virtual
# Fix issue #14162 with extra-virtual
apt-get
install
--yes
linux-image-extra-
$(
uname
-r
)
linux-image-extra-virtual
apt-get
-install
linux-image-extra-
$(
uname
-r
)
linux-image-extra-virtual
# Install aufs tools
# Install aufs tools
apt-get
install
--yes
aufs-tools
apt-get
-install
aufs-tools
DOCKER_OPTS
=
"
${
DOCKER_OPTS
}
-s aufs"
DOCKER_OPTS
=
"
${
DOCKER_OPTS
}
-s aufs"
elif
[[
${
docker_storage
}
==
"devicemapper"
]]
;
then
elif
[[
${
docker_storage
}
==
"devicemapper"
]]
;
then
...
...
cluster/aws/util.sh
View file @
30375b21
...
@@ -53,6 +53,9 @@ if [[ "${KUBE_OS_DISTRIBUTION}" == "ubuntu" ]]; then
...
@@ -53,6 +53,9 @@ if [[ "${KUBE_OS_DISTRIBUTION}" == "ubuntu" ]]; then
KUBE_OS_DISTRIBUTION
=
vivid
KUBE_OS_DISTRIBUTION
=
vivid
fi
fi
# For GCE script compatability
OS_DISTRIBUTION
=
${
KUBE_OS_DISTRIBUTION
}
case
"
${
KUBE_OS_DISTRIBUTION
}
"
in
case
"
${
KUBE_OS_DISTRIBUTION
}
"
in
trusty|wheezy|jessie|vivid|coreos
)
trusty|wheezy|jessie|vivid|coreos
)
source
"
${
KUBE_ROOT
}
/cluster/aws/
${
KUBE_OS_DISTRIBUTION
}
/util.sh"
source
"
${
KUBE_ROOT
}
/cluster/aws/
${
KUBE_OS_DISTRIBUTION
}
/util.sh"
...
@@ -564,10 +567,15 @@ function ensure-temp-dir {
...
@@ -564,10 +567,15 @@ function ensure-temp-dir {
# SALT_TAR_URL
# SALT_TAR_URL
function
upload-server-tars
()
{
function
upload-server-tars
()
{
SERVER_BINARY_TAR_URL
=
SERVER_BINARY_TAR_URL
=
SERVER_BINARY_TAR_HASH
=
SALT_TAR_URL
=
SALT_TAR_URL
=
SALT_TAR_HASH
=
ensure-temp-dir
ensure-temp-dir
SERVER_BINARY_TAR_HASH
=
$(
sha1sum-file
"
${
SERVER_BINARY_TAR
}
"
)
SALT_TAR_HASH
=
$(
sha1sum-file
"
${
SALT_TAR
}
"
)
if
[[
-z
${
AWS_S3_BUCKET
-
}
]]
;
then
if
[[
-z
${
AWS_S3_BUCKET
-
}
]]
;
then
local
project_hash
=
local
project_hash
=
local
key
=
$(
aws configure get aws_access_key_id
)
local
key
=
$(
aws configure get aws_access_key_id
)
...
@@ -922,48 +930,24 @@ function start-master() {
...
@@ -922,48 +930,24 @@ function start-master() {
service_ip
=
$(
echo
"
${
octets
[*]
}
"
|
sed
's/ /./g'
)
service_ip
=
$(
echo
"
${
octets
[*]
}
"
|
sed
's/ /./g'
)
MASTER_EXTRA_SANS
=
"IP:
${
service_ip
}
,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.
${
DNS_DOMAIN
}
,DNS:
${
MASTER_NAME
}
"
MASTER_EXTRA_SANS
=
"IP:
${
service_ip
}
,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.
${
DNS_DOMAIN
}
,DNS:
${
MASTER_NAME
}
"
write-master-env
(
(
# We pipe this to the ami as a startup script in the user-data field. Requires a compatible ami
# We pipe this to the ami as a startup script in the user-data field. Requires a compatible ami
echo
"#! /bin/bash"
echo
"#! /bin/bash"
echo
"mkdir -p /var/cache/kubernetes-install"
echo
"mkdir -p /var/cache/kubernetes-install"
echo
"cd /var/cache/kubernetes-install"
echo
"cd /var/cache/kubernetes-install"
echo
"readonly SALT_MASTER='
${
MASTER_INTERNAL_IP
}
'"
echo
"readonly INSTANCE_PREFIX='
${
INSTANCE_PREFIX
}
'"
echo
"cat > kube-env.yaml << __EOF_MASTER_KUBE_ENV_YAML"
echo
"readonly NODE_INSTANCE_PREFIX='
${
NODE_INSTANCE_PREFIX
}
'"
cat
${
KUBE_TEMP
}
/master-kube-env.yaml
echo
"readonly NON_MASQUERADE_CIDR='
${
NON_MASQUERADE_CIDR
:-}
'"
# TODO: get rid of these exceptions / harmonize with common or GCE
echo
"readonly CLUSTER_IP_RANGE='
${
CLUSTER_IP_RANGE
}
'"
echo
"SALT_MASTER:
$(
yaml-quote
${
MASTER_INTERNAL_IP
:-})
"
echo
"readonly ALLOCATE_NODE_CIDRS='
${
ALLOCATE_NODE_CIDRS
}
'"
echo
"DOCKER_STORAGE:
$(
yaml-quote
${
DOCKER_STORAGE
:-})
"
echo
"readonly SERVER_BINARY_TAR_URL='
${
SERVER_BINARY_TAR_URL
}
'"
echo
"MASTER_EXTRA_SANS:
$(
yaml-quote
${
MASTER_EXTRA_SANS
:-})
"
echo
"readonly SALT_TAR_URL='
${
SALT_TAR_URL
}
'"
echo
"__EOF_MASTER_KUBE_ENV_YAML"
echo
"readonly ZONE='
${
ZONE
}
'"
echo
"readonly NUM_NODES='
${
NUM_NODES
}
'"
echo
"readonly KUBE_USER='
${
KUBE_USER
}
'"
echo
"readonly KUBE_PASSWORD='
${
KUBE_PASSWORD
}
'"
echo
"readonly SERVICE_CLUSTER_IP_RANGE='
${
SERVICE_CLUSTER_IP_RANGE
}
'"
echo
"readonly ENABLE_CLUSTER_MONITORING='
${
ENABLE_CLUSTER_MONITORING
:-
none
}
'"
echo
"readonly ENABLE_CLUSTER_LOGGING='
${
ENABLE_CLUSTER_LOGGING
:-
false
}
'"
echo
"readonly ENABLE_NODE_LOGGING='
${
ENABLE_NODE_LOGGING
:-
false
}
'"
echo
"readonly LOGGING_DESTINATION='
${
LOGGING_DESTINATION
:-}
'"
echo
"readonly ELASTICSEARCH_LOGGING_REPLICAS='
${
ELASTICSEARCH_LOGGING_REPLICAS
:-}
'"
echo
"readonly ENABLE_CLUSTER_DNS='
${
ENABLE_CLUSTER_DNS
:-
false
}
'"
echo
"readonly ENABLE_CLUSTER_UI='
${
ENABLE_CLUSTER_UI
:-
false
}
'"
echo
"readonly RUNTIME_CONFIG='
${
RUNTIME_CONFIG
}
'"
echo
"readonly DNS_REPLICAS='
${
DNS_REPLICAS
:-}
'"
echo
"readonly DNS_SERVER_IP='
${
DNS_SERVER_IP
:-}
'"
echo
"readonly DNS_DOMAIN='
${
DNS_DOMAIN
:-}
'"
echo
"readonly ADMISSION_CONTROL='
${
ADMISSION_CONTROL
:-}
'"
echo
"readonly MASTER_IP_RANGE='
${
MASTER_IP_RANGE
:-}
'"
echo
"readonly KUBELET_TOKEN='
${
KUBELET_TOKEN
}
'"
echo
"readonly KUBE_PROXY_TOKEN='
${
KUBE_PROXY_TOKEN
}
'"
echo
"readonly DOCKER_STORAGE='
${
DOCKER_STORAGE
:-}
'"
echo
"readonly MASTER_EXTRA_SANS='
${
MASTER_EXTRA_SANS
:-}
'"
echo
"readonly NETWORK_PROVIDER='
${
NETWORK_PROVIDER
:-}
'"
echo
"readonly OPENCONTRAIL_TAG='
${
OPENCONTRAIL_TAG
:-}
'"
echo
"readonly OPENCONTRAIL_KUBERNETES_TAG='
${
OPENCONTRAIL_KUBERNETES_TAG
:-}
'"
echo
"readonly OPENCONTRAIL_PUBLIC_SUBNET='
${
OPENCONTRAIL_PUBLIC_SUBNET
:-}
'"
echo
"readonly E2E_STORAGE_TEST_ENVIRONMENT='
${
E2E_STORAGE_TEST_ENVIRONMENT
:-}
'"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/common.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/common.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/extract-kube-env.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/format-disks.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/format-disks.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/setup-master-pd.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/setup-master-pd.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/create-dynamic-salt-files.sh"
grep
-v
"^#"
"
${
KUBE_ROOT
}
/cluster/aws/templates/create-dynamic-salt-files.sh"
...
@@ -1523,25 +1507,3 @@ function get-tokens() {
...
@@ -1523,25 +1507,3 @@ function get-tokens() {
KUBELET_TOKEN
=
$(
dd
if
=
/dev/urandom
bs
=
128
count
=
1 2>/dev/null |
base64
|
tr
-d
"=+/"
|
dd
bs
=
32
count
=
1 2>/dev/null
)
KUBELET_TOKEN
=
$(
dd
if
=
/dev/urandom
bs
=
128
count
=
1 2>/dev/null |
base64
|
tr
-d
"=+/"
|
dd
bs
=
32
count
=
1 2>/dev/null
)
KUBE_PROXY_TOKEN
=
$(
dd
if
=
/dev/urandom
bs
=
128
count
=
1 2>/dev/null |
base64
|
tr
-d
"=+/"
|
dd
bs
=
32
count
=
1 2>/dev/null
)
KUBE_PROXY_TOKEN
=
$(
dd
if
=
/dev/urandom
bs
=
128
count
=
1 2>/dev/null |
base64
|
tr
-d
"=+/"
|
dd
bs
=
32
count
=
1 2>/dev/null
)
}
}
# Builds the RUNTIME_CONFIG var from other feature enable options
function
build-runtime-config
()
{
if
[[
"
${
ENABLE_DEPLOYMENTS
}
"
==
"true"
]]
;
then
if
[[
-z
"
${
RUNTIME_CONFIG
}
"
]]
;
then
RUNTIME_CONFIG
=
"extensions/v1beta1/deployments=true"
else
if
echo
"
${
RUNTIME_CONFIG
}
"
|
grep
-q
-v
"extensions/v1beta1/deployments=true"
;
then
RUNTIME_CONFIG
=
"
${
RUNTIME_CONFIG
}
,extensions/v1beta1/deployments=true"
fi
fi
fi
if
[[
"
${
ENABLE_DAEMONSETS
}
"
==
"true"
]]
;
then
if
[[
-z
"
${
RUNTIME_CONFIG
}
"
]]
;
then
RUNTIME_CONFIG
=
"extensions/v1beta1/daemonsets=true"
else
if
echo
"
${
RUNTIME_CONFIG
}
"
|
grep
-q
-v
"extensions/v1beta1/daemonsets=true"
;
then
RUNTIME_CONFIG
=
"
${
RUNTIME_CONFIG
}
,extensions/v1beta1/daemonsets=true"
fi
fi
fi
}
cluster/common.sh
View file @
30375b21
...
@@ -410,3 +410,222 @@ function stage-images() {
...
@@ -410,3 +410,222 @@ function stage-images() {
rm
-rf
"
${
temp_dir
}
"
rm
-rf
"
${
temp_dir
}
"
return
0
return
0
}
}
# Quote something appropriate for a yaml string.
#
# TODO(zmerlynn): Note that this function doesn't so much "quote" as
# "strip out quotes", and we really should be using a YAML library for
# this, but PyYAML isn't shipped by default, and *rant rant rant ... SIGH*
function
yaml-quote
{
echo
"'
$(
echo
"
${
@
}
"
|
sed
-e
"s/'/''/g"
)
'"
}
# Builds the RUNTIME_CONFIG var from other feature enable options
function
build-runtime-config
()
{
if
[[
"
${
ENABLE_DEPLOYMENTS
}
"
==
"true"
]]
;
then
if
[[
-z
"
${
RUNTIME_CONFIG
}
"
]]
;
then
RUNTIME_CONFIG
=
"extensions/v1beta1/deployments=true"
else
if
echo
"
${
RUNTIME_CONFIG
}
"
|
grep
-q
-v
"extensions/v1beta1/deployments=true"
;
then
RUNTIME_CONFIG
=
"
${
RUNTIME_CONFIG
}
,extensions/v1beta1/deployments=true"
fi
fi
fi
if
[[
"
${
ENABLE_DAEMONSETS
}
"
==
"true"
]]
;
then
if
[[
-z
"
${
RUNTIME_CONFIG
}
"
]]
;
then
RUNTIME_CONFIG
=
"extensions/v1beta1/daemonsets=true"
else
if
echo
"
${
RUNTIME_CONFIG
}
"
|
grep
-q
-v
"extensions/v1beta1/daemonsets=true"
;
then
RUNTIME_CONFIG
=
"
${
RUNTIME_CONFIG
}
,extensions/v1beta1/daemonsets=true"
fi
fi
fi
}
function
write-master-env
{
# If the user requested that the master be part of the cluster, set the
# environment variable to program the master kubelet to register itself.
if
[[
"
${
REGISTER_MASTER_KUBELET
:-}
"
==
"true"
]]
;
then
KUBELET_APISERVER
=
"
${
MASTER_NAME
}
"
fi
build-kube-env
true
"
${
KUBE_TEMP
}
/master-kube-env.yaml"
}
function
write-node-env
{
build-kube-env
false
"
${
KUBE_TEMP
}
/node-kube-env.yaml"
}
# $1: if 'true', we're building a master yaml, else a node
function
build-kube-env
{
local
master
=
$1
local
file
=
$2
build-runtime-config
rm
-f
${
file
}
cat
>
$file
<<
EOF
ENV_TIMESTAMP:
$(
yaml-quote
$(
date
-u
+%Y-%m-%dT%T%z
))
INSTANCE_PREFIX:
$(
yaml-quote
${
INSTANCE_PREFIX
})
NODE_INSTANCE_PREFIX:
$(
yaml-quote
${
NODE_INSTANCE_PREFIX
})
CLUSTER_IP_RANGE:
$(
yaml-quote
${
CLUSTER_IP_RANGE
:-
10
.244.0.0/16
})
SERVER_BINARY_TAR_URL:
$(
yaml-quote
${
SERVER_BINARY_TAR_URL
})
SERVER_BINARY_TAR_HASH:
$(
yaml-quote
${
SERVER_BINARY_TAR_HASH
})
SALT_TAR_URL:
$(
yaml-quote
${
SALT_TAR_URL
})
SALT_TAR_HASH:
$(
yaml-quote
${
SALT_TAR_HASH
})
SERVICE_CLUSTER_IP_RANGE:
$(
yaml-quote
${
SERVICE_CLUSTER_IP_RANGE
})
KUBERNETES_MASTER_NAME:
$(
yaml-quote
${
MASTER_NAME
})
ALLOCATE_NODE_CIDRS:
$(
yaml-quote
${
ALLOCATE_NODE_CIDRS
:-
false
})
ENABLE_CLUSTER_MONITORING:
$(
yaml-quote
${
ENABLE_CLUSTER_MONITORING
:-
none
})
ENABLE_L7_LOADBALANCING:
$(
yaml-quote
${
ENABLE_L7_LOADBALANCING
:-
none
})
ENABLE_CLUSTER_LOGGING:
$(
yaml-quote
${
ENABLE_CLUSTER_LOGGING
:-
false
})
ENABLE_CLUSTER_UI:
$(
yaml-quote
${
ENABLE_CLUSTER_UI
:-
false
})
ENABLE_NODE_LOGGING:
$(
yaml-quote
${
ENABLE_NODE_LOGGING
:-
false
})
LOGGING_DESTINATION:
$(
yaml-quote
${
LOGGING_DESTINATION
:-})
ELASTICSEARCH_LOGGING_REPLICAS:
$(
yaml-quote
${
ELASTICSEARCH_LOGGING_REPLICAS
:-})
ENABLE_CLUSTER_DNS:
$(
yaml-quote
${
ENABLE_CLUSTER_DNS
:-
false
})
ENABLE_CLUSTER_REGISTRY:
$(
yaml-quote
${
ENABLE_CLUSTER_REGISTRY
:-
false
})
CLUSTER_REGISTRY_DISK:
$(
yaml-quote
${
CLUSTER_REGISTRY_DISK
:-})
CLUSTER_REGISTRY_DISK_SIZE:
$(
yaml-quote
${
CLUSTER_REGISTRY_DISK_SIZE
:-})
DNS_REPLICAS:
$(
yaml-quote
${
DNS_REPLICAS
:-})
DNS_SERVER_IP:
$(
yaml-quote
${
DNS_SERVER_IP
:-})
DNS_DOMAIN:
$(
yaml-quote
${
DNS_DOMAIN
:-})
KUBELET_TOKEN:
$(
yaml-quote
${
KUBELET_TOKEN
:-})
KUBE_PROXY_TOKEN:
$(
yaml-quote
${
KUBE_PROXY_TOKEN
:-})
ADMISSION_CONTROL:
$(
yaml-quote
${
ADMISSION_CONTROL
:-})
MASTER_IP_RANGE:
$(
yaml-quote
${
MASTER_IP_RANGE
})
RUNTIME_CONFIG:
$(
yaml-quote
${
RUNTIME_CONFIG
})
CA_CERT:
$(
yaml-quote
${
CA_CERT_BASE64
:-})
KUBELET_CERT:
$(
yaml-quote
${
KUBELET_CERT_BASE64
:-})
KUBELET_KEY:
$(
yaml-quote
${
KUBELET_KEY_BASE64
:-})
NETWORK_PROVIDER:
$(
yaml-quote
${
NETWORK_PROVIDER
:-})
OPENCONTRAIL_TAG:
$(
yaml-quote
${
OPENCONTRAIL_TAG
:-})
OPENCONTRAIL_KUBERNETES_TAG:
$(
yaml-quote
${
OPENCONTRAIL_KUBERNETES_TAG
:-})
OPENCONTRAIL_PUBLIC_SUBNET:
$(
yaml-quote
${
OPENCONTRAIL_PUBLIC_SUBNET
:-})
E2E_STORAGE_TEST_ENVIRONMENT:
$(
yaml-quote
${
E2E_STORAGE_TEST_ENVIRONMENT
:-})
KUBE_IMAGE_TAG:
$(
yaml-quote
${
KUBE_IMAGE_TAG
:-})
KUBE_DOCKER_REGISTRY:
$(
yaml-quote
${
KUBE_DOCKER_REGISTRY
:-})
MULTIZONE:
$(
yaml-quote
${
MULTIZONE
:-})
NON_MASQUERADE_CIDR:
$(
yaml-quote
${
NON_MASQUERADE_CIDR
:-})
EOF
if
[
-n
"
${
KUBELET_PORT
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBELET_PORT:
$(
yaml-quote
${
KUBELET_PORT
})
EOF
fi
if
[
-n
"
${
KUBE_APISERVER_REQUEST_TIMEOUT
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBE_APISERVER_REQUEST_TIMEOUT:
$(
yaml-quote
${
KUBE_APISERVER_REQUEST_TIMEOUT
})
EOF
fi
if
[
-n
"
${
TERMINATED_POD_GC_THRESHOLD
:-}
"
]
;
then
cat
>>
$file
<<
EOF
TERMINATED_POD_GC_THRESHOLD:
$(
yaml-quote
${
TERMINATED_POD_GC_THRESHOLD
})
EOF
fi
if
[[
"
${
OS_DISTRIBUTION
}
"
==
"trusty"
]]
;
then
cat
>>
$file
<<
EOF
KUBE_MANIFESTS_TAR_URL:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_URL
})
KUBE_MANIFESTS_TAR_HASH:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_HASH
})
EOF
fi
if
[
-n
"
${
TEST_CLUSTER
:-}
"
]
;
then
cat
>>
$file
<<
EOF
TEST_CLUSTER:
$(
yaml-quote
${
TEST_CLUSTER
})
EOF
fi
if
[
-n
"
${
KUBELET_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBELET_TEST_ARGS:
$(
yaml-quote
${
KUBELET_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
KUBELET_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBELET_TEST_LOG_LEVEL:
$(
yaml-quote
${
KUBELET_TEST_LOG_LEVEL
})
EOF
fi
if
[[
"
${
master
}
"
==
"true"
]]
;
then
# Master-only env vars.
cat
>>
$file
<<
EOF
KUBERNETES_MASTER:
$(
yaml-quote
"true"
)
KUBE_USER:
$(
yaml-quote
${
KUBE_USER
})
KUBE_PASSWORD:
$(
yaml-quote
${
KUBE_PASSWORD
})
KUBE_BEARER_TOKEN:
$(
yaml-quote
${
KUBE_BEARER_TOKEN
})
MASTER_CERT:
$(
yaml-quote
${
MASTER_CERT_BASE64
:-})
MASTER_KEY:
$(
yaml-quote
${
MASTER_KEY_BASE64
:-})
KUBECFG_CERT:
$(
yaml-quote
${
KUBECFG_CERT_BASE64
:-})
KUBECFG_KEY:
$(
yaml-quote
${
KUBECFG_KEY_BASE64
:-})
KUBELET_APISERVER:
$(
yaml-quote
${
KUBELET_APISERVER
:-})
ENABLE_MANIFEST_URL:
$(
yaml-quote
${
ENABLE_MANIFEST_URL
:-
false
})
MANIFEST_URL:
$(
yaml-quote
${
MANIFEST_URL
:-})
MANIFEST_URL_HEADER:
$(
yaml-quote
${
MANIFEST_URL_HEADER
:-})
NUM_NODES:
$(
yaml-quote
${
NUM_NODES
})
EOF
if
[
-n
"
${
APISERVER_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
APISERVER_TEST_ARGS:
$(
yaml-quote
${
APISERVER_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
APISERVER_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
APISERVER_TEST_LOG_LEVEL:
$(
yaml-quote
${
APISERVER_TEST_LOG_LEVEL
})
EOF
fi
if
[
-n
"
${
CONTROLLER_MANAGER_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
CONTROLLER_MANAGER_TEST_ARGS:
$(
yaml-quote
${
CONTROLLER_MANAGER_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
CONTROLLER_MANAGER_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
CONTROLLER_MANAGER_TEST_LOG_LEVEL:
$(
yaml-quote
${
CONTROLLER_MANAGER_TEST_LOG_LEVEL
})
EOF
fi
if
[
-n
"
${
SCHEDULER_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
SCHEDULER_TEST_ARGS:
$(
yaml-quote
${
SCHEDULER_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
SCHEDULER_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
SCHEDULER_TEST_LOG_LEVEL:
$(
yaml-quote
${
SCHEDULER_TEST_LOG_LEVEL
})
EOF
fi
else
# Node-only env vars.
cat
>>
$file
<<
EOF
KUBERNETES_MASTER:
$(
yaml-quote
"false"
)
ZONE:
$(
yaml-quote
${
ZONE
})
EXTRA_DOCKER_OPTS:
$(
yaml-quote
${
EXTRA_DOCKER_OPTS
:-})
EOF
if
[
-n
"
${
KUBEPROXY_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBEPROXY_TEST_ARGS:
$(
yaml-quote
${
KUBEPROXY_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
KUBEPROXY_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBEPROXY_TEST_LOG_LEVEL:
$(
yaml-quote
${
KUBEPROXY_TEST_LOG_LEVEL
})
EOF
fi
fi
if
[[
"
${
OS_DISTRIBUTION
}
"
==
"coreos"
]]
;
then
# CoreOS-only env vars. TODO(yifan): Make them available on other distros.
cat
>>
$file
<<
EOF
KUBE_MANIFESTS_TAR_URL:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_URL
})
KUBE_MANIFESTS_TAR_HASH:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_HASH
})
KUBERNETES_CONTAINER_RUNTIME:
$(
yaml-quote
${
CONTAINER_RUNTIME
:-
docker
})
RKT_VERSION:
$(
yaml-quote
${
RKT_VERSION
:-})
RKT_PATH:
$(
yaml-quote
${
RKT_PATH
:-})
KUBERNETES_CONFIGURE_CBR0:
$(
yaml-quote
${
KUBERNETES_CONFIGURE_CBR0
:-
true
})
EOF
fi
}
function
sha1sum-file
()
{
if
which shasum
>
/dev/null 2>&1
;
then
shasum
-a1
"
$1
"
|
awk
'{ print $1 }'
else
sha1sum
"
$1
"
|
awk
'{ print $1 }'
fi
}
cluster/gce/util.sh
View file @
30375b21
...
@@ -115,14 +115,6 @@ function detect-project () {
...
@@ -115,14 +115,6 @@ function detect-project () {
fi
fi
}
}
function
sha1sum-file
()
{
if
which shasum
>
/dev/null 2>&1
;
then
shasum
-a1
"
$1
"
|
awk
'{ print $1 }'
else
sha1sum
"
$1
"
|
awk
'{ print $1 }'
fi
}
function
already-staged
()
{
function
already-staged
()
{
local
-r
file
=
$1
local
-r
file
=
$1
local
-r
newsum
=
$2
local
-r
newsum
=
$2
...
@@ -465,29 +457,6 @@ function add-instance-metadata-from-file {
...
@@ -465,29 +457,6 @@ function add-instance-metadata-from-file {
done
done
}
}
# Quote something appropriate for a yaml string.
#
# TODO(zmerlynn): Note that this function doesn't so much "quote" as
# "strip out quotes", and we really should be using a YAML library for
# this, but PyYAML isn't shipped by default, and *rant rant rant ... SIGH*
function
yaml-quote
{
echo
"'
$(
echo
"
${
@
}
"
|
sed
-e
"s/'/''/g"
)
'"
}
function
write-master-env
{
# If the user requested that the master be part of the cluster, set the
# environment variable to program the master kubelet to register itself.
if
[[
"
${
REGISTER_MASTER_KUBELET
:-}
"
==
"true"
]]
;
then
KUBELET_APISERVER
=
"
${
MASTER_NAME
}
"
fi
build-kube-env
true
"
${
KUBE_TEMP
}
/master-kube-env.yaml"
}
function
write-node-env
{
build-kube-env
false
"
${
KUBE_TEMP
}
/node-kube-env.yaml"
}
# Create certificate pairs for the cluster.
# Create certificate pairs for the cluster.
# $1: The public IP for the master.
# $1: The public IP for the master.
#
#
...
@@ -1335,190 +1304,3 @@ function restart-apiserver {
...
@@ -1335,190 +1304,3 @@ function restart-apiserver {
function
prepare-e2e
()
{
function
prepare-e2e
()
{
detect-project
detect-project
}
}
# Builds the RUNTIME_CONFIG var from other feature enable options
function
build-runtime-config
()
{
if
[[
"
${
ENABLE_DEPLOYMENTS
}
"
==
"true"
]]
;
then
if
[[
-z
"
${
RUNTIME_CONFIG
}
"
]]
;
then
RUNTIME_CONFIG
=
"extensions/v1beta1/deployments=true"
else
if
echo
"
${
RUNTIME_CONFIG
}
"
|
grep
-q
-v
"extensions/v1beta1/deployments=true"
;
then
RUNTIME_CONFIG
=
"
${
RUNTIME_CONFIG
}
,extensions/v1beta1/deployments=true"
fi
fi
fi
if
[[
"
${
ENABLE_DAEMONSETS
}
"
==
"true"
]]
;
then
if
[[
-z
"
${
RUNTIME_CONFIG
}
"
]]
;
then
RUNTIME_CONFIG
=
"extensions/v1beta1/daemonsets=true"
else
if
echo
"
${
RUNTIME_CONFIG
}
"
|
grep
-q
-v
"extensions/v1beta1/daemonsets=true"
;
then
RUNTIME_CONFIG
=
"
${
RUNTIME_CONFIG
}
,extensions/v1beta1/daemonsets=true"
fi
fi
fi
}
# $1: if 'true', we're building a master yaml, else a node
function
build-kube-env
{
local
master
=
$1
local
file
=
$2
build-runtime-config
rm
-f
${
file
}
cat
>
$file
<<
EOF
ENV_TIMESTAMP:
$(
yaml-quote
$(
date
-u
+%Y-%m-%dT%T%z
))
INSTANCE_PREFIX:
$(
yaml-quote
${
INSTANCE_PREFIX
})
NODE_INSTANCE_PREFIX:
$(
yaml-quote
${
NODE_INSTANCE_PREFIX
})
CLUSTER_IP_RANGE:
$(
yaml-quote
${
CLUSTER_IP_RANGE
:-
10
.244.0.0/16
})
SERVER_BINARY_TAR_URL:
$(
yaml-quote
${
SERVER_BINARY_TAR_URL
})
SERVER_BINARY_TAR_HASH:
$(
yaml-quote
${
SERVER_BINARY_TAR_HASH
})
SALT_TAR_URL:
$(
yaml-quote
${
SALT_TAR_URL
})
SALT_TAR_HASH:
$(
yaml-quote
${
SALT_TAR_HASH
})
SERVICE_CLUSTER_IP_RANGE:
$(
yaml-quote
${
SERVICE_CLUSTER_IP_RANGE
})
KUBERNETES_MASTER_NAME:
$(
yaml-quote
${
MASTER_NAME
})
ALLOCATE_NODE_CIDRS:
$(
yaml-quote
${
ALLOCATE_NODE_CIDRS
:-
false
})
ENABLE_CLUSTER_MONITORING:
$(
yaml-quote
${
ENABLE_CLUSTER_MONITORING
:-
none
})
ENABLE_L7_LOADBALANCING:
$(
yaml-quote
${
ENABLE_L7_LOADBALANCING
:-
none
})
ENABLE_CLUSTER_LOGGING:
$(
yaml-quote
${
ENABLE_CLUSTER_LOGGING
:-
false
})
ENABLE_CLUSTER_UI:
$(
yaml-quote
${
ENABLE_CLUSTER_UI
:-
false
})
ENABLE_NODE_LOGGING:
$(
yaml-quote
${
ENABLE_NODE_LOGGING
:-
false
})
LOGGING_DESTINATION:
$(
yaml-quote
${
LOGGING_DESTINATION
:-})
ELASTICSEARCH_LOGGING_REPLICAS:
$(
yaml-quote
${
ELASTICSEARCH_LOGGING_REPLICAS
:-})
ENABLE_CLUSTER_DNS:
$(
yaml-quote
${
ENABLE_CLUSTER_DNS
:-
false
})
ENABLE_CLUSTER_REGISTRY:
$(
yaml-quote
${
ENABLE_CLUSTER_REGISTRY
:-
false
})
CLUSTER_REGISTRY_DISK:
$(
yaml-quote
${
CLUSTER_REGISTRY_DISK
})
CLUSTER_REGISTRY_DISK_SIZE:
$(
yaml-quote
${
CLUSTER_REGISTRY_DISK_SIZE
})
DNS_REPLICAS:
$(
yaml-quote
${
DNS_REPLICAS
:-})
DNS_SERVER_IP:
$(
yaml-quote
${
DNS_SERVER_IP
:-})
DNS_DOMAIN:
$(
yaml-quote
${
DNS_DOMAIN
:-})
KUBELET_TOKEN:
$(
yaml-quote
${
KUBELET_TOKEN
:-})
KUBE_PROXY_TOKEN:
$(
yaml-quote
${
KUBE_PROXY_TOKEN
:-})
ADMISSION_CONTROL:
$(
yaml-quote
${
ADMISSION_CONTROL
:-})
MASTER_IP_RANGE:
$(
yaml-quote
${
MASTER_IP_RANGE
})
RUNTIME_CONFIG:
$(
yaml-quote
${
RUNTIME_CONFIG
})
CA_CERT:
$(
yaml-quote
${
CA_CERT_BASE64
:-})
KUBELET_CERT:
$(
yaml-quote
${
KUBELET_CERT_BASE64
:-})
KUBELET_KEY:
$(
yaml-quote
${
KUBELET_KEY_BASE64
:-})
NETWORK_PROVIDER:
$(
yaml-quote
${
NETWORK_PROVIDER
:-})
OPENCONTRAIL_TAG:
$(
yaml-quote
${
OPENCONTRAIL_TAG
:-})
OPENCONTRAIL_KUBERNETES_TAG:
$(
yaml-quote
${
OPENCONTRAIL_KUBERNETES_TAG
:-})
OPENCONTRAIL_PUBLIC_SUBNET:
$(
yaml-quote
${
OPENCONTRAIL_PUBLIC_SUBNET
:-})
E2E_STORAGE_TEST_ENVIRONMENT:
$(
yaml-quote
${
E2E_STORAGE_TEST_ENVIRONMENT
:-})
KUBE_IMAGE_TAG:
$(
yaml-quote
${
KUBE_IMAGE_TAG
:-})
KUBE_DOCKER_REGISTRY:
$(
yaml-quote
${
KUBE_DOCKER_REGISTRY
:-})
MULTIZONE:
$(
yaml-quote
${
MULTIZONE
:-})
EOF
if
[
-n
"
${
KUBELET_PORT
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBELET_PORT:
$(
yaml-quote
${
KUBELET_PORT
})
EOF
fi
if
[
-n
"
${
KUBE_APISERVER_REQUEST_TIMEOUT
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBE_APISERVER_REQUEST_TIMEOUT:
$(
yaml-quote
${
KUBE_APISERVER_REQUEST_TIMEOUT
})
EOF
fi
if
[
-n
"
${
TERMINATED_POD_GC_THRESHOLD
:-}
"
]
;
then
cat
>>
$file
<<
EOF
TERMINATED_POD_GC_THRESHOLD:
$(
yaml-quote
${
TERMINATED_POD_GC_THRESHOLD
})
EOF
fi
if
[[
"
${
OS_DISTRIBUTION
}
"
==
"trusty"
]]
;
then
cat
>>
$file
<<
EOF
KUBE_MANIFESTS_TAR_URL:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_URL
})
KUBE_MANIFESTS_TAR_HASH:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_HASH
})
EOF
fi
if
[
-n
"
${
TEST_CLUSTER
:-}
"
]
;
then
cat
>>
$file
<<
EOF
TEST_CLUSTER:
$(
yaml-quote
${
TEST_CLUSTER
})
EOF
fi
if
[
-n
"
${
KUBELET_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBELET_TEST_ARGS:
$(
yaml-quote
${
KUBELET_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
KUBELET_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBELET_TEST_LOG_LEVEL:
$(
yaml-quote
${
KUBELET_TEST_LOG_LEVEL
})
EOF
fi
if
[[
"
${
master
}
"
==
"true"
]]
;
then
# Master-only env vars.
cat
>>
$file
<<
EOF
KUBERNETES_MASTER:
$(
yaml-quote
"true"
)
KUBE_USER:
$(
yaml-quote
${
KUBE_USER
})
KUBE_PASSWORD:
$(
yaml-quote
${
KUBE_PASSWORD
})
KUBE_BEARER_TOKEN:
$(
yaml-quote
${
KUBE_BEARER_TOKEN
})
MASTER_CERT:
$(
yaml-quote
${
MASTER_CERT_BASE64
:-})
MASTER_KEY:
$(
yaml-quote
${
MASTER_KEY_BASE64
:-})
KUBECFG_CERT:
$(
yaml-quote
${
KUBECFG_CERT_BASE64
:-})
KUBECFG_KEY:
$(
yaml-quote
${
KUBECFG_KEY_BASE64
:-})
KUBELET_APISERVER:
$(
yaml-quote
${
KUBELET_APISERVER
:-})
ENABLE_MANIFEST_URL:
$(
yaml-quote
${
ENABLE_MANIFEST_URL
:-
false
})
MANIFEST_URL:
$(
yaml-quote
${
MANIFEST_URL
:-})
MANIFEST_URL_HEADER:
$(
yaml-quote
${
MANIFEST_URL_HEADER
:-})
NUM_NODES:
$(
yaml-quote
${
NUM_NODES
})
EOF
if
[
-n
"
${
APISERVER_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
APISERVER_TEST_ARGS:
$(
yaml-quote
${
APISERVER_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
APISERVER_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
APISERVER_TEST_LOG_LEVEL:
$(
yaml-quote
${
APISERVER_TEST_LOG_LEVEL
})
EOF
fi
if
[
-n
"
${
CONTROLLER_MANAGER_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
CONTROLLER_MANAGER_TEST_ARGS:
$(
yaml-quote
${
CONTROLLER_MANAGER_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
CONTROLLER_MANAGER_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
CONTROLLER_MANAGER_TEST_LOG_LEVEL:
$(
yaml-quote
${
CONTROLLER_MANAGER_TEST_LOG_LEVEL
})
EOF
fi
if
[
-n
"
${
SCHEDULER_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
SCHEDULER_TEST_ARGS:
$(
yaml-quote
${
SCHEDULER_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
SCHEDULER_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
SCHEDULER_TEST_LOG_LEVEL:
$(
yaml-quote
${
SCHEDULER_TEST_LOG_LEVEL
})
EOF
fi
else
# Node-only env vars.
cat
>>
$file
<<
EOF
KUBERNETES_MASTER:
$(
yaml-quote
"false"
)
ZONE:
$(
yaml-quote
${
ZONE
})
EXTRA_DOCKER_OPTS:
$(
yaml-quote
${
EXTRA_DOCKER_OPTS
:-})
EOF
if
[
-n
"
${
KUBEPROXY_TEST_ARGS
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBEPROXY_TEST_ARGS:
$(
yaml-quote
${
KUBEPROXY_TEST_ARGS
})
EOF
fi
if
[
-n
"
${
KUBEPROXY_TEST_LOG_LEVEL
:-}
"
]
;
then
cat
>>
$file
<<
EOF
KUBEPROXY_TEST_LOG_LEVEL:
$(
yaml-quote
${
KUBEPROXY_TEST_LOG_LEVEL
})
EOF
fi
fi
if
[[
"
${
OS_DISTRIBUTION
}
"
==
"coreos"
]]
;
then
# CoreOS-only env vars. TODO(yifan): Make them available on other distros.
cat
>>
$file
<<
EOF
KUBE_MANIFESTS_TAR_URL:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_URL
})
KUBE_MANIFESTS_TAR_HASH:
$(
yaml-quote
${
KUBE_MANIFESTS_TAR_HASH
})
KUBERNETES_CONTAINER_RUNTIME:
$(
yaml-quote
${
CONTAINER_RUNTIME
:-
docker
})
RKT_VERSION:
$(
yaml-quote
${
RKT_VERSION
:-})
RKT_PATH:
$(
yaml-quote
${
RKT_PATH
:-})
KUBERNETES_CONFIGURE_CBR0:
$(
yaml-quote
${
KUBERNETES_CONFIGURE_CBR0
:-
true
})
EOF
fi
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment