Add ingress object

This commit is contained in:
David Boreham 2023-11-21 13:22:44 -07:00
parent 15e4c94b8d
commit 4e9151318a
4 changed files with 98 additions and 7 deletions

View File

@ -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"

View File

@ -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,

View File

@ -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)

View File

@ -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)