mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 01:18:58 +00:00
20ed2c6bcf
* salt/cloud/__init__.py: remove repr formatting * salt/cloud/clouds/azurearm.py: remove repr formatting * salt/cloud/clouds/ec2.py: remove repr formatting * salt/cloud/clouds/profitbricks.py: remove repr formatting * salt/loader.py: remove repr formatting * salt/modules/win_file.py: remove repr formatting * salt/modules/zypper.py: remove repr formatting * salt/pillar/consul_pillar.py: remove repr formatting * salt/renderers/pyobjects.py: remove repr formatting * salt/returners/sentry_return.py: remove repr formatting * salt/states/bower.py: remove repr formatting * salt/states/cabal.py: remove repr formatting * salt/states/cmd.py: remove repr formatting * salt/states/composer.py: remove repr formatting * salt/states/win_network.py: remove repr formatting * salt/states/eselect.py: remove repr formatting * salt/states/file.py: remove repr formatting * salt/states/htpasswd.py: remove repr formatting * salt/states/memcached.py: remove repr formatting * salt/states/npm.py: remove repr formatting * salt/states/pip_state.py: remove repr formatting * salt/states/pkg.py: remove repr formatting * salt/states/pkgrepo.py: remove repr formatting * salt/states/supervisord.py: remove repr formatting * salt/states/timezone.py: remove repr formatting * salt/states/virtualenv_mod.py: remove repr formatting * salt/states/dockerio.py: remove repr formatting * salt/states/win_system.py: remove repr formatting * salt/utils/nb_popen.py: remove repr formatting * salt/utils/cloud.py: remove repr formatting * Add pylint disable due to legit usage of repr flag See https://github.com/saltstack/salt-pylint/pull/6 * Fix composer tests These tests needed to be updated because quoting was changed in the state module in 9dc9146. There was an unnecessary !r used for the exception class there, which means that instead of the exception class being passed through the formatter and coming out with the equivalent value of err.__str__(), we get a repr'ed instance of the exception class (i.e. SaltException('',)) in the state output. The unit test was asserting that we have that repr'ed instance of SaltException in the output, a case of writing the test to confirm the badly-conceived output in the state. This has also been corrected. * salt/cloud/clouds/azurearm.py: lint fixes * salt/modules/boto_s3_bucket.py: lint fixes * salt/modules/minion.py: lint fixes * salt/modules/reg.py: lint fixes * salt/modules/testinframod.py: lint fixes * salt/modules/win_iis.py: lint fixes * salt/pillar/csvpillar.py: lint fixes * salt/utils/win_functions.py: lint fixes * salt/states/nxos.py: lint fixes * salt/returners/mongo_future_return.py: lint fixes * tests/integration/__init__.py: lint fixes * tests/unit/context_test.py: lint fixes * tests/integration/states/file.py: lint fixes * tests/integration/utils/test_reactor.py: lint fixes * tests/integration/utils/testprogram.py: lint fixes * tests/unit/__init__.py: lint fixes * tests/integration/shell/minion.py: lint fixes * tests/unit/modules/boto_apigateway_test.py: lint fixes * tests/unit/modules/boto_cognitoidentity_test.py: lint fixes * tests/unit/modules/boto_elasticsearch_domain_test.py: lint fixes * tests/unit/modules/k8s_test.py: lint fixes * tests/unit/modules/reg_win_test.py: lint fixes * tests/unit/states/boto_apigateway_test.py: lint fixes * tests/unit/states/boto_cognitoidentity_test.py: lint fixes * tests/unit/states/boto_elasticsearch_domain_test.py: lint fixes
409 lines
15 KiB
Python
409 lines
15 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
Unit Tests for the k8s execution module.
|
|
'''
|
|
|
|
# Import Python libs
|
|
from __future__ import absolute_import
|
|
import json
|
|
import hashlib
|
|
import base64
|
|
import time
|
|
from subprocess import Popen, PIPE
|
|
|
|
# Import Salt Testing libs
|
|
from salttesting import TestCase
|
|
from salttesting.helpers import ensure_in_syspath, skip_if_binaries_missing
|
|
|
|
ensure_in_syspath('../../')
|
|
|
|
# Import Salt libs
|
|
import salt.modules.k8s as k8s
|
|
|
|
# Import 3rd-party libs
|
|
from salt.ext.six.moves import range # pylint: disable=import-error
|
|
|
|
TestCase.maxDiff = None
|
|
|
|
|
|
@skip_if_binaries_missing(['kubectl'])
|
|
class TestK8SNamespace(TestCase):
|
|
|
|
def test_get_namespaces(self):
|
|
res = k8s.get_namespaces(apiserver_url="http://127.0.0.1:8080")
|
|
a = len(res.get("items"))
|
|
proc = Popen(["kubectl", "get", "namespaces", "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = len(kubectl_out.get("items"))
|
|
self.assertEqual(a, b)
|
|
|
|
def test_get_one_namespace(self):
|
|
res = k8s.get_namespaces("default", apiserver_url="http://127.0.0.1:8080")
|
|
a = res.get("metadata", {}).get("name", "a")
|
|
proc = Popen(["kubectl", "get", "namespaces", "default", "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = kubectl_out.get("metadata", {}).get("name", "b")
|
|
self.assertEqual(a, b)
|
|
|
|
def test_create_namespace(self):
|
|
hash = hashlib.sha1()
|
|
hash.update(str(time.time()))
|
|
nsname = hash.hexdigest()[:16]
|
|
res = k8s.create_namespace(nsname, apiserver_url="http://127.0.0.1:8080")
|
|
proc = Popen(["kubectl", "get", "namespaces", nsname, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
# if creation is failed, kubernetes return non json error message
|
|
self.assertTrue(isinstance(kubectl_out, dict))
|
|
|
|
|
|
@skip_if_binaries_missing(['kubectl'])
|
|
class TestK8SSecrets(TestCase):
|
|
|
|
def setUp(self):
|
|
hash = hashlib.sha1()
|
|
hash.update(str(time.time()))
|
|
self.name = hash.hexdigest()[:16]
|
|
data = {"testsecret": base64.encodestring("teststring")}
|
|
self.request = {
|
|
"apiVersion": "v1",
|
|
"kind": "Secret",
|
|
"metadata": {
|
|
"name": self.name,
|
|
"namespace": "default",
|
|
},
|
|
"data": data,
|
|
}
|
|
|
|
def test_get_secrets(self):
|
|
res = k8s.get_secrets("default", apiserver_url="http://127.0.0.1:8080")
|
|
a = len(res.get("items", []))
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "secrets", "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = len(kubectl_out.get("items", []))
|
|
self.assertEqual(a, b)
|
|
|
|
def test_get_one_secret(self):
|
|
name = self.name
|
|
filename = "/tmp/{0}.json".format(name)
|
|
with open(filename, 'w') as f:
|
|
json.dump(self.request, f)
|
|
|
|
create = Popen(["kubectl", "--namespace=default", "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.1)
|
|
res = k8s.get_secrets("default", name, apiserver_url="http://127.0.0.1:8080")
|
|
a = res.get("metadata", {}).get("name", "a")
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "secrets", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = kubectl_out.get("metadata", {}).get("name", "b")
|
|
self.assertEqual(a, b)
|
|
|
|
def test_get_decoded_secret(self):
|
|
name = self.name
|
|
filename = "/tmp/{0}.json".format(name)
|
|
with open(filename, 'w') as f:
|
|
json.dump(self.request, f)
|
|
|
|
create = Popen(["kubectl", "--namespace=default", "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give etcd to populate data on all nodes
|
|
time.sleep(0.1)
|
|
res = k8s.get_secrets("default", name, apiserver_url="http://127.0.0.1:8080", decode=True)
|
|
a = res.get("data", {}).get("testsecret", )
|
|
self.assertEqual(a, "teststring")
|
|
|
|
def test_create_secret(self):
|
|
name = self.name
|
|
names = []
|
|
expected_data = {}
|
|
for i in range(2):
|
|
names.append("/tmp/{0}-{1}".format(name, i))
|
|
with open("/tmp/{0}-{1}".format(name, i), 'w') as f:
|
|
expected_data["{0}-{1}".format(name, i)] = base64.b64encode("{0}{1}".format(name, i))
|
|
f.write("{0}{1}".format(name, i))
|
|
res = k8s.create_secret("default", name, names, apiserver_url="http://127.0.0.1:8080")
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "secrets", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
# if creation is failed, kubernetes return non json error message
|
|
b = kubectl_out.get("data", {})
|
|
self.assertTrue(isinstance(kubectl_out, dict))
|
|
self.assertEqual(expected_data, b)
|
|
|
|
def test_update_secret(self):
|
|
name = self.name
|
|
filename = "/tmp/{0}.json".format(name)
|
|
with open(filename, 'w') as f:
|
|
json.dump(self.request, f)
|
|
|
|
create = Popen(["kubectl", "--namespace=default", "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.1)
|
|
expected_data = {}
|
|
names = []
|
|
for i in range(3):
|
|
names.append("/tmp/{0}-{1}-updated".format(name, i))
|
|
with open("/tmp/{0}-{1}-updated".format(name, i), 'w') as f:
|
|
expected_data["{0}-{1}-updated".format(name, i)] = base64.b64encode("{0}{1}-updated".format(name, i))
|
|
f.write("{0}{1}-updated".format(name, i))
|
|
|
|
res = k8s.update_secret("default", name, names, apiserver_url="http://127.0.0.1:8080")
|
|
# if creation is failed, kubernetes return non json error message
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "secrets", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
# if creation is failed, kubernetes return non json error message
|
|
b = kubectl_out.get("data", {})
|
|
self.assertTrue(isinstance(kubectl_out, dict))
|
|
self.assertEqual(expected_data, b)
|
|
|
|
def test_delete_secret(self):
|
|
name = self.name
|
|
filename = "/tmp/{0}.json".format(name)
|
|
with open(filename, 'w') as f:
|
|
json.dump(self.request, f)
|
|
|
|
create = Popen(["kubectl", "--namespace=default", "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.1)
|
|
res = k8s.delete_secret("default", name, apiserver_url="http://127.0.0.1:8080")
|
|
time.sleep(0.1)
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "secrets", name, "-o", "json"], stdout=PIPE, stderr=PIPE)
|
|
kubectl_out, err = proc.communicate()
|
|
# stdout is empty, stderr is showing something like "not found"
|
|
self.assertEqual('', kubectl_out)
|
|
self.assertEqual('Error from server: secrets "{0}" not found\n'.format(name), err)
|
|
|
|
|
|
@skip_if_binaries_missing(['kubectl'])
|
|
class TestK8SResourceQuotas(TestCase):
|
|
|
|
def setUp(self):
|
|
hash = hashlib.sha1()
|
|
hash.update(str(time.time()))
|
|
self.name = hash.hexdigest()[:16]
|
|
|
|
def test_get_resource_quotas(self):
|
|
name = self.name
|
|
namespace = self.name
|
|
create_namespace = Popen(["kubectl", "create", "namespace", namespace], stdout=PIPE)
|
|
create_namespace = Popen(["kubectl", "create", "namespace", namespace], stdout=PIPE)
|
|
request = """
|
|
apiVersion: v1
|
|
kind: ResourceQuota
|
|
metadata:
|
|
name: {0}
|
|
spec:
|
|
hard:
|
|
cpu: "20"
|
|
memory: 1Gi
|
|
persistentvolumeclaims: "10"
|
|
pods: "10"
|
|
replicationcontrollers: "20"
|
|
resourcequotas: "1"
|
|
secrets: "10"
|
|
services: "5"
|
|
""".format(name)
|
|
filename = "/tmp/{0}.yaml".format(name)
|
|
with open(filename, 'w') as f:
|
|
f.write(request)
|
|
|
|
create = Popen(["kubectl", "--namespace={0}".format(namespace), "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.2)
|
|
res = k8s.get_resource_quotas(namespace, apiserver_url="http://127.0.0.1:8080")
|
|
a = len(res.get("items", []))
|
|
proc = Popen(["kubectl", "--namespace={0}".format(namespace), "get", "quota", "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = len(kubectl_out.get("items", []))
|
|
self.assertEqual(a, b)
|
|
|
|
def test_get_one_resource_quota(self):
|
|
name = self.name
|
|
namespace = self.name
|
|
create_namespace = Popen(["kubectl", "create", "namespace", namespace], stdout=PIPE)
|
|
request = """
|
|
apiVersion: v1
|
|
kind: ResourceQuota
|
|
metadata:
|
|
name: {0}
|
|
spec:
|
|
hard:
|
|
cpu: "20"
|
|
memory: 1Gi
|
|
persistentvolumeclaims: "10"
|
|
pods: "10"
|
|
replicationcontrollers: "20"
|
|
resourcequotas: "1"
|
|
secrets: "10"
|
|
services: "5"
|
|
""".format(name)
|
|
filename = "/tmp/{0}.yaml".format(name)
|
|
with open(filename, 'w') as f:
|
|
f.write(request)
|
|
|
|
create = Popen(["kubectl", "--namespace={0}".format(namespace), "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.2)
|
|
res = k8s.get_resource_quotas(namespace, name, apiserver_url="http://127.0.0.1:8080")
|
|
a = res.get("metadata", {}).get("name", "a")
|
|
proc = Popen(["kubectl", "--namespace={0}".format(namespace), "get", "quota", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = kubectl_out.get("metadata", {}).get("name", "b")
|
|
self.assertEqual(a, b)
|
|
|
|
def test_create_resource_quota(self):
|
|
name = self.name
|
|
namespace = self.name
|
|
create_namespace = Popen(["kubectl", "create", "namespace", namespace], stdout=PIPE)
|
|
quota = {
|
|
"cpu": "20",
|
|
"memory": "1Gi"
|
|
}
|
|
res = k8s.create_resource_quota(namespace, quota, name=name, apiserver_url="http://127.0.0.1:8080")
|
|
proc = Popen(["kubectl", "--namespace={0}".format(namespace), "get", "quota", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
self.assertTrue(isinstance(kubectl_out, dict))
|
|
|
|
def test_update_resource_quota(self):
|
|
name = self.name
|
|
namespace = self.name
|
|
create_namespace = Popen(["kubectl", "create", "namespace", namespace], stdout=PIPE)
|
|
request = """
|
|
apiVersion: v1
|
|
kind: ResourceQuota
|
|
metadata:
|
|
name: {0}
|
|
spec:
|
|
hard:
|
|
cpu: "20"
|
|
memory: 1Gi
|
|
persistentvolumeclaims: "10"
|
|
pods: "10"
|
|
replicationcontrollers: "20"
|
|
resourcequotas: "1"
|
|
secrets: "10"
|
|
services: "5"
|
|
""".format(name)
|
|
filename = "/tmp/{0}.yaml".format(name)
|
|
with open(filename, 'w') as f:
|
|
f.write(request)
|
|
|
|
create = Popen(["kubectl", "--namespace={0}".format(namespace), "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.2)
|
|
quota = {
|
|
"cpu": "10",
|
|
"memory": "2Gi"
|
|
}
|
|
res = k8s.create_resource_quota(namespace, quota, name=name, apiserver_url="http://127.0.0.1:8080", update=True)
|
|
proc = Popen(["kubectl", "--namespace={0}".format(namespace), "get", "quota", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
limit = kubectl_out.get("spec").get("hard").get("memory")
|
|
self.assertEqual("2Gi", limit)
|
|
|
|
|
|
@skip_if_binaries_missing(['kubectl'])
|
|
class TestK8SLimitRange(TestCase):
|
|
|
|
def setUp(self):
|
|
hash = hashlib.sha1()
|
|
hash.update(str(time.time()))
|
|
self.name = hash.hexdigest()[:16]
|
|
|
|
def test_create_limit_range(self):
|
|
name = self.name
|
|
limits = {
|
|
"Container": {
|
|
"defaultRequest": {
|
|
"cpu": "100m"
|
|
}
|
|
}
|
|
}
|
|
res = k8s.create_limit_range("default", limits, name=name, apiserver_url="http://127.0.0.1:8080")
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "limits", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
self.assertTrue(isinstance(kubectl_out, dict))
|
|
|
|
def test_update_limit_range(self):
|
|
name = self.name
|
|
request = """
|
|
apiVersion: v1
|
|
kind: LimitRange
|
|
metadata:
|
|
name: {0}
|
|
spec:
|
|
limits:
|
|
- default:
|
|
cpu: 200m
|
|
memory: 512Mi
|
|
defaultRequest:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
type: Container
|
|
""".format(name)
|
|
limits = {
|
|
"Container": {
|
|
"defaultRequest": {
|
|
"cpu": "100m"
|
|
}
|
|
}
|
|
}
|
|
filename = "/tmp/{0}.yaml".format(name)
|
|
with open(filename, 'w') as f:
|
|
f.write(request)
|
|
|
|
create = Popen(["kubectl", "--namespace=default", "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.1)
|
|
res = k8s.create_limit_range("default", limits, name=name, apiserver_url="http://127.0.0.1:8080", update=True)
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "limits", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
limit = kubectl_out.get("spec").get("limits")[0].get("defaultRequest").get("cpu")
|
|
self.assertEqual("100m", limit)
|
|
|
|
def test_get_limit_ranges(self):
|
|
res = k8s.get_limit_ranges("default", apiserver_url="http://127.0.0.1:8080")
|
|
a = len(res.get("items", []))
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "limits", "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = len(kubectl_out.get("items", []))
|
|
self.assertEqual(a, b)
|
|
|
|
def test_get_one_limit_range(self):
|
|
name = self.name
|
|
request = """
|
|
apiVersion: v1
|
|
kind: LimitRange
|
|
metadata:
|
|
name: {0}
|
|
spec:
|
|
limits:
|
|
- default:
|
|
cpu: 200m
|
|
memory: 512Mi
|
|
defaultRequest:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
type: Container
|
|
""".format(name)
|
|
filename = "/tmp/{0}.yaml".format(name)
|
|
with open(filename, 'w') as f:
|
|
f.write(request)
|
|
|
|
create = Popen(["kubectl", "--namespace=default", "create", "-f", filename], stdout=PIPE)
|
|
# wee need to give kubernetes time save data in etcd
|
|
time.sleep(0.1)
|
|
res = k8s.get_limit_ranges("default", name, apiserver_url="http://127.0.0.1:8080")
|
|
a = res.get("metadata", {}).get("name", "a")
|
|
proc = Popen(["kubectl", "--namespace=default", "get", "limits", name, "-o", "json"], stdout=PIPE)
|
|
kubectl_out = json.loads(proc.communicate()[0])
|
|
b = kubectl_out.get("metadata", {}).get("name", "b")
|
|
self.assertEqual(a, b)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
from integration import run_tests
|
|
run_tests(TestK8SNamespace,
|
|
TestK8SSecrets,
|
|
TestK8SResourceQuotas,
|
|
TestK8SLimitRange,
|
|
needs_daemon=False)
|