Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Setup-Manager
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Analyze
Contributor analytics
CI/CD analytics
Repository analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Dmytro Bogatov
Setup-Manager
Commits
4629ca85
Commit
4629ca85
authored
Jul 14, 2019
by
Dmytro Bogatov
Browse files
Options
Downloads
Patches
Plain Diff
Add kubectl apply, fix shevastream.
parent
a7d9951d
Branches
17-python-k8s-upgrade-daemonsets-for-apps
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
infra/deploy.py
+103
-33
103 additions, 33 deletions
infra/deploy.py
infra/sources/dashboard/ingress.yaml
+1
-1
1 addition, 1 deletion
infra/sources/dashboard/ingress.yaml
infra/sources/service/website.yaml
+13
-0
13 additions, 0 deletions
infra/sources/service/website.yaml
with
117 additions
and
34 deletions
infra/deploy.py
+
103
−
33
View file @
4629ca85
...
@@ -9,10 +9,12 @@ import requests
...
@@ -9,10 +9,12 @@ import requests
import
time
import
time
import
sys
import
sys
import
os
import
os
from
kubernetes
import
client
,
config
from
kubernetes
import
client
,
config
,
utils
from
kubernetes.client.rest
import
ApiException
from
kubernetes.client.rest
import
ApiException
import
base64
import
base64
from
enum
import
Enum
,
auto
from
enum
import
Enum
,
auto
import
subprocess
from
jinja2
import
Template
,
Environment
,
FileSystemLoader
cwd
=
Path
(
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
)))
cwd
=
Path
(
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
)))
...
@@ -23,6 +25,33 @@ def deploy():
...
@@ -23,6 +25,33 @@ def deploy():
bootstrapCluster
()
bootstrapCluster
()
def
apply
(
resource
,
message
=
None
):
if
len
(
resource
.
splitlines
())
==
1
:
argument
=
resource
if
"
https://
"
in
resource
else
(
cwd
/
resource
).
as_posix
()
kubectl
=
f
"
kubectl --kubeconfig=
{
(
cwd
/
'
kubeconfig.yaml
'
).
as_posix
()
}
apply -f
{
argument
}
"
output
,
error
=
subprocess
.
Popen
(
kubectl
.
split
(),
stdout
=
subprocess
.
PIPE
).
communicate
()
else
:
kubectl
=
f
"
kubectl --kubeconfig=
{
(
cwd
/
'
kubeconfig.yaml
'
).
as_posix
()
}
apply -f -
"
result
=
subprocess
.
run
(
kubectl
.
split
(),
stdout
=
subprocess
.
PIPE
,
input
=
resource
,
encoding
=
'
ascii
'
)
output
=
result
.
stdout
.
encode
()
error
=
result
.
stderr
if
error
is
None
:
_logger
.
debug
(
f
"
{
kubectl
}
\n
{
output
.
decode
()
}
"
)
else
:
if
message
is
not
None
:
_logger
.
critical
(
f
"
{
message
}
provision failed
"
)
_logger
.
error
(
error
)
raise
Exception
(
f
"
kubectl failed :
{
kubectl
}
"
)
if
message
is
not
None
:
_logger
.
info
(
message
)
def
bootstrapCluster
():
def
bootstrapCluster
():
class
SecretType
(
Enum
):
class
SecretType
(
Enum
):
...
@@ -30,6 +59,9 @@ def bootstrapCluster():
...
@@ -30,6 +59,9 @@ def bootstrapCluster():
BASICAUTH
=
auto
()
BASICAUTH
=
auto
()
REGSITRY
=
auto
()
REGSITRY
=
auto
()
DASHBOARD
=
auto
()
DASHBOARD
=
auto
()
DO
=
auto
()
STATUSSITE
=
auto
()
SHEVASTREAM
=
auto
()
def
createNamespace
(
namespace
):
def
createNamespace
(
namespace
):
try
:
try
:
...
@@ -41,19 +73,27 @@ def bootstrapCluster():
...
@@ -41,19 +73,27 @@ def bootstrapCluster():
else
:
else
:
raise
e
raise
e
def
create
Tls
Secret
(
namespace
,
type
):
def
createSecret
(
namespace
,
type
):
try
:
try
:
if
type
==
SecretType
.
TLS
:
data
=
None
stringData
=
None
if
type
==
SecretType
.
TLS
or
type
==
SecretType
.
DASHBOARD
:
with
open
(
_secretsPath
/
"
certificate.key
"
,
"
r
"
)
as
key
:
with
open
(
_secretsPath
/
"
certificate.key
"
,
"
r
"
)
as
key
:
with
open
(
_secretsPath
/
"
certificate.crt
"
,
"
r
"
)
as
certificate
:
with
open
(
_secretsPath
/
"
certificate.crt
"
,
"
r
"
)
as
certificate
:
data
=
{
'
tls.crt
'
:
base64
.
b64encode
(
certificate
.
read
().
encode
()).
decode
(),
'
tls.key
'
:
base64
.
b64encode
(
key
.
read
().
encode
()).
decode
()}
if
type
==
SecretType
.
TLS
:
secType
=
'
kubernetes.io/tls
'
data
=
{
"
tls.crt
"
:
base64
.
b64encode
(
certificate
.
read
().
encode
()).
decode
(),
"
tls.key
"
:
base64
.
b64encode
(
key
.
read
().
encode
()).
decode
()}
metadata
=
{
'
name
'
:
'
lets-encrypt
'
}
secType
=
"
kubernetes.io/tls
"
metadata
=
{
"
name
"
:
"
lets-encrypt
"
}
else
:
data
=
{
"
certificate.crt
"
:
base64
.
b64encode
(
certificate
.
read
().
encode
()).
decode
(),
"
certificate.key
"
:
base64
.
b64encode
(
key
.
read
().
encode
()).
decode
()}
secType
=
"
Opaque
"
metadata
=
{
"
name
"
:
"
kubernetes-dashboard-certs
"
}
elif
type
==
SecretType
.
BASICAUTH
:
elif
type
==
SecretType
.
BASICAUTH
:
with
open
(
_secretsPath
/
"
auth
"
,
"
r
"
)
as
auth
:
with
open
(
_secretsPath
/
"
auth
"
,
"
r
"
)
as
auth
:
data
=
{
'
auth
'
:
base64
.
b64encode
(
auth
.
read
().
encode
()).
decode
()}
data
=
{
"
auth
"
:
base64
.
b64encode
(
auth
.
read
().
encode
()).
decode
()}
secType
=
'
Opaque
'
secType
=
"
Opaque
"
metadata
=
{
'
name
'
:
'
basic-auth
'
}
metadata
=
{
"
name
"
:
"
basic-auth
"
}
elif
type
==
SecretType
.
REGSITRY
:
elif
type
==
SecretType
.
REGSITRY
:
data
=
{
data
=
{
"
.dockerconfigjson
"
:
base64
.
b64encode
(
"
.dockerconfigjson
"
:
base64
.
b64encode
(
...
@@ -69,10 +109,24 @@ def bootstrapCluster():
...
@@ -69,10 +109,24 @@ def bootstrapCluster():
}).
encode
()
}).
encode
()
).
decode
()
).
decode
()
}
}
secType
=
'
kubernetes.io/dockerconfigjson
'
secType
=
"
kubernetes.io/dockerconfigjson
"
metadata
=
{
'
name
'
:
'
regsecret
'
}
metadata
=
{
"
name
"
:
"
regsecret
"
}
elif
type
==
SecretType
.
DO
:
api
.
create_namespaced_secret
(
namespace
,
client
.
V1Secret
(
data
=
data
,
metadata
=
metadata
,
api_version
=
"
v1
"
,
type
=
secType
))
stringData
=
{
"
access-token
"
:
_doToken
}
secType
=
"
Opaque
"
metadata
=
{
"
name
"
:
"
digitalocean
"
}
elif
type
==
SecretType
.
STATUSSITE
:
with
open
(
_secretsPath
/
"
appsettings.production.yml
"
,
"
r
"
)
as
config
:
data
=
{
"
appsettings.production.yml
"
:
base64
.
b64encode
(
config
.
read
().
encode
()).
decode
()}
secType
=
"
Opaque
"
metadata
=
{
"
name
"
:
"
appsettings.production.yml
"
}
elif
type
==
SecretType
.
SHEVASTREAM
:
with
open
(
cwd
/
"
sources
"
/
"
shevastream
"
/
"
appsettings.json
"
,
"
r
"
)
as
config
:
data
=
{
"
appsettings.json
"
:
base64
.
b64encode
(
config
.
read
().
encode
()).
decode
()}
secType
=
"
Opaque
"
metadata
=
{
"
name
"
:
"
shevastream-appsettings
"
}
api
.
create_namespaced_secret
(
namespace
,
client
.
V1Secret
(
data
=
data
,
string_data
=
stringData
,
metadata
=
metadata
,
api_version
=
"
v1
"
,
type
=
secType
))
_logger
.
info
(
f
"
Secret
{
type
}
added to
{
namespace
}
"
)
_logger
.
info
(
f
"
Secret
{
type
}
added to
{
namespace
}
"
)
except
ApiException
as
e
:
except
ApiException
as
e
:
if
"
already exists
"
in
e
.
body
:
if
"
already exists
"
in
e
.
body
:
...
@@ -80,6 +134,12 @@ def bootstrapCluster():
...
@@ -80,6 +134,12 @@ def bootstrapCluster():
else
:
else
:
raise
e
raise
e
def
createDashboardIngress
():
templates
=
Environment
(
loader
=
FileSystemLoader
(
searchpath
=
str
(
cwd
/
"
sources
"
/
"
dashboard
"
)))
config
=
templates
.
get_template
(
"
ingress.yaml
"
).
render
(
data
=
{
"
token
"
:
"
TODO
"
})
print
(
config
)
apply
(
config
)
if
not
(
cwd
/
"
kubeconfig.yaml
"
).
is_file
():
if
not
(
cwd
/
"
kubeconfig.yaml
"
).
is_file
():
raise
"
Bootstrap called with no Kubeconfig file
"
raise
"
Bootstrap called with no Kubeconfig file
"
...
@@ -89,9 +149,20 @@ def bootstrapCluster():
...
@@ -89,9 +149,20 @@ def bootstrapCluster():
for
namespace
in
namespaces
:
for
namespace
in
namespaces
:
createNamespace
(
namespace
)
createNamespace
(
namespace
)
createTlsSecret
(
namespace
,
SecretType
.
TLS
)
createSecret
(
namespace
,
SecretType
.
TLS
)
createTlsSecret
(
namespace
,
SecretType
.
BASICAUTH
)
createSecret
(
namespace
,
SecretType
.
BASICAUTH
)
createTlsSecret
(
namespace
,
SecretType
.
REGSITRY
)
createSecret
(
namespace
,
SecretType
.
REGSITRY
)
createSecret
(
"
kube-system
"
,
SecretType
.
DASHBOARD
)
createSecret
(
"
kube-system
"
,
SecretType
.
DO
)
createSecret
(
"
status-site
"
,
SecretType
.
STATUSSITE
)
createSecret
(
"
websites
"
,
SecretType
.
SHEVASTREAM
)
apply
(
"
sources/dashboard/all.yaml
"
,
"
Dashboard
"
)
apply
(
"
sources/nginx/mandatory.yaml
"
,
"
NGINX ingress controller
"
)
apply
(
"
https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v0.3.1.yaml
"
,
"
DO Volume provisioner
"
)
createDashboardIngress
()
def
provisionCluster
():
def
provisionCluster
():
...
@@ -134,9 +205,6 @@ def generateServices():
...
@@ -134,9 +205,6 @@ def generateServices():
def
generateService
(
name
,
image
,
replicated
=
True
,
auth
=
False
,
rps
=
10
):
def
generateService
(
name
,
image
,
replicated
=
True
,
auth
=
False
,
rps
=
10
):
import
subprocess
from
jinja2
import
Template
,
Environment
,
FileSystemLoader
_logger
.
info
(
f
"
Generating
{
name
}
service
"
)
_logger
.
info
(
f
"
Generating
{
name
}
service
"
)
if
name
in
domainUrlExceptions
:
if
name
in
domainUrlExceptions
:
...
@@ -168,7 +236,8 @@ def generateService(name, image, replicated=True, auth=False, rps=10):
...
@@ -168,7 +236,8 @@ def generateService(name, image, replicated=True, auth=False, rps=10):
"
replicated
"
:
replicated
,
"
replicated
"
:
replicated
,
"
rps
"
:
rps
,
"
rps
"
:
rps
,
"
auth
"
:
auth
,
"
auth
"
:
auth
,
"
hosts
"
:
hosts
"
hosts
"
:
hosts
,
"
secret
"
:
None
if
"
shevastream
"
not
in
name
else
(
"
appsettings
"
,
"
/run/secrets/settings/
"
,
"
shevastream-appsettings
"
,
"
appsettings
"
,
"
appsettings.production.json
"
)
}
}
)
)
...
@@ -196,7 +265,7 @@ def kubeconfig():
...
@@ -196,7 +265,7 @@ def kubeconfig():
if
response
.
status_code
==
200
:
if
response
.
status_code
==
200
:
try
:
try
:
response
=
response
.
content
.
decode
(
'
utf-8
'
)
response
=
response
.
content
.
decode
(
"
utf-8
"
)
_logger
.
debug
(
f
"
Kubeconfig
\n
{
response
}
"
)
_logger
.
debug
(
f
"
Kubeconfig
\n
{
response
}
"
)
with
open
(
cwd
/
"
kubeconfig.yaml
"
,
"
w
"
)
as
kubeconfigFile
:
with
open
(
cwd
/
"
kubeconfig.yaml
"
,
"
w
"
)
as
kubeconfigFile
:
kubeconfigFile
.
write
(
response
)
kubeconfigFile
.
write
(
response
)
...
@@ -222,14 +291,14 @@ def setup_logger(level):
...
@@ -222,14 +291,14 @@ def setup_logger(level):
datefmt
=
None
,
datefmt
=
None
,
reset
=
True
,
reset
=
True
,
log_colors
=
{
log_colors
=
{
'
DEBUG
'
:
'
cyan
'
,
"
DEBUG
"
:
"
cyan
"
,
'
INFO
'
:
'
green
'
,
"
INFO
"
:
"
green
"
,
'
WARNING
'
:
'
yellow
'
,
"
WARNING
"
:
"
yellow
"
,
'
ERROR
'
:
'
red
'
,
"
ERROR
"
:
"
red
"
,
'
CRITICAL
'
:
'
red
'
,
"
CRITICAL
"
:
"
red
"
,
}
}
)
)
logger
=
logging
.
getLogger
(
'
example
'
)
logger
=
logging
.
getLogger
(
"
example
"
)
handler
=
logging
.
StreamHandler
()
handler
=
logging
.
StreamHandler
()
handler
.
setFormatter
(
formatter
)
handler
.
setFormatter
(
formatter
)
logger
.
addHandler
(
handler
)
logger
.
addHandler
(
handler
)
...
@@ -267,7 +336,7 @@ def main():
...
@@ -267,7 +336,7 @@ def main():
parser
=
argparse
.
ArgumentParser
(
description
=
"
Deploy K8S to Digital Ocean.
"
)
parser
=
argparse
.
ArgumentParser
(
description
=
"
Deploy K8S to Digital Ocean.
"
)
parser
.
add_argument
(
'
--verbose
'
,
'
-v
'
,
dest
=
"
verbose
"
,
action
=
'
count
'
,
default
=
4
,
help
=
"
Log level: CRITICAL, ERROR, WARNING, INFO, DEBUG
"
)
parser
.
add_argument
(
"
--verbose
"
,
"
-v
"
,
dest
=
"
verbose
"
,
action
=
"
count
"
,
default
=
4
,
help
=
"
Log level: CRITICAL, ERROR, WARNING, INFO, DEBUG
"
)
subparsers
=
parser
.
add_subparsers
(
title
=
"
commands
"
,
dest
=
"
command
"
,
required
=
True
)
subparsers
=
parser
.
add_subparsers
(
title
=
"
commands
"
,
dest
=
"
command
"
,
required
=
True
)
...
@@ -287,6 +356,7 @@ def main():
...
@@ -287,6 +356,7 @@ def main():
bootstrapParser
=
subparsers
.
add_parser
(
"
bootstrap
"
)
bootstrapParser
=
subparsers
.
add_parser
(
"
bootstrap
"
)
addSecretsPathArgument
(
bootstrapParser
)
addSecretsPathArgument
(
bootstrapParser
)
addDockerPassArgument
(
bootstrapParser
)
addDockerPassArgument
(
bootstrapParser
)
addDOTokenArgument
(
bootstrapParser
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
...
@@ -297,10 +367,10 @@ def main():
...
@@ -297,10 +367,10 @@ def main():
global
_secretsPath
global
_secretsPath
_logger
=
setup_logger
(
60
-
args
.
verbose
*
10
)
_logger
=
setup_logger
(
60
-
args
.
verbose
*
10
)
_doToken
=
args
.
doToken
if
'
doToken
'
in
args
else
""
_doToken
=
args
.
doToken
if
"
doToken
"
in
args
else
""
_name
=
args
.
name
if
'
name
'
in
args
else
""
_name
=
args
.
name
if
"
name
"
in
args
else
""
_dockerPass
=
args
.
dockerPass
if
'
dockerPass
'
in
args
else
""
_dockerPass
=
args
.
dockerPass
if
"
dockerPass
"
in
args
else
""
_secretsPath
=
args
.
secretsPath
if
'
secretsPath
'
in
args
else
""
_secretsPath
=
args
.
secretsPath
if
"
secretsPath
"
in
args
else
""
if
args
.
command
==
"
deploy
"
:
if
args
.
command
==
"
deploy
"
:
deploy
()
deploy
()
...
@@ -394,5 +464,5 @@ domainUrlExceptions = {
...
@@ -394,5 +464,5 @@ domainUrlExceptions = {
namespaces
=
[
"
websites
"
,
"
monitoring
"
,
"
ingress
"
,
"
status-site
"
,
"
kube-system
"
,
"
gitlab
"
,
"
review
"
]
namespaces
=
[
"
websites
"
,
"
monitoring
"
,
"
ingress
"
,
"
status-site
"
,
"
kube-system
"
,
"
gitlab
"
,
"
review
"
]
if
__name__
==
'
__main__
'
:
if
__name__
==
"
__main__
"
:
main
()
main
()
This diff is collapsed.
Click to expand it.
infra/sources/dashboard/ingress.yaml
+
1
−
1
View file @
4629ca85
...
@@ -8,7 +8,7 @@ metadata:
...
@@ -8,7 +8,7 @@ metadata:
nginx.ingress.kubernetes.io/auth-realm
:
"
Authentication
Required!"
nginx.ingress.kubernetes.io/auth-realm
:
"
Authentication
Required!"
nginx.ingress.kubernetes.io/auth-type
:
basic
nginx.ingress.kubernetes.io/auth-type
:
basic
nginx.ingress.kubernetes.io/configuration-snippet
:
|
nginx.ingress.kubernetes.io/configuration-snippet
:
|
proxy_set_header Authorization "Bearer
__DASHBOARD_TOKEN__
";
proxy_set_header Authorization "Bearer
{{ data.token }}
";
name
:
dashboard
name
:
dashboard
namespace
:
kube-system
namespace
:
kube-system
spec
:
spec
:
...
...
This diff is collapsed.
Click to expand it.
infra/sources/service/website.yaml
+
13
−
0
View file @
4629ca85
...
@@ -49,6 +49,19 @@ spec:
...
@@ -49,6 +49,19 @@ spec:
-
name
:
{{
data.name
}}
-
name
:
{{
data.name
}}
image
:
{{
data.image
}}
image
:
{{
data.image
}}
imagePullPolicy
:
Always
imagePullPolicy
:
Always
{
%
if data.secret is not none %
}
volumeMounts
:
-
name
:
{{
data.secret
[
0
]
}}
mountPath
:
{{
data.secret
[
1
]
}}
volumes
:
-
name
:
{{
data.secret
[
0
]
}}
secret
:
secretName
:
{{
data.secret
[
2
]
}}
items
:
-
key
:
{{
data.secret
[
3
]
}}
path
:
{{
data.secret
[
4
]
}}
{
%
endif %
}
{
%
else %
}
{
%
else %
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment