Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
f685ed72
Commit
f685ed72
authored
Nov 26, 2019
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanup Review App components by name in addition to by label
Signed-off-by:
Rémy Coutable
<
remy@rymai.me
>
parent
754bb5d8
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
106 additions
and
26 deletions
+106
-26
lib/quality/kubernetes_client.rb
lib/quality/kubernetes_client.rb
+33
-3
scripts/review_apps/review-apps.sh
scripts/review_apps/review-apps.sh
+21
-1
spec/lib/quality/kubernetes_client_spec.rb
spec/lib/quality/kubernetes_client_spec.rb
+52
-22
No files found.
lib/quality/kubernetes_client.rb
View file @
f685ed72
...
@@ -4,6 +4,7 @@ require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
...
@@ -4,6 +4,7 @@ require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
module
Quality
module
Quality
class
KubernetesClient
class
KubernetesClient
RESOURCE_LIST
=
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa,crd'
CommandFailedError
=
Class
.
new
(
StandardError
)
CommandFailedError
=
Class
.
new
(
StandardError
)
attr_reader
:namespace
attr_reader
:namespace
...
@@ -13,6 +14,13 @@ module Quality
...
@@ -13,6 +14,13 @@ module Quality
end
end
def
cleanup
(
release_name
:,
wait:
true
)
def
cleanup
(
release_name
:,
wait:
true
)
delete_by_selector
(
release_name:
release_name
,
wait:
wait
)
delete_by_matching_name
(
release_name:
release_name
)
end
private
def
delete_by_selector
(
release_name
:,
wait
:)
selector
=
case
release_name
selector
=
case
release_name
when
String
when
String
%(-l release="#{release_name}")
%(-l release="#{release_name}")
...
@@ -23,9 +31,9 @@ module Quality
...
@@ -23,9 +31,9 @@ module Quality
end
end
command
=
[
command
=
[
%(--namespace "#{namespace}")
,
'delete'
,
'delete'
,
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa'
,
RESOURCE_LIST
,
%(--namespace "#{namespace}")
,
'--now'
,
'--now'
,
'--ignore-not-found'
,
'--ignore-not-found'
,
'--include-uninitialized'
,
'--include-uninitialized'
,
...
@@ -36,7 +44,29 @@ module Quality
...
@@ -36,7 +44,29 @@ module Quality
run_command
(
command
)
run_command
(
command
)
end
end
private
def
delete_by_matching_name
(
release_name
:)
resource_names
=
raw_resource_names
command
=
[
'delete'
,
%(--namespace "#{namespace}")
]
Array
(
release_name
).
each
do
|
release
|
resource_names
.
select
{
|
resource_name
|
resource_name
.
include?
(
release
)
}
.
each
{
|
matching_resource
|
run_command
(
command
+
[
matching_resource
])
}
end
end
def
raw_resource_names
command
=
[
'get'
,
RESOURCE_LIST
,
%(--namespace "#{namespace}")
,
'-o custom-columns=NAME:.metadata.name'
]
run_command
(
command
).
lines
.
map
(
&
:strip
)
end
def
run_command
(
command
)
def
run_command
(
command
)
final_command
=
[
'kubectl'
,
*
command
].
join
(
' '
)
final_command
=
[
'kubectl'
,
*
command
].
join
(
' '
)
...
...
scripts/review_apps/review-apps.sh
View file @
f685ed72
...
@@ -48,11 +48,31 @@ function delete_release() {
...
@@ -48,11 +48,31 @@ function delete_release() {
return
return
fi
fi
echoinfo
"Deleting release '
${
release
}
'..."
true
helm_delete_release
"
${
namespace
}
"
"
${
release
}
"
kubectl_cleanup_release
"
${
namespace
}
"
"
${
release
}
"
}
function
helm_delete_release
()
{
local
namespace
=
"
${
1
}
"
local
release
=
"
${
2
}
"
echoinfo
"Deleting Helm release '
${
release
}
'..."
true
helm delete
--tiller-namespace
"
${
namespace
}
"
--purge
"
${
release
}
"
helm delete
--tiller-namespace
"
${
namespace
}
"
--purge
"
${
release
}
"
}
}
function
kubectl_cleanup_release
()
{
local
namespace
=
"
${
1
}
"
local
release
=
"
${
2
}
"
echoinfo
"Deleting all K8s resources matching '
${
release
}
'..."
true
kubectl
--namespace
"
${
namespace
}
"
get ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa,crd 2>&1
\
|
grep
"
${
release
}
"
\
|
awk
'{print $1}'
\
| xargs kubectl
--namespace
"
${
namespace
}
"
delete
\
||
true
}
function
delete_failed_release
()
{
function
delete_failed_release
()
{
local
namespace
=
"
${
KUBE_NAMESPACE
}
"
local
namespace
=
"
${
KUBE_NAMESPACE
}
"
local
release
=
"
${
CI_ENVIRONMENT_SLUG
}
"
local
release
=
"
${
CI_ENVIRONMENT_SLUG
}
"
...
...
spec/lib/quality/kubernetes_client_spec.rb
View file @
f685ed72
...
@@ -5,15 +5,27 @@ require 'fast_spec_helper'
...
@@ -5,15 +5,27 @@ require 'fast_spec_helper'
RSpec
.
describe
Quality
::
KubernetesClient
do
RSpec
.
describe
Quality
::
KubernetesClient
do
let
(
:namespace
)
{
'review-apps-ee'
}
let
(
:namespace
)
{
'review-apps-ee'
}
let
(
:release_name
)
{
'my-release'
}
let
(
:release_name
)
{
'my-release'
}
let
(
:pod_for_release
)
{
"pod-my-release-abcd"
}
let
(
:raw_resource_names_str
)
{
"NAME
\n
foo
\n
#{
pod_for_release
}
\n
bar"
}
let
(
:raw_resource_names
)
{
raw_resource_names_str
.
lines
.
map
(
&
:strip
)
}
subject
{
described_class
.
new
(
namespace:
namespace
)
}
subject
{
described_class
.
new
(
namespace:
namespace
)
}
describe
'RESOURCE_LIST'
do
it
'returns the correct list of resources separated by commas'
do
expect
(
described_class
::
RESOURCE_LIST
).
to
eq
(
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa,crd'
)
end
end
describe
'#cleanup'
do
describe
'#cleanup'
do
before
do
allow
(
subject
).
to
receive
(
:raw_resource_names
).
and_return
(
raw_resource_names
)
end
it
'raises an error if the Kubernetes command fails'
do
it
'raises an error if the Kubernetes command fails'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl --namespace "#{namespace}" delete )
\
.
with
([
"kubectl delete
#{
described_class
::
RESOURCE_LIST
}
"
+
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa '
\
%(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=true -l release="#{release_name}")
])
"--now --ignore-not-found --include-uninitialized --wait=true -l release=
\"
#{
release_name
}
\"
"
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
false
)))
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
false
)))
expect
{
subject
.
cleanup
(
release_name:
release_name
)
}.
to
raise_error
(
described_class
::
CommandFailedError
)
expect
{
subject
.
cleanup
(
release_name:
release_name
)
}.
to
raise_error
(
described_class
::
CommandFailedError
)
...
@@ -21,9 +33,12 @@ RSpec.describe Quality::KubernetesClient do
...
@@ -21,9 +33,12 @@ RSpec.describe Quality::KubernetesClient do
it
'calls kubectl with the correct arguments'
do
it
'calls kubectl with the correct arguments'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl --namespace "#{namespace}" delete )
\
.
with
([
"kubectl delete
#{
described_class
::
RESOURCE_LIST
}
"
+
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa '
\
%(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=true -l release="#{release_name}")
])
"--now --ignore-not-found --include-uninitialized --wait=true -l release=
\"
#{
release_name
}
\"
"
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl delete --namespace "#{namespace}" #{pod_for_release})
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
# We're not verifying the output here, just silencing it
# We're not verifying the output here, just silencing it
...
@@ -35,20 +50,22 @@ RSpec.describe Quality::KubernetesClient do
...
@@ -35,20 +50,22 @@ RSpec.describe Quality::KubernetesClient do
it
'raises an error if the Kubernetes command fails'
do
it
'raises an error if the Kubernetes command fails'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl --namespace "#{namespace}" delete )
\
.
with
([
"kubectl delete
#{
described_class
::
RESOURCE_LIST
}
"
+
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa '
\
%(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=true -l 'release in (#{release_name.join(', ')})')
])
"--now --ignore-not-found --include-uninitialized --wait=true -l 'release in (
#{
release_name
.
join
(
', '
)
}
)'"
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
false
)))
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
false
)))
expect
{
subject
.
cleanup
(
release_name:
release_name
)
}.
to
raise_error
(
described_class
::
CommandFailedError
)
expect
{
subject
.
cleanup
(
release_name:
release_name
)
}.
to
raise_error
(
described_class
::
CommandFailedError
)
end
end
it
'calls kubectl with the correct arguments'
do
it
'calls kubectl with the correct arguments'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl --namespace "#{namespace}" delete )
\
.
with
([
"kubectl delete
#{
described_class
::
RESOURCE_LIST
}
"
+
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa '
\
%(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=true -l 'release in (#{release_name.join(', ')})')
])
"--now --ignore-not-found --include-uninitialized --wait=true -l 'release in (
#{
release_name
.
join
(
', '
)
}
)'"
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl delete --namespace "#{namespace}" #{pod_for_release})
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
# We're not verifying the output here, just silencing it
# We're not verifying the output here, just silencing it
expect
{
subject
.
cleanup
(
release_name:
release_name
)
}.
to
output
.
to_stdout
expect
{
subject
.
cleanup
(
release_name:
release_name
)
}.
to
output
.
to_stdout
...
@@ -58,24 +75,37 @@ RSpec.describe Quality::KubernetesClient do
...
@@ -58,24 +75,37 @@ RSpec.describe Quality::KubernetesClient do
context
'with `wait: false`'
do
context
'with `wait: false`'
do
it
'raises an error if the Kubernetes command fails'
do
it
'raises an error if the Kubernetes command fails'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl --namespace "#{namespace}" delete )
\
.
with
([
"kubectl delete
#{
described_class
::
RESOURCE_LIST
}
"
+
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa '
\
%(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=false -l release="#{release_name}")
])
"--now --ignore-not-found --include-uninitialized --wait=false -l release=
\"
#{
release_name
}
\"
"
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
false
)))
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
false
)))
expect
{
subject
.
cleanup
(
release_name:
release_name
,
wait:
false
)
}.
to
raise_error
(
described_class
::
CommandFailedError
)
expect
{
subject
.
cleanup
(
release_name:
release_name
,
wait:
false
)
}.
to
raise_error
(
described_class
::
CommandFailedError
)
end
end
it
'calls kubectl with the correct arguments'
do
it
'calls kubectl with the correct arguments'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl --namespace "#{namespace}" delete )
\
.
with
([
"kubectl delete
#{
described_class
::
RESOURCE_LIST
}
"
+
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa '
\
%(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=false -l release="#{release_name}")
])
"--now --ignore-not-found --include-uninitialized --wait=false -l release=
\"
#{
release_name
}
\"
"
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
%(kubectl delete --namespace "#{namespace}" #{pod_for_release})
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
''
,
''
,
double
(
success?:
true
)))
# We're not verifying the output here, just silencing it
# We're not verifying the output here, just silencing it
expect
{
subject
.
cleanup
(
release_name:
release_name
,
wait:
false
)
}.
to
output
.
to_stdout
expect
{
subject
.
cleanup
(
release_name:
release_name
,
wait:
false
)
}.
to
output
.
to_stdout
end
end
end
end
end
end
describe
'#raw_resource_names'
do
it
'calls kubectl to retrieve the resource names'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen_with_detail
)
.
with
([
"kubectl get
#{
described_class
::
RESOURCE_LIST
}
"
+
%(--namespace "#{namespace}" -o custom-columns=NAME:.metadata.name)
])
.
and_return
(
Gitlab
::
Popen
::
Result
.
new
([],
raw_resource_names_str
,
''
,
double
(
success?:
true
)))
expect
(
subject
.
__send__
(
:raw_resource_names
)).
to
eq
(
raw_resource_names
)
end
end
end
end
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