Add deployment update
and deploy-webapp-from-registry
commands.
#676
@ -40,6 +40,12 @@ class DockerDeployer(Deployer):
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
return self.docker.compose.restart()
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def ps(self):
|
||||
try:
|
||||
return self.docker.compose.ps()
|
||||
|
@ -107,6 +107,14 @@ def down_operation(ctx, delete_volumes, extra_args_list):
|
||||
ctx.obj.deployer.down(timeout=timeout_arg, volumes=delete_volumes)
|
||||
|
||||
|
||||
def update_operation(ctx):
|
||||
global_context = ctx.parent.parent.obj
|
||||
if not global_context.dry_run:
|
||||
if global_context.verbose:
|
||||
print("Running compose update")
|
||||
ctx.obj.deployer.update()
|
||||
|
||||
|
||||
def ps_operation(ctx):
|
||||
global_context = ctx.parent.parent.obj
|
||||
if not global_context.dry_run:
|
||||
|
@ -27,6 +27,10 @@ class Deployer(ABC):
|
||||
def down(self, timeout, volumes):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def ps(self):
|
||||
pass
|
||||
|
@ -19,7 +19,7 @@ import sys
|
||||
from stack_orchestrator import constants
|
||||
from stack_orchestrator.deploy.images import push_images_operation
|
||||
from stack_orchestrator.deploy.deploy import up_operation, down_operation, ps_operation, port_operation
|
||||
from stack_orchestrator.deploy.deploy import exec_operation, logs_operation, create_deploy_context
|
||||
from stack_orchestrator.deploy.deploy import exec_operation, logs_operation, create_deploy_context, update_operation
|
||||
from stack_orchestrator.deploy.deploy_types import DeployCommandContext
|
||||
from stack_orchestrator.deploy.deployment_context import DeploymentContext
|
||||
from stack_orchestrator.deploy.webapp import update_from_registry as webapp_update
|
||||
@ -161,3 +161,10 @@ def status(ctx):
|
||||
def update_from_registry(ctx, laconic_config, app_crn, deployment_crn, force):
|
||||
ctx.obj = make_deploy_context(ctx)
|
||||
webapp_update.update(ctx, str(ctx.obj.stack.parent), laconic_config, app_crn, deployment_crn, force)
|
||||
|
||||
|
||||
@command.command()
|
||||
@click.pass_context
|
||||
def update(ctx):
|
||||
ctx.obj = make_deploy_context(ctx)
|
||||
update_operation(ctx)
|
||||
|
@ -189,6 +189,7 @@ class ClusterInfo:
|
||||
container = client.V1Container(
|
||||
name=container_name,
|
||||
image=image_to_use,
|
||||
image_pull_policy="Always",
|
||||
env=envs_from_environment_variables_map(self.environment_variables.map),
|
||||
ports=[client.V1ContainerPort(container_port=port)],
|
||||
volume_mounts=volume_mounts,
|
||||
|
@ -13,6 +13,8 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from pathlib import Path
|
||||
from kubernetes import client, config
|
||||
|
||||
@ -42,7 +44,7 @@ class K8sDeployer(Deployer):
|
||||
networking_api: client.NetworkingV1Api
|
||||
k8s_namespace: str = "default"
|
||||
kind_cluster_name: str
|
||||
cluster_info : ClusterInfo
|
||||
cluster_info: ClusterInfo
|
||||
deployment_dir: Path
|
||||
deployment_context: DeploymentContext
|
||||
|
||||
@ -230,6 +232,33 @@ class K8sDeployer(Deployer):
|
||||
log_data = self.core_api.read_namespaced_pod_log(k8s_pod_name, namespace="default", container="test")
|
||||
return log_stream_from_string(log_data)
|
||||
|
||||
def update(self):
|
||||
self.connect_api()
|
||||
ref_deployment = self.cluster_info.get_deployment()
|
||||
|
||||
deployment = self.apps_api.read_namespaced_deployment(
|
||||
name=ref_deployment.metadata.name,
|
||||
namespace=self.k8s_namespace
|
||||
)
|
||||
|
||||
new_env = ref_deployment.spec.template.spec.containers[0].env
|
||||
for container in deployment.spec.template.spec.containers:
|
||||
old_env = container.env
|
||||
if old_env != new_env:
|
||||
container.env = new_env
|
||||
|
||||
deployment.spec.template.metadata.annotations = {
|
||||
"kubectl.kubernetes.io/restartedAt": datetime.utcnow()
|
||||
.replace(tzinfo=timezone.utc)
|
||||
.isoformat()
|
||||
}
|
||||
|
||||
self.apps_api.patch_namespaced_deployment(
|
||||
name=ref_deployment.metadata.name,
|
||||
namespace=self.k8s_namespace,
|
||||
body=deployment
|
||||
)
|
||||
|
||||
def run(self, image: str, command=None, user=None, volumes=None, entrypoint=None, env={}, ports=[], detach=False):
|
||||
# We need to figure out how to do this -- check why we're being called first
|
||||
pass
|
||||
|
@ -74,12 +74,8 @@ def config_changed(deploy_record, deployment_dir):
|
||||
|
||||
|
||||
def redeploy(laconic_config, app_record, deploy_record, deploy_crn, deployment_dir):
|
||||
print("Stopping deployment ...")
|
||||
result = subprocess.run(["laconic-so", "deployment", "--dir", deployment_dir, "stop"])
|
||||
result.check_returncode()
|
||||
|
||||
print("Starting deployment ...")
|
||||
result = subprocess.run(["laconic-so", "deployment", "--dir", deployment_dir, "start"])
|
||||
print("Updating deployment ...")
|
||||
result = subprocess.run(["laconic-so", "deployment", "--dir", deployment_dir, "update"])
|
||||
result.check_returncode()
|
||||
|
||||
spec = yaml.full_load(open(os.path.join(deployment_dir, "spec.yml")))
|
||||
@ -143,19 +139,20 @@ def update(ctx, deployment_dir, laconic_config, app_crn, deploy_crn, force=False
|
||||
if app_record["id"] == deploy_record.get("attributes", {}).get("application"):
|
||||
print("Deployment %s has latest application: %s" % (deploy_crn, app_record["id"]))
|
||||
else:
|
||||
needs_update = True
|
||||
print("Found updated application record eligible for deployment %s (old: %s, new: %s)" % (
|
||||
deploy_crn, deploy_record.get("id"), app_record["id"]))
|
||||
build_image(app_record, deployment_dir)
|
||||
needs_update = True
|
||||
|
||||
# check config
|
||||
if config_changed(deploy_record, deployment_dir):
|
||||
needs_update = True
|
||||
old = None
|
||||
if deploy_record:
|
||||
old = json.loads(deploy_record["attributes"]["meta"]["config"])
|
||||
print(deploy_record)
|
||||
old = json.loads(deploy_record["attributes"]["meta"])["config"]
|
||||
print("Deployment %s has changed config: (old: %s, new: %s)" % (
|
||||
deploy_crn, old, config_hash(deployment_dir)))
|
||||
needs_update = True
|
||||
else:
|
||||
print("Deployment %s has latest config: %s" % (
|
||||
deploy_crn, json.loads(deploy_record["attributes"]["meta"])["config"]))
|
||||
|
Loading…
Reference in New Issue
Block a user