def test_on_can_run_on_success(): def _capture_value(x): global on_success_value on_success_value = x + 1 E.success(1) | E.on | dict(success=_capture_value) assert on_success_value == 2
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args["file_system"] project_id = "project1" service_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" image_url = "test-service:1.0.0" app_port = 3000 service_port = 80 service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[micro_service(service_name, image_url, app_port)]) yamls = find_write_template_calls(fs) assert yamls[0]['kind'] == 'Service' assert yamls[0]['metadata']['name'] == service_name assert yamls[0]['spec']['selector']['app'] == service_name + '-app' assert yamls[0]['spec']['ports'][0]['targetPort'] == app_port assert yamls[0]['spec']['ports'][0]['port'] == service_port assert yamls[1]['kind'] == 'Deployment'
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args["file_system"] project_id = "project1" app_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode(json.dumps({'key': 'someKey'}).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ deployment(app_name) .with_rolling_update(max_surge='20%', max_unavailable='20%') .with_volume_claim(name='test-volume', claim_name='some-claim-name') .with_container(container('test', 'test:100') .with_volume_mount('test-volume', '/var/data/my-data') .with_environment_from_context('ENV', lambda c: c('cluster_name'))) ] ) deployment_yaml = find_write_template_calls(fs)[0] assert deployment_yaml['spec']['template']['spec']['containers'][0]['env'][1]['name'] == 'ENV' assert deployment_yaml['spec']['template']['spec']['containers'][0]['env'][1]['value'] == cluster_name
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args["file_system"] app_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" container_1 = container(name='myservice', image='busybox:1.0') container_2 = container(name='myservice-2', image='busybox:2.0') os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = gen_template([ deployment(app_name) .with_containers([container_1, container_2]) ]) deployment_yaml = find_write_template_calls(fs)[0] containers = deployment_yaml['spec']['template']['spec']['containers'] assert containers[0]['name'] == 'myservice-app' assert containers[0]['image'] == 'busybox:1.0' assert containers[1]['name'] == 'myservice-2-app' assert containers[1]['image'] == 'busybox:2.0'
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args["file_system"] project_id = "project1" app_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode(json.dumps({'key': 'someKey'}).encode('utf-8')) container_1 = container(name='myservice', image='busybox:1.0') container_2 = container(name='myservice-2', image='busybox:2.0') os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ deployment(app_name) .with_containers([container_1, container_2]) ] ) deployment_yaml = find_write_template_calls(fs)[0] containers = deployment_yaml['spec']['template']['spec']['containers'] assert containers[0]['name'] == 'myservice-app' assert containers[0]['image'] == 'busybox:1.0' assert containers[1]['name'] == 'myservice-2-app' assert containers[1]['image'] == 'busybox:2.0'
def _run_dsl(args): os: MockOsSystem = args["os_system"] project_id = "project1" cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl(cluster_name, 'get mappings', E.failure('No such resource')) os.mock_kubectl(cluster_name, 'get virtualservices', E.failure('No such resource')) with patch.object(sys, "exit") as mock_exit: _, error = run_in_cluster(conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ gateway_mapping( 'api', 'api.com', 'api.default.svc.cluster.local') ]) assert mock_exit.call_args[0][0] == 1 assert str(error.caught_error) == 'Unsupported gateway'
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args["file_system"] project_id = "project1" app_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode(json.dumps({'key': 'someKey'}).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ deployment(app_name) .with_rolling_update(max_surge='20%', max_unavailable='20%') .with_empty_volume(name='test-volume') .with_container(container('test', 'test:100')) .with_container(container('test-2', 'test-2:100')) ] ) deployment_yaml = find_write_template_calls(fs)[0] assert deployment_yaml['spec']['strategy'] == {'rollingUpdate': {'maxSurge': '20%', 'maxUnavailable': '20%'}, 'type': 'RollingUpdate'}
def test_on_can_run_whatever_on_success(): def _capture_value(value, _): global on_whatever_value on_whatever_value = value + 1 E.success(1) | E.on | dict(whatever=_capture_value) assert on_whatever_value == 2
def _run_dsl(args): fs: MockFileSystem = args['file_system'] os: MockOsSystem = args["os_system"] project_id = "project1" secret_name = 'test-secret' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode(json.dumps({'key': 'someKey'}).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ secret(secret_name, data={'key1': 'someValue'}) ] ) yamls = find_write_template_calls(fs) assert yamls[0]['kind'] == 'Secret' assert yamls[0]['metadata']['name'] == secret_name assert b64decode(yamls[0]['data']['key1'].encode('utf-8')).decode('utf-8') == 'someValue'
def _run_dsl(args): fs: MockFileSystem = args['file_system'] os: MockOsSystem = args["os_system"] project_id = "project1" job_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" image_url = "test-service:1.0.0" service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ cron_job(job_name, image_url).with_environment_secret( 'coolSecret', {'ENV_NAME': 'secretkey'}) ]) yamls = find_write_template_calls(fs) container = yamls[0]['spec']['jobTemplate']['spec']['template'][ 'spec']['containers'][0] assert container['env'][0]['name'] == 'ENV_NAME' assert container['env'][0]['valueFrom']['secretKeyRef'][ 'name'] == 'coolSecret' assert container['env'][0]['valueFrom']['secretKeyRef'][ 'key'] == 'secretkey'
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args['file_system'] project_id = "project1" job_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" image_url = "test-service:1.0.0" service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster(conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[cron_job(job_name, image_url)]) yamls = find_write_template_calls(fs) assert yamls[0]['kind'] == 'CronJob' assert yamls[0]['metadata']['name'] == job_name container = yamls[0]['spec']['jobTemplate']['spec']['template'][ 'spec']['containers'][0] assert container['name'] == job_name assert container['image'] == image_url
def mock_clusters_list(self, cluster_names: List[str]): for cluster_name in cluster_names: self.mock_create_kube_config(cluster_name, return_value=E.success()) self.mock_kubectl_apply_temp_file(cluster_name, return_value=E.success()) cmd = '{cwd}/{cache_dir_name}/google-cloud-sdk/bin/gcloud container clusters list --format=\"value(name)\"' \ .format(cache_dir_name=Config.cache_folder_name(), cwd=MockFileSystem.cwd()) PyMock.mock(self.os_system.run, args=[cmd, MatchArg.any()], return_values=[E.success('\n'.join(cluster_names))])
def os_run(command, log: Logger): log.debug("OS_RUN: {}".format(command)) process = Popen(command, stdout=PIPE, stderr=PIPE, shell=True) output = [] for line in iter(process.stdout.readline, 'b'): if line == b'': break line = line.rstrip().decode("utf-8") log.debug(line) output.append(line) for line in iter(process.stderr.readline, 'b'): if line == b'': break line = line.rstrip().decode("utf-8") log.error("OS_RUN: {}".format(line)) process.communicate() if process.returncode != 0: return E.failure("ErrorCode: " + str(process.returncode)) return E.success('\n'.join(output))
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args['file_system'] project_id = "project1" cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl(cluster_name, 'get mappings', E.failure('No such resource')) os.mock_kubectl(cluster_name, 'get virtualservices', E.success()) _, result = run_in_cluster(conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ gateway_mapping( 'api', 'api.com', 'api.default.svc.cluster.local') ]) yamls = find_write_template_calls(fs) output_yaml = yamls[0] assert output_yaml == { 'apiVersion': 'networking.istio.io/v1alpha3', 'kind': 'VirtualService', 'metadata': { 'name': 'api-vs' }, 'spec': { 'hosts': ['api.com'], 'gateways': ['cluster-gateway'], 'http': [{ 'route': [{ 'destination': { 'host': 'api.default.svc.cluster.local' } }] }] } }
def _write_template_plan(cluster_name, conf, file_path, template: str, cur_ctx: TemplateContext): template_outs = _gen_template(template, cluster_name, conf, cur_ctx) templates_out = y.load_all(conf.fs.read(file_path)) if conf.fs.exists(file_path) else [] templates_out = templates_out + template_outs conf.fs.write(file_path, y.combine_templates(templates_out)) return E.success(cur_ctx)
def _exec_template(self, action, templates: List[dict], cluster_name: str): if len(templates) is 0: return E.success() return self._file.with_temp_file( contents=yaml.combine_templates(templates), filename='template.yaml', runner=lambda temp_file: self._k8s_provider.kubectl( action + ' -f {}'.format(temp_file), cluster_name))
def chain_func(remaining_items: List[Any], resulting_items: List[Any]) -> Either[Any, Any]: if len(remaining_items) == 0: return E.success(resulting_items) item = remaining_items[0] new_remaining_items = remaining_items[1:] return E.try_catch(lambda: processor(item)) \ | E.then | (lambda result: chain_func(new_remaining_items, resulting_items+[result]))
def chain_func(remaining_items: List[Any], last_result: Optional[Any]) -> E.Either: if len(remaining_items) == 0: return E.success(last_result) item = remaining_items[0] remaining_items = remaining_items[1:] return E.try_catch(lambda: action(item, last_result)) \ | E.then | (lambda next_result: chain_func(remaining_items, next_result))
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args['file_system'] project_id = "project1" claim_name = 'test-volume' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[volume_claim(claim_name).with_size('5Gi')]) yamls = find_write_template_calls(fs) assert yamls[0] == { 'apiVersion': 'v1', 'kind': 'PersistentVolumeClaim', 'metadata': { 'name': 'test-volume' }, 'spec': { 'accessModes': ['ReadWriteOnce'], 'resources': { 'requests': { 'storage': '5Gi' } }, 'volumeMode': 'Filesystem' } }
def _install_kubectl(self): if self._file.exists( "{cache_dir}/kubectl".format(cache_dir=self._cache_dir)): return E.success() cur_os = 'darwin' if self._is_macos() else 'linux' self._log.info("INSTALLING DEPENDENCY: Installing kubectl...") self._run("curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt") \ | E.then | (lambda kube_version: self._run("curl -L https://storage.googleapis.com/kubernetes-release/release" "/{kube_version}/bin/{os}/amd64/kubectl > {cache_dir}/kubectl " "&& chmod u+x {cache_dir}/kubectl" .format(os=cur_os, kube_version=kube_version, cache_dir=self._cache_dir)))
def _run_dsl(args): fs: MockFileSystem = args['file_system'] os: MockOsSystem = args["os_system"] project_id = "project1" cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode( json.dumps({ 'key': 'someKey' }).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl(cluster_name, 'get mappings', E.success()) os.mock_kubectl(cluster_name, 'get virtualservices', E.failure('No such resource')) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ gateway_mapping('api', '*', 'api.default.svc.cluster.local') ]) yamls = find_write_template_calls(fs) output_yaml = yamls[0] assert output_yaml == { 'apiVersion': 'getambassador.io/v1', 'kind': 'Mapping', 'metadata': { 'name': 'api-mapping' }, 'spec': { 'prefix': '/', 'service': 'api.default.svc.cluster.local' } }
def _run_dsl(args): os: MockOsSystem = args["os_system"] fs: MockFileSystem = args["file_system"] project_id = "project1" app_name = 'test-service' cluster_name = 'prod-us-east1' kubectl_version = "v1.15.3" service_account_b64 = b64encode(json.dumps({'key': 'someKey'}).encode('utf-8')) os.mock_clusters_list([cluster_name]) os.mock_kubernetes_release(E.success(kubectl_version)) os.mock_download_install_kubectl(kubectl_version, E.success()) os.mock_create_kube_config(cluster_name, E.success()) os.mock_kubectl_apply_temp_file(cluster_name, E.success()) _, result = run_in_cluster( conn=gke_conn(cluster_name, project_id, service_account_b64), templates=[ deployment(app_name) .with_empty_volume(name='test-volume') .with_container(container('test', 'test:100')) .with_container(container('test-2', 'test-2:100')) ] ) deployment_yaml = find_write_template_calls(fs)[0] assert deployment_yaml['kind'] == 'Deployment' assert deployment_yaml['metadata']['name'] == app_name+'-dp' assert deployment_yaml['spec']['selector']['matchLabels']['app'] == app_name+'-app' assert deployment_yaml['spec']['template']['spec']['volumes'][0]['name'] == 'test-volume' container1 = deployment_yaml['spec']['template']['spec']['containers'][0] container2 = deployment_yaml['spec']['template']['spec']['containers'][1] assert container1['name'] == 'test-app' assert container1['image'] == 'test:100' assert container2['name'] == 'test-2-app' assert container2['image'] == 'test-2:100'
def _install_google_cloud_sdk(self): if self._file.exists("{cache_dir}/google-cloud-sdk".format( cache_dir=self._cache_dir)): return E.success() self._log.info("INSTALLING DEPENDENCY: Installing google-cloud-sdk...") cur_os = 'darwin' if self._is_macos() else 'linux' gcloud_version = self._conf.get_arg('KG_GCLOUD_VERSION', default='284.0.0') google_sdk_url = ( "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/" "google-cloud-sdk-{gcloud_version}-{os}-x86_64.tar.gz".format( os=cur_os, gcloud_version=gcloud_version)) return self._run("cd {cache_dir} && curl -L {url} | tar zx".format( cache_dir=self._cache_dir, url=google_sdk_url))
def _gen_kubeconfig(self, cluster_name: str): if self._is_kubeconfig_valid(cluster_name): return E.success() kubeconfig_file = self._kubeconfig_file_path(cluster_name) self._log.info("\n\n==========KUBECONFIG SETUP==========") return self._configure_auth() \ | E.then | (lambda _: self._run('{scripts_dir}/create-kube-config.sh {cluster_name} ' '{cache_dir} {key_file} "{kubeconfig_file}" {project}' .format(scripts_dir=self._scripts_dir, cluster_name=cluster_name, cache_dir=self._cache_dir, kubeconfig_file=kubeconfig_file, key_file=self._service_account_file, project=self._project_id))) \ | E.on | (dict(whatever=lambda _x, _y: self._log.info("\n==========KUBECONFIG SETUP END==========\n")))
def __init__(self): os_system = Mock(spec=OS) os_system.is_macos = Mock(name='os_system.is_macos', return_value=True) os_system.run = Mock(name='os_system.run', return_value=E.success()) os_system.get_env = Mock(name='os_system.get_env', return_value=None) self.os_system = os_system self.mock_gcloud_download(E.success()) self.mock_kubernetes_release(return_value=E.success("1.16")) self.mock_download_install_kubectl("1.16", return_value=E.success()) self.mock_clusters_list(['prod-us-east1']) self.mock_set_project_id('project1', return_values=[E.success()]) self.mock_activate_service_account('service_account.json', return_values=[E.success()])
def test_can_catch_error_and_return_success(): assert E.failure("someError") | E.catch_error | ( lambda x: E.success(1)) == E.success(1)
def test_can_catch_error_and_default_non_either_result_to_success(): assert E.failure("someError") | E.catch_error | ( lambda _: 1) == E.success(1)
def test_from_either_can_return_on_success(): assert E.success(1) \ | E.from_either | dict( if_success=lambda x: x + 1, if_failure=lambda _: "shouldSucceed") == 2
def test_can_make_empty_success_either(): assert E.success() == ("success", None)
def get_clusters(self, by_regex: str) -> E.Either[List[str], Any]: return E.success(['host-kubectl'])