def __init__(self, name, start_calico=True, dind=True): self.name = name self.dind = dind self.workloads = set() # This variable is used to assert on destruction that this object was # cleaned up. If not used as a context manager, users of this object self._cleaned = False if dind: docker.rm("-f", self.name, _ok_code=[0, 1]) docker.run("--privileged", "-v", os.getcwd()+":/code", "--name", self.name, "-e", "DOCKER_DAEMON_ARGS=" "--kv-store=consul:%s:8500" % utils.get_ip(), "-tid", "calico/dind") self.ip = docker.inspect("--format", "{{ .NetworkSettings.IPAddress }}", self.name).stdout.rstrip() self.ip6 = docker.inspect("--format", "{{ .NetworkSettings." "GlobalIPv6Address }}", self.name).stdout.rstrip() # Make sure docker is up docker_ps = partial(self.execute, "docker ps") retry_until_success(docker_ps, ex_class=CalledProcessError) self.execute("docker load --input /code/calico_containers/calico-node.tar && " "docker load --input /code/calico_containers/busybox.tar") else: self.ip = get_ip() if start_calico: self.start_calico_node() self.assert_driver_up()
def wipe_etcd(): _log.debug("Wiping etcd") # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. curl_etcd(get_ip(), "calico", options=["-XDELETE"]) # Disable Usage Reporting to usage.projectcalico.org # We want to avoid polluting analytics data with unit test noise curl_etcd(get_ip(), "calico/v1/config/UsageReportingEnabled", options=["-XPUT -d value=False"]) curl_etcd(get_ip(), "calico/v1/config/LogSeverityScreen", options=["-XPUT -d value=debug"])
def wipe_etcd(): _log.debug("Wiping etcd") # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. curl_etcd(get_ip(), "calico", options=["-XDELETE"]) # Disable Usage Reporting to usage.projectcalico.org # We want to avoid polluting analytics data with unit test noise curl_etcd(get_ip(), "calico/v1/config/UsageReportingEnabled", options=["-XPUT -d value=False"]) curl_etcd(get_ip(), "calico/v1/config/LogSeverityScreen", options=["-XPUT -d value=debug"])
def __init__(self, name): self.name = name self.workloads = set() # This variable is used to assert on destruction that this object was # cleaned up. If not used as a context manager, users of this object self._cleaned = False log_and_run("docker rm -f %s || true" % self.name) log_and_run("docker run --privileged -tid" "-v `pwd`/docker:/usr/local/bin/docker " "-v %s:/code --name %s " "calico/dind:libnetwork --cluster-store=etcd://%s:2379" % (os.getcwd(), self.name, utils.get_ip())) self.ip = log_and_run("docker inspect --format " "'{{ .NetworkSettings.IPAddress }}' %s" % self.name) # Make sure docker is up docker_ps = partial(self.execute, "docker ps") retry_until_success(docker_ps, ex_class=CalledProcessError, retries=10) self.execute("gunzip -c /code/calico-node.tgz | docker load") self.execute("gunzip -c /code/busybox.tgz | docker load") self.execute( "gunzip -c /code/calico-node-libnetwork.tgz | docker load") self.start_calico_node()
def execute(self, command): """ Pass a command into a host container. Raises a CommandExecError() if the command returns a non-zero return code. :param command: The command to execute. :return: The output from the command with leading and trailing whitespace removed. """ etcd_auth = "ETCD_AUTHORITY=%s:2379" % get_ip() # Export the environment, in case the command has multiple parts, e.g. # use of | or ; command = "export %s; %s" % (etcd_auth, command) if self.dind: command = self.escape_bash_single_quotes(command) command = "docker exec -it %s bash -c '%s'" % (self.name, command) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: # Wrap the original exception with one that gives a better error # message (including command output). raise CommandExecError(e) else: return output.strip()
def setUp(self): try: self.host.execute("docker rm -f calico-node") except CommandExecError: # Presumably calico-node wasn't running pass wipe_etcd(get_ip())
def test_converter(testname, fail_expected, error_text=None): """ Convert a v1 object to v3, then apply the result and read it back. """ test_converter.__name__ = testname # Let's start every test afresh wipe_etcd(get_ip()) testdata = data[testname] # Convert data to V3 API using the tool under test rc = calicoctl("convert", data=testdata) if not fail_expected: logger.debug("Trying to convert manifest from V1 to V3") rc.assert_no_error() # Get the converted yaml and clean it up (remove fields we don't care about) converted_data = clean_calico_data(yaml.safe_load(rc.output)) original_resource = rc # Apply the converted data rc = calicoctl("create", data=original_resource.output) logger.debug("Trying to create resource using converted manifest") rc.assert_no_error() rc = calicoctl("get %s %s -o yaml" % (converted_data['kind'], name(converted_data))) # Comparison here needs to be against cleaned versions of data to remove Creation Timestamp logger.debug("Comparing 'get'ted output with original converted yaml") cleaned_output = yaml.safe_dump( clean_calico_data( yaml.safe_load(rc.output), extra_keys_to_remove=['projectcalico.org/orchestrator', 'namespace'] ) ) original_resource.assert_data(cleaned_output) else: rc.assert_error(error_text)
def setUp(self): try: self.host.execute("docker rm -f calico-node") except CommandExecError: # Presumably calico-node wasn't running pass wipe_etcd(get_ip())
def __init__(self, name): self.name = name self.workloads = set() # This variable is used to assert on destruction that this object was # cleaned up. If not used as a context manager, users of this object self._cleaned = False log_and_run("docker rm -f %s || true" % self.name) log_and_run("docker run --privileged -tid" "-v `pwd`/docker:/usr/local/bin/docker " "-v %s:/code --name %s " "calico/dind:libnetwork --cluster-store=etcd://%s:2379" % (os.getcwd(), self.name, utils.get_ip())) self.ip = log_and_run("docker inspect --format " "'{{ .NetworkSettings.IPAddress }}' %s" % self.name) # Make sure docker is up docker_ps = partial(self.execute, "docker ps") retry_until_success(docker_ps, ex_class=CalledProcessError, retries=10) self.execute("gunzip -c /code/calico-node.tgz | docker load") self.execute("gunzip -c /code/busybox.tgz | docker load") self.execute("gunzip -c /code/calico-node-libnetwork.tgz | docker load") self.start_calico_node()
def __init__(self, name, start_calico=True, dind=True): self.name = name self.dind = dind self.workloads = set() # This variable is used to assert on destruction that this object was # cleaned up. If not used as a context manager, users of this object self._cleaned = False if dind: # TODO use pydocker docker.rm("-f", self.name, _ok_code=[0, 1]) docker.run("--privileged", "-v", os.getcwd()+":/code", "--name", self.name, "-tid", "calico/dind") self.ip = docker.inspect("--format", "{{ .NetworkSettings.IPAddress }}", self.name).stdout.rstrip() self.ip6 = docker.inspect("--format", "{{ .NetworkSettings." "GlobalIPv6Address }}", self.name).stdout.rstrip() # Make sure docker is up docker_ps = partial(self.execute, "docker ps") retry_until_success(docker_ps, ex_class=CalledProcessError, retries=100) self.execute("docker load --input /code/calico_containers/calico-node.tar && " "docker load --input /code/calico_containers/busybox.tar") else: self.ip = get_ip() if start_calico: self.start_calico_node()
def setUp(self): """ Clean up before every test. """ self.ip = get_ip() # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. subprocess.check_output("curl -sL http://%s:2379/v2/keys/calico?recursive=true -XDELETE" % self.ip, shell=True)
def setUp(self): """ Clean up before every test. """ self.ip = get_ip() # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. subprocess.check_output( "curl -sL http://%s:2379/v2/keys/calico?recursive=true -XDELETE" % self.ip, shell=True)
def setUpClass(cls): wipe_etcd(get_ip()) # Rough idea for setup # # Network1 Network2 # # container1 container2 # foo = bar baz = bop # # container3 container4 # foo = bing foo = bar cls.hosts = [] cls.host1 = DockerHost( "host1", additional_docker_options=ADDITIONAL_DOCKER_OPTIONS, post_docker_commands=POST_DOCKER_COMMANDS, start_calico=False, networking=NETWORKING_LIBNETWORK) cls.host1_hostname = cls.host1.execute("hostname") cls.hosts.append(cls.host1) cls.host2 = DockerHost( "host2", additional_docker_options=ADDITIONAL_DOCKER_OPTIONS, post_docker_commands=POST_DOCKER_COMMANDS, start_calico=False, networking=NETWORKING_LIBNETWORK) cls.host2_hostname = cls.host1.execute("hostname") cls.hosts.append(cls.host2) for host in cls.hosts: host.start_calico_node( options='--use-docker-networking-container-labels') cls.network1 = cls.host1.create_network("network1") cls.network2 = cls.host1.create_network("network2") cls.workload1_nw1_foo_bar = cls.host1.create_workload( "workload1", network=cls.network1, labels=["org.projectcalico.label.foo=bar"]) cls.workload2_nw2_baz_bop = cls.host1.create_workload( "workload2", network=cls.network2, labels=["org.projectcalico.label.baz=bop"]) cls.workload3_nw1_foo_bing = cls.host2.create_workload( "workload3", network=cls.network1, labels=["org.projectcalico.label.foo=bing"]) cls.workload4_nw2_foo_bar = cls.host2.create_workload( "workload4", network=cls.network2, labels=["org.projectcalico.label.foo=bar"])
def test_empty_datastore(cmd): """ Test dry-run and start when the etcdv2 datastore is empty. """ wipe_etcdv2(get_ip()) dump_etcdv2() rcu = calicoupgrade(cmd) logger.debug( "INFO: empty etcdv2 datastore: Expecting a non-zero" + "return code for calico-upgrade %s.", cmd) rcu.assert_error()
def setUp(self): """ Clean up before every test. """ self.ip = get_ip() # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. subprocess.check_output( "curl -sL http://%s:2379/v2/keys/calico?recursive=true -XDELETE" % self.ip, shell=True) # Log a newline to ensure that the first log appears on its own line. logger.info("")
def setUpClass(cls): wipe_etcd(get_ip()) # Rough idea for setup # # Network1 Network2 # # container1 container2 # foo = bar baz = bop # # container3 container4 # foo = bing foo = bar cls.hosts = [] cls.host1 = DockerHost( "host1", additional_docker_options=ADDITIONAL_DOCKER_OPTIONS, post_docker_commands=POST_DOCKER_COMMANDS, start_calico=False, networking=NETWORKING_LIBNETWORK) cls.host1_hostname = cls.host1.execute("hostname") cls.hosts.append(cls.host1) cls.host2 = DockerHost( "host2", additional_docker_options=ADDITIONAL_DOCKER_OPTIONS, post_docker_commands=POST_DOCKER_COMMANDS, start_calico=False, networking=NETWORKING_LIBNETWORK) cls.host2_hostname = cls.host1.execute("hostname") cls.hosts.append(cls.host2) for host in cls.hosts: host.start_calico_node(options='--use-docker-networking-container-labels') cls.network1 = cls.host1.create_network("network1") cls.network2 = cls.host1.create_network("network2") cls.workload1_nw1_foo_bar = cls.host1.create_workload( "workload1", network=cls.network1, labels=["org.projectcalico.label.foo=bar"]) cls.workload2_nw2_baz_bop = cls.host1.create_workload( "workload2", network=cls.network2, labels=["org.projectcalico.label.baz=bop"]) cls.workload3_nw1_foo_bing = cls.host2.create_workload( "workload3", network=cls.network1, labels=["org.projectcalico.label.foo=bing"]) cls.workload4_nw2_foo_bar = cls.host2.create_workload( "workload4", network=cls.network2, labels=["org.projectcalico.label.foo=bar"])
def setUp(self): """ Clean up before every test. """ self.ip = get_ip() # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. subprocess.check_output( "curl -sL http://%s:2379/v2/keys/calico?recursive=true -XDELETE" % self.ip, shell=True) # Log a newline to ensure that the first log appears on its own line. logger.info("")
def calicoctl(self, command): """ Convenience function for abstracting away calling the calicoctl command. Raises a CommandExecError() if the command returns a non-zero return code. :param command: The calicoctl command line parms as a single string. :return: The output from the command with leading and trailing whitespace removed. """ command = "/code/calicoctl " + command etcd_auth = "ETCD_AUTHORITY=%s:2379" % get_ip() # Export the environment, in case the command has multiple parts, e.g. # use of | or ; command = "export %s; %s" % (etcd_auth, command) return self.execute(command)
def calicoctl(self, command): """ Convenience function for abstracting away calling the calicoctl command. Raises a CommandExecError() if the command returns a non-zero return code. :param command: The calicoctl command line parms as a single string. :return: The output from the command with leading and trailing whitespace removed. """ command = "/code/calicoctl " + command etcd_auth = "ETCD_AUTHORITY=%s:2379" % get_ip() # Export the environment, in case the command has multiple parts, e.g. # use of | or ; command = "export %s; %s" % (etcd_auth, command) return self.execute(command)
def setUp(self): """ Clean up before every test. """ self.ip = get_ip() # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. if ETCD_SCHEME == "https": # Etcd is running with SSL/TLS, require key/certificates subprocess.check_output( "curl --cacert %s --cert %s --key %s " "-sL https://%s:2379/v2/keys/calico?recursive=true -XDELETE" % (ETCD_CA, ETCD_CERT, ETCD_KEY, self.ip), shell=True) else: subprocess.check_output( "curl -sL http://%s:2379/v2/keys/calico?recursive=true -XDELETE" % self.ip, shell=True) # Log a newline to ensure that the first log appears on its own line. logger.info("")
def setUp(self): """ Clean up before every test. """ self.ip = get_ip() # Delete /calico if it exists. This ensures each test has an empty data # store at start of day. if ETCD_SCHEME == "https": # Etcd is running with SSL/TLS, require key/certificates subprocess.check_output( "curl --cacert %s --cert %s --key %s " "-sL https://%s:2379/v2/keys/calico?recursive=true -XDELETE" % (ETCD_CA, ETCD_CERT, ETCD_KEY, self.ip), shell=True) else: subprocess.check_output( "curl -sL http://%s:2379/v2/keys/calico?recursive=true -XDELETE" % self.ip, shell=True) # Log a newline to ensure that the first log appears on its own line. logger.info("")
# 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. import os import subprocess from unittest import TestCase from tests.st.utils.utils import (get_ip, ETCD_SCHEME, ETCD_CA, ETCD_CERT, ETCD_KEY, debug_failures) import logging HOST_IPV6 = get_ip(v6=True) logging.basicConfig(level=logging.DEBUG, format="%(message)s") logger = logging.getLogger(__name__) # Disable spammy logging from the sh module sh_logger = logging.getLogger("sh") sh_logger.setLevel(level=logging.CRITICAL) class TestBase(TestCase): """ Base class for test-wide methods. """ def setUp(self): """
# 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. import json import subprocess from unittest import TestCase from tests.st.utils.utils import (get_ip, ETCD_SCHEME, ETCD_CA, ETCD_CERT, ETCD_KEY, debug_failures, ETCD_HOSTNAME_SSL) import logging HOST_IPV6 = get_ip(v6=True) HOST_IPV4 = get_ip() logging.basicConfig(level=logging.DEBUG, format="%(message)s") logger = logging.getLogger(__name__) # Disable spammy logging from the sh module sh_logger = logging.getLogger("sh") sh_logger.setLevel(level=logging.CRITICAL) class TestBase(TestCase): """ Base class for test-wide methods. """ def setUp(self):
# 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. import logging from unittest import TestCase from tests.st.utils.utils import (get_ip, wipe_etcd, calicoctl) HOST_IPV4 = get_ip() logging.basicConfig(level=logging.DEBUG, format="%(message)s") logger = logging.getLogger(__name__) class TestBase(TestCase): """ Base class for test-wide methods. """ def setUp(self): """ Clean up before every test. """ self.ip = HOST_IPV4
logger = logging.getLogger(__name__) POST_DOCKER_COMMANDS = ["docker load -i /code/calico-node.tgz", "docker load -i /code/busybox.tgz", "docker load -i /code/calico-node-libnetwork.tgz"] if ETCD_SCHEME == "https": ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " \ "--cluster-store-opt kv.cacertfile=%s " \ "--cluster-store-opt kv.certfile=%s " \ "--cluster-store-opt kv.keyfile=%s " % \ (ETCD_HOSTNAME_SSL, ETCD_CA, ETCD_CERT, ETCD_KEY) else: ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " % \ utils.get_ip() class TestMainline(TestBase): def test_mainline(self): """ Setup two endpoints on one host and check connectivity then teardown. """ # TODO - add in IPv6 as part of this flow. with DockerHost('host', additional_docker_options=ADDITIONAL_DOCKER_OPTIONS, post_docker_commands=POST_DOCKER_COMMANDS, start_calico=False) as host: host.start_calico_node("--libnetwork") # Set up two endpoints on one host network = host.create_network("testnet")
# # 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. import logging from unittest import TestCase from tests.st.utils.utils import (get_ip, wipe_etcdv2, wipe_etcdv3, set_version_etcdv2, set_ready_etcdv2, get_value_etcdv2) HOST_IPV4 = get_ip() logging.basicConfig(level=logging.DEBUG, format="%(message)s") logger = logging.getLogger(__name__) class TestBase(TestCase): """ Base class for test-wide methods. """ def setUp(self): """ Clean up before every test. """ self.ip = HOST_IPV4 self.wipe_etcdv2()
# 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. import json import yaml import logging import subprocess from pprint import pformat from unittest import TestCase from deepdiff import DeepDiff from tests.st.utils.utils import (get_ip, ETCD_SCHEME, ETCD_CA, ETCD_CERT, ETCD_KEY, debug_failures, ETCD_HOSTNAME_SSL) HOST_IPV6 = get_ip(v6=True) HOST_IPV4 = get_ip() logging.basicConfig(level=logging.DEBUG, format="%(message)s") logger = logging.getLogger(__name__) # Disable spammy logging from the sh module sh_logger = logging.getLogger("sh") sh_logger.setLevel(level=logging.CRITICAL) class TestBase(TestCase): """ Base class for test-wide methods. """ def setUp(self):
# 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. import subprocess from unittest import TestCase from tests.st.utils.utils import get_ip import logging HOST_IPV6 = get_ip(v6=True) logging.basicConfig(level=logging.DEBUG, format="%(message)s") logger = logging.getLogger(__name__) # Disable spammy logging from the sh module sh_logger = logging.getLogger("sh") sh_logger.setLevel(level=logging.CRITICAL) class TestBase(TestCase): """ Base class for test-wide methods. """ def setUp(self): """
POST_DOCKER_COMMANDS = [ "docker load -i /code/calico-node.tgz", "docker load -i /code/busybox.tgz", "docker load -i /code/calico-node-libnetwork.tgz" ] if ETCD_SCHEME == "https": ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " \ "--cluster-store-opt kv.cacertfile=%s " \ "--cluster-store-opt kv.certfile=%s " \ "--cluster-store-opt kv.keyfile=%s " % \ (ETCD_HOSTNAME_SSL, ETCD_CA, ETCD_CERT, ETCD_KEY) else: ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " % \ utils.get_ip() class TestMainline(TestBase): def test_mainline(self): """ Setup two endpoints on one host and check connectivity then teardown. """ # TODO - add in IPv6 as part of this flow. with DockerHost('host', additional_docker_options=ADDITIONAL_DOCKER_OPTIONS, post_docker_commands=POST_DOCKER_COMMANDS, start_calico=False) as host: host.start_calico_node("--libnetwork") # Set up two endpoints on one host
POST_DOCKER_COMMANDS = [ "docker load -i /code/calico-node.tar", "docker load -i /code/busybox.tar", "docker load -i /code/workload.tar", ] if ETCD_SCHEME == "https": ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " \ "--cluster-store-opt kv.cacertfile=%s " \ "--cluster-store-opt kv.certfile=%s " \ "--cluster-store-opt kv.keyfile=%s " % \ (ETCD_HOSTNAME_SSL, ETCD_CA, ETCD_CERT, ETCD_KEY) else: ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " % \ get_ip() class TestLibnetworkLabeling(TestBase): """ Tests that labeling is correctly implemented in libnetwork. Setup multiple networks and then run containers with labels and see that policy will allow and block traffic. """ hosts = None host = None @classmethod def setUpClass(cls): wipe_etcd(get_ip())
ETCD_CERT, ETCD_KEY, ETCD_HOSTNAME_SSL, ETCD_SCHEME, get_ip, check_bird_status, ) if ETCD_SCHEME == "https": ADDITIONAL_DOCKER_OPTIONS = ( "--cluster-store=etcd://%s:2379 " "--cluster-store-opt kv.cacertfile=%s " "--cluster-store-opt kv.certfile=%s " "--cluster-store-opt kv.keyfile=%s " % (ETCD_HOSTNAME_SSL, ETCD_CA, ETCD_CERT, ETCD_KEY) ) else: ADDITIONAL_DOCKER_OPTIONS = "--cluster-store=etcd://%s:2379 " % get_ip() def create_bgp_peer(host, scope, ip, asNum): assert scope in ("node", "global") node = host.get_hostname() if scope == "node" else "" testdata = { "apiVersion": "v1", "kind": "bgpPeer", "metadata": {"scope": scope, "node": node, "peerIP": ip}, "spec": {"asNumber": asNum}, } host.writefile("testfile.yaml", testdata) host.calicoctl("create -f testfile.yaml")