Skip to content

Commit

Permalink
feat: deployment modes
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgiga1993 committed Mar 20, 2024
1 parent 16e4355 commit 820fa10
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 5 deletions.
34 changes: 32 additions & 2 deletions octoploy/api/Kubectl.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ def apply(self, yml: str, namespace: Optional[str] = None) -> str:
"""
raise NotImplemented

@abstractmethod
def replace(self, yml: str, namespace: Optional[str] = None) -> str:
"""
Replaces the object
:param yml: Yml file
:param namespace: Namespace
:return: Stdout
"""
raise NotImplemented

@abstractmethod
def create(self, yml: str, namespace: Optional[str] = None) -> str:
"""
Creates the object
:param yml: Yml file
:param namespace: Namespace
:return: Stdout
"""
raise NotImplemented

@abstractmethod
def get_pod(self, dc_name: str = None, pod_name: str = None,
namespace: Optional[str] = None) -> Optional[PodData]:
Expand Down Expand Up @@ -133,6 +153,10 @@ def delete(self, name: str, namespace: str):


class Oc(K8sApi):
"""
Openshift specific implementation
"""

def get_namespaces(self) -> List[str]:
lines = self._exec(['get', 'namespaces', '-o', 'name'])
return lines.splitlines()
Expand All @@ -144,7 +168,7 @@ def get(self, name: str, namespace: Optional[str] = None) -> Optional[BaseObj]:
try:
json_str = self._exec(['get', name, '-o', 'json'], namespace=namespace)
except Exception as e:
if 'NotFound' in str(e):
if 'NotFound' in str(e) or "doesn't have a resource type" in str(e):
return None
raise

Expand All @@ -155,6 +179,12 @@ def dry_run(self, yml: str, namespace: Optional[str] = None, server_side_dry_run
json_str = self._exec(args, stdin=yml, namespace=namespace)
return BaseObj(json.loads(json_str))

def replace(self, yml: str, namespace: Optional[str] = None) -> str:
return self._exec(['replace', '-f', '-'], stdin=yml, namespace=namespace)

def create(self, yml: str, namespace: Optional[str] = None) -> str:
return self._exec(['create', '-f', '-'], stdin=yml, namespace=namespace)

def apply(self, yml: str, namespace: Optional[str] = None) -> str:
return self._exec(['apply', '-f', '-'], stdin=yml, namespace=namespace)

Expand Down Expand Up @@ -259,7 +289,7 @@ def _get_bin(self) -> str:
return 'oc'


class K8(Oc):
class K8s(Oc):
def rollout(self, name: str, namespace: Optional[str] = None):
self._exec(['rollout', 'restart', 'deployment', name], namespace=namespace)

Expand Down
10 changes: 10 additions & 0 deletions octoploy/config/AppConfig.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from octoploy.deploy.DeploymentMode import DeploymentMode, ReplaceDeploymentMode, ApplyDeploymentMode

if TYPE_CHECKING:
from octoploy.config.Config import RootConfig

Expand Down Expand Up @@ -125,3 +129,9 @@ def get_replacements(self) -> Dict[str, str]:
'DC_NAME': dc_name # Deprecated
})
return items

def get_deployment_mode(self) -> DeploymentMode:
mode = self.data.get('deploymentMode', 'apply')
if mode == 'replace':
return ReplaceDeploymentMode()
return ApplyDeploymentMode()
4 changes: 2 additions & 2 deletions octoploy/config/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os
from typing import Optional, Dict, List

from octoploy.api.Kubectl import Oc, K8, K8sApi
from octoploy.api.Kubectl import Oc, K8s, K8sApi
from octoploy.config.AppConfig import AppConfig
from octoploy.config.BaseConfig import BaseConfig
from octoploy.processing import Constants
Expand Down Expand Up @@ -155,7 +155,7 @@ def create_api(self) -> K8sApi:
if mode == 'oc':
k8s_api = Oc()
elif mode == 'k8s' or mode == 'k8':
k8s_api = K8()
k8s_api = K8s()
else:
raise ValueError(f'Invalid mode: {mode}')

Expand Down
3 changes: 3 additions & 0 deletions octoploy/config/DynamicConfigMap.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class DynamicConfigMap:
def __init__(self, data):
self._data = data
self.name = data['name']
self.namespace = data.get('namespace')
self.files = data['files']
self.disable_templating = data.get('disableTemplating', False)

Expand All @@ -31,6 +32,8 @@ def build_object(self, config_root: str) -> ConfigMapObject:
},
'data': config_data
}
if self.namespace is not None:
data['metadata']['namespace'] = self.namespace

for file_obj in self.files:
file = file_obj['file']
Expand Down
37 changes: 37 additions & 0 deletions octoploy/deploy/DeploymentMode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from abc import abstractmethod
from typing import Optional

from octoploy.api.Kubectl import K8sApi
from octoploy.k8s.BaseObj import BaseObj


class DeploymentMode:
"""
Defines how an object should be deployed
"""
_api: K8sApi

def use_api(self, api: K8sApi):
self._api = api

@abstractmethod
def deploy(self, k8s_object: BaseObj, existing_object: Optional[BaseObj], namespace: str):
pass


class ReplaceDeploymentMode(DeploymentMode):
"""
Replace the object
"""

def deploy(self, k8s_object: BaseObj, existing_object: Optional[BaseObj], namespace: str):
self._api.replace(k8s_object.as_string(), namespace=namespace)


class ApplyDeploymentMode(DeploymentMode):
"""
Apply the object
"""

def deploy(self, k8s_object: BaseObj, existing_object: Optional[BaseObj], namespace: str):
self._api.apply(k8s_object.as_string(), namespace=namespace)
4 changes: 3 additions & 1 deletion octoploy/deploy/K8sObjectDeployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ def _deploy_object(self, k8s_object: BaseObj):
# Migrate to new state format by removing the old one
self._api.annotate(k8s_object.get_fqn(), self.HASH_ANNOTATION, None, namespace=k8s_object.namespace)

self._api.apply(k8s_object.as_string(), namespace=namespace)
deploy_mode = self._app_config.get_deployment_mode()
deploy_mode.use_api(self._api)
deploy_mode.deploy(k8s_object, current_object, namespace=namespace)

# Update hash
self._state.visit(self._app_config.get_name(), k8s_object, hash_val)
Expand Down

0 comments on commit 820fa10

Please sign in to comment.