Add ingress object
This commit is contained in:
		
							parent
							
								
									15e4c94b8d
								
							
						
					
					
						commit
						4e9151318a
					
				@ -19,6 +19,8 @@ k8s_kind_deploy_type = "k8s-kind"
 | 
			
		||||
k8s_deploy_type = "k8s"
 | 
			
		||||
kube_config_key = "kube-config"
 | 
			
		||||
deploy_to_key = "deploy-to"
 | 
			
		||||
network_key = "network"
 | 
			
		||||
http_proxy_key = "http-proxy"
 | 
			
		||||
image_resigtry_key = "image-registry"
 | 
			
		||||
kind_config_filename = "kind-config.yml"
 | 
			
		||||
kube_config_filename = "kubeconfig.yml"
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ from stack_orchestrator.deploy.k8s.helpers import get_node_pv_mount_path
 | 
			
		||||
from stack_orchestrator.deploy.k8s.helpers import env_var_map_from_file, envs_from_environment_variables_map
 | 
			
		||||
from stack_orchestrator.deploy.deploy_util import parsed_pod_files_map_from_file_names, images_for_deployment
 | 
			
		||||
from stack_orchestrator.deploy.deploy_types import DeployEnvVars
 | 
			
		||||
from stack_orchestrator.deploy.spec import Spec
 | 
			
		||||
from stack_orchestrator.deploy.images import remote_tag_for_image
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -31,20 +32,74 @@ class ClusterInfo:
 | 
			
		||||
    app_name: str = "test-app"
 | 
			
		||||
    deployment_name: str = "test-deployment"
 | 
			
		||||
    environment_variables: DeployEnvVars
 | 
			
		||||
    remote_image_repo: str
 | 
			
		||||
    spec: Spec
 | 
			
		||||
 | 
			
		||||
    def __init__(self) -> None:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def int(self, pod_files: List[str], compose_env_file, remote_image_repo):
 | 
			
		||||
    def int(self, pod_files: List[str], compose_env_file, spec: Spec):
 | 
			
		||||
        self.parsed_pod_yaml_map = parsed_pod_files_map_from_file_names(pod_files)
 | 
			
		||||
        # Find the set of images in the pods
 | 
			
		||||
        self.image_set = images_for_deployment(pod_files)
 | 
			
		||||
        self.environment_variables = DeployEnvVars(env_var_map_from_file(compose_env_file))
 | 
			
		||||
        self.remote_image_repo = remote_image_repo
 | 
			
		||||
        self.spec = spec
 | 
			
		||||
        if (opts.o.debug):
 | 
			
		||||
            print(f"Env vars: {self.environment_variables.map}")
 | 
			
		||||
 | 
			
		||||
    def get_ingress(self):
 | 
			
		||||
        # No ingress for a deployment that has no http-proxy defined, for now
 | 
			
		||||
        http_proxy_info = self.spec.get_http_proxy()
 | 
			
		||||
        ingress = None
 | 
			
		||||
        if http_proxy_info:
 | 
			
		||||
            if opts.o.debug:
 | 
			
		||||
                print(f"http-proxy: {http_proxy_info}")
 | 
			
		||||
            # TODO: good enough parsing for webapp deployment for now
 | 
			
		||||
            host_name = http_proxy_info["host-name"]
 | 
			
		||||
            rules = []
 | 
			
		||||
            tls = [client.V1IngressTLS(
 | 
			
		||||
                hosts=[host_name],
 | 
			
		||||
                secret_name=f"{self.app_name}-tls"
 | 
			
		||||
            )]
 | 
			
		||||
            paths = []
 | 
			
		||||
            for route in http_proxy_info["routes"]:
 | 
			
		||||
                path = route["path"]
 | 
			
		||||
                proxy_to = route["proxy-to"]
 | 
			
		||||
                if opts.o.debug:
 | 
			
		||||
                    print(f"proxy config: {path} -> {proxy_to}")
 | 
			
		||||
                paths.append(client.V1HTTPIngressPath(
 | 
			
		||||
                    path_type="Prefix",
 | 
			
		||||
                    path=path,
 | 
			
		||||
                    backend=client.V1IngressBackend(
 | 
			
		||||
                        service=client.V1IngressServiceBackend(
 | 
			
		||||
                            # TODO: this looks wrong
 | 
			
		||||
                            name=self.deployment_name,
 | 
			
		||||
                            # TODO: pull port number from the service
 | 
			
		||||
                            port=client.V1ServiceBackendPort(number=80)
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                ))
 | 
			
		||||
            rules.append(client.V1IngressRule(
 | 
			
		||||
                host=host_name,
 | 
			
		||||
                http=client.V1HTTPIngressRuleValue(
 | 
			
		||||
                    paths=paths
 | 
			
		||||
                )
 | 
			
		||||
            ))
 | 
			
		||||
            spec = client.V1IngressSpec(
 | 
			
		||||
                tls=tls,
 | 
			
		||||
                rules=rules
 | 
			
		||||
            )
 | 
			
		||||
            ingress = client.V1Ingress(
 | 
			
		||||
                metadata=client.V1ObjectMeta(
 | 
			
		||||
                    name=f"{self.app_name}-ingress",
 | 
			
		||||
                    annotations={
 | 
			
		||||
                        "kubernetes.io/ingress.class": "nginx",
 | 
			
		||||
                        "cert-manager.io/cluster-issuer": "letsencrypt-prod"
 | 
			
		||||
                    }
 | 
			
		||||
                ),
 | 
			
		||||
                spec=spec
 | 
			
		||||
            )
 | 
			
		||||
        return ingress
 | 
			
		||||
 | 
			
		||||
    def get_pvcs(self):
 | 
			
		||||
        result = []
 | 
			
		||||
        volumes = named_volumes_from_pod_files(self.parsed_pod_yaml_map)
 | 
			
		||||
@ -96,7 +151,8 @@ class ClusterInfo:
 | 
			
		||||
                service_info = services[service_name]
 | 
			
		||||
                image = service_info["image"]
 | 
			
		||||
                # Re-write the image tag for remote deployment
 | 
			
		||||
                image_to_use = remote_tag_for_image(image, self.remote_image_repo) if self.remote_image_repo is not None else image
 | 
			
		||||
                image_to_use = remote_tag_for_image(
 | 
			
		||||
                    image, self.spec.get_image_registry()) if self.spec.get_image_registry() is not None else image
 | 
			
		||||
                volume_mounts = volume_mounts_for_service(self.parsed_pod_yaml_map, service_name)
 | 
			
		||||
                container = client.V1Container(
 | 
			
		||||
                    name=container_name,
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ class K8sDeployer(Deployer):
 | 
			
		||||
    type: str
 | 
			
		||||
    core_api: client.CoreV1Api
 | 
			
		||||
    apps_api: client.AppsV1Api
 | 
			
		||||
    networking_api: client.NetworkingV1Api
 | 
			
		||||
    k8s_namespace: str = "default"
 | 
			
		||||
    kind_cluster_name: str
 | 
			
		||||
    cluster_info : ClusterInfo
 | 
			
		||||
@ -45,7 +46,7 @@ class K8sDeployer(Deployer):
 | 
			
		||||
        self.deployment_context = deployment_context
 | 
			
		||||
        self.kind_cluster_name = compose_project_name
 | 
			
		||||
        self.cluster_info = ClusterInfo()
 | 
			
		||||
        self.cluster_info.int(compose_files, compose_env_file, deployment_context.spec.obj[constants.image_resigtry_key])
 | 
			
		||||
        self.cluster_info.int(compose_files, compose_env_file, deployment_context.spec)
 | 
			
		||||
        if (opts.o.debug):
 | 
			
		||||
            print(f"Deployment dir: {deployment_context.deployment_dir}")
 | 
			
		||||
            print(f"Compose files: {compose_files}")
 | 
			
		||||
@ -60,9 +61,11 @@ class K8sDeployer(Deployer):
 | 
			
		||||
            # Get the config file and pass to load_kube_config()
 | 
			
		||||
            config.load_kube_config(config_file=self.deployment_dir.joinpath(constants.kube_config_filename).as_posix())
 | 
			
		||||
        self.core_api = client.CoreV1Api()
 | 
			
		||||
        self.networking_api = client.NetworkingV1Api()
 | 
			
		||||
        self.apps_api = client.AppsV1Api()
 | 
			
		||||
 | 
			
		||||
    def up(self, detach, services):
 | 
			
		||||
 | 
			
		||||
        if self.is_kind():
 | 
			
		||||
            # Create the kind cluster
 | 
			
		||||
            create_cluster(self.kind_cluster_name, self.deployment_dir.joinpath(constants.kind_config_filename))
 | 
			
		||||
@ -102,6 +105,17 @@ class K8sDeployer(Deployer):
 | 
			
		||||
            print(f"{deployment_resp.metadata.namespace} {deployment_resp.metadata.name} \
 | 
			
		||||
                  {deployment_resp.metadata.generation} {deployment_resp.spec.template.spec.containers[0].image}")
 | 
			
		||||
 | 
			
		||||
        # TODO: disable ingress for kind
 | 
			
		||||
        ingress: client.V1Ingress = self.cluster_info.get_ingress()
 | 
			
		||||
 | 
			
		||||
        ingress_resp = self.networking_api.create_namespaced_ingress(
 | 
			
		||||
            namespace=self.k8s_namespace,
 | 
			
		||||
            body=ingress
 | 
			
		||||
        )
 | 
			
		||||
        if opts.o.debug:
 | 
			
		||||
            print("Ingress created:")
 | 
			
		||||
            print(f"{ingress_resp}")
 | 
			
		||||
 | 
			
		||||
    def down(self, timeout, volumes):
 | 
			
		||||
        self.connect_api()
 | 
			
		||||
        # Delete the k8s objects
 | 
			
		||||
@ -124,14 +138,21 @@ class K8sDeployer(Deployer):
 | 
			
		||||
            if opts.o.debug:
 | 
			
		||||
                print("PVCs deleted:")
 | 
			
		||||
                print(f"{pvc_resp}")
 | 
			
		||||
        # Process compose files into a Deployment
 | 
			
		||||
        deployment = self.cluster_info.get_deployment()
 | 
			
		||||
        # Create the k8s objects
 | 
			
		||||
        if opts.o.debug:
 | 
			
		||||
            print(f"Deleting this deployment: {deployment}")
 | 
			
		||||
        self.apps_api.delete_namespaced_deployment(
 | 
			
		||||
            name=deployment.metadata.name, namespace=self.k8s_namespace
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # TODO: disable ingress for kind
 | 
			
		||||
        ingress: client.V1Ingress = self.cluster_info.get_ingress()
 | 
			
		||||
        if opts.o.debug:
 | 
			
		||||
            print(f"Deleting this ingress: {ingress}")
 | 
			
		||||
        self.apps_api.delete_namespaced_ingress(
 | 
			
		||||
            name=ingress.metadata.name, namespace=self.k8s_namespace
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if self.is_kind():
 | 
			
		||||
            # Destroy the kind cluster
 | 
			
		||||
            destroy_cluster(self.kind_cluster_name)
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
import typing
 | 
			
		||||
from stack_orchestrator.util import get_yaml
 | 
			
		||||
from stack_orchestrator import constants
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Spec:
 | 
			
		||||
@ -28,3 +29,14 @@ class Spec:
 | 
			
		||||
    def init_from_file(self, file_path: Path):
 | 
			
		||||
        with file_path:
 | 
			
		||||
            self.obj = get_yaml().load(open(file_path, "r"))
 | 
			
		||||
 | 
			
		||||
    def get_image_registry(self):
 | 
			
		||||
        return (self.obj[constants.image_resigtry_key]
 | 
			
		||||
                if self.obj and constants.image_resigtry_key in self.obj
 | 
			
		||||
                else None)
 | 
			
		||||
 | 
			
		||||
    def get_http_proxy(self):
 | 
			
		||||
        return (self.obj[constants.network_key][constants.http_proxy_key]
 | 
			
		||||
                if self.obj and constants.network_key in self.obj
 | 
			
		||||
                and constants.http_proxy_key in self.obj[constants.network_key]
 | 
			
		||||
                else None)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user