diff --git a/tools/test-cloud-meta-mock.py b/tools/test-cloud-meta-mock.py index 262dc2ffb3..5c4fcad4a7 100755 --- a/tools/test-cloud-meta-mock.py +++ b/tools/test-cloud-meta-mock.py @@ -1,13 +1,23 @@ #!/usr/bin/env python +# A service that mocks up various metadata providers. Used for testing, +# can also be used standalone as a development aid. +# +# To run standalone: +# # run: $ systemd-socket-activate -l 8000 python tools/test-cloud-meta-mock.py & # $ NM_CLOUD_SETUP_EC2_HOST=http://localhost:8000 \ # NM_CLOUD_SETUP_LOG=trace \ # NM_CLOUD_SETUP_EC2=yes src/nm-cloud-setup/nm-cloud-setup # or just: $ python tools/test-cloud-meta-mock.py +# +# By default, the utility will server some resources for each known cloud +# providers, for convenience. The tests start this with "--empty" argument, +# which starts with no resources. import os import socket +from sys import argv from http.server import HTTPServer from http.server import BaseHTTPRequestHandler @@ -20,35 +30,39 @@ class MockCloudMDRequestHandler(BaseHTTPRequestHandler): Currently implements a fairly minimal subset of AWS EC2 API. """ - _ec2_macs = "/2018-09-24/meta-data/network/interfaces/macs/" - _meta_resources = { - "/latest/meta-data/": b"ami-id\n", - _ec2_macs: b"9e:c0:3e:92:24:2d\n53:e9:7e:52:8d:a8", - _ec2_macs + "9e:c0:3e:92:24:2d/subnet-ipv4-cidr-block": b"172.31.16.0/20", - _ec2_macs + "9e:c0:3e:92:24:2d/local-ipv4s": b"172.31.26.249", - _ec2_macs + "53:e9:7e:52:8d:a8/subnet-ipv4-cidr-block": b"172.31.166.0/20", - _ec2_macs + "53:e9:7e:52:8d:a8/local-ipv4s": b"172.31.176.249", - } - def log_message(self, format, *args): pass def do_GET(self): - if self.path in self._meta_resources: + path = self.path.encode("ascii") + if path in self.server._resources: self.send_response(200) self.end_headers() - self.wfile.write(self._meta_resources[self.path]) + self.wfile.write(self.server._resources[path]) else: self.send_response(404) self.end_headers() def do_PUT(self): - if self.path == "/latest/api/token": + path = self.path.encode("ascii") + if path == b"/latest/api/token": self.send_response(200) self.end_headers() self.wfile.write( b"AQAAALH-k7i18JMkK-ORLZQfAa7nkNjQbKwpQPExNHqzk1oL_7eh-A==" ) + else: + length = int(self.headers["content-length"]) + self.server._resources[path] = self.rfile.read(length) + self.send_response(201) + self.end_headers() + + def do_DELETE(self): + path = self.path.encode("ascii") + if path in self.server._resources: + del self.server._resources[path] + self.send_response(204) + self.end_headers() else: self.send_response(404) self.end_headers() @@ -61,12 +75,41 @@ class SocketHTTPServer(HTTPServer): fron the test runner. """ - def __init__(self, server_address, RequestHandlerClass, socket): + def __init__(self, server_address, RequestHandlerClass, socket, resources): BaseServer.__init__(self, server_address, RequestHandlerClass) self.socket = socket self.server_address = self.socket.getsockname() + self._resources = resources +def default_resources(): + ec2_macs = b"/2018-09-24/meta-data/network/interfaces/macs/" + + mac1 = b"9e:c0:3e:92:24:2d" + mac2 = b"53:e9:7e:52:8d:a8" + + ip1 = b"172.31.26.249" + ip2 = b"172.31.176.249" + + return { + b"/latest/meta-data/": b"ami-id\n", + ec2_macs: mac2 + b"\n" + mac1, + ec2_macs + mac2 + b"/subnet-ipv4-cidr-block": b"172.31.16.0/20", + ec2_macs + mac2 + b"/local-ipv4s": ip1, + ec2_macs + mac1 + b"/subnet-ipv4-cidr-block": b"172.31.166.0/20", + ec2_macs + mac1 + b"/local-ipv4s": ip2, + } + + +resources = None +try: + if argv[1] == "--empty": + resources = {} +except IndexError: + pass +if resources is None: + resources = default_resources() + # See sd_listen_fds(3) fileno = os.getenv("LISTEN_FDS") if fileno is not None: @@ -80,8 +123,7 @@ else: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) s.bind(addr) - -httpd = SocketHTTPServer(None, MockCloudMDRequestHandler, socket=s) +httpd = SocketHTTPServer(None, MockCloudMDRequestHandler, socket=s, resources=resources) print("Listening on http://%s:%d" % (httpd.server_address[0], httpd.server_address[1])) httpd.server_activate()