Skip to content

Commit

Permalink
fix(deployments): fix deployment status and wait command
Browse files Browse the repository at this point in the history
  • Loading branch information
smrutisenapati authored and pallabpain committed Sep 4, 2024
1 parent c97b186 commit 0e3ea14
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 53 deletions.
28 changes: 15 additions & 13 deletions riocli/deployment/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,29 @@

import click
from click_help_colors import HelpColorsCommand
from rapyuta_io.clients.deployment import Deployment, DeploymentPhaseConstants
from riocli.v2client.enums import DeploymentPhaseConstants
from rapyuta_io.clients.deployment import Deployment

from riocli.config import new_v2_client
from riocli.constants import Colors
from riocli.deployment.util import process_deployment_errors
from riocli.utils import tabulate_data

ALL_PHASES = [
DeploymentPhaseConstants.INPROGRESS,
DeploymentPhaseConstants.PROVISIONING,
DeploymentPhaseConstants.SUCCEEDED,
DeploymentPhaseConstants.FAILED_TO_START,
DeploymentPhaseConstants.PARTIALLY_DEPROVISIONED,
DeploymentPhaseConstants.DEPLOYMENT_STOPPED,
DeploymentPhaseConstants.DeploymentPhaseInProgress,
DeploymentPhaseConstants.DeploymentPhaseProvisioning,
DeploymentPhaseConstants.DeploymentPhaseSucceeded,
DeploymentPhaseConstants.DeploymentPhaseStopped,
DeploymentPhaseConstants.DeploymentPhaseFailedToStart,
DeploymentPhaseConstants.DeploymentPhaseFailedToUpdate,
]

DEFAULT_PHASES = [
DeploymentPhaseConstants.INPROGRESS,
DeploymentPhaseConstants.PROVISIONING,
DeploymentPhaseConstants.SUCCEEDED,
DeploymentPhaseConstants.FAILED_TO_START,
DeploymentPhaseConstants.DeploymentPhaseInProgress,
DeploymentPhaseConstants.DeploymentPhaseProvisioning,
DeploymentPhaseConstants.DeploymentPhaseSucceeded,
DeploymentPhaseConstants.DeploymentPhaseFailedToStart,
DeploymentPhaseConstants.DeploymentPhaseFailedToUpdate
]


Expand All @@ -46,7 +48,7 @@
help_options_color=Colors.GREEN,
)
@click.option('--device', prompt_required=False, default='', type=str,
help='Filter the Deployment list by Device ID')
help='Filter the Deployment list by Device name')
@click.option('--phase', prompt_required=False, multiple=True,
type=click.Choice(ALL_PHASES),
default=DEFAULT_PHASES,
Expand All @@ -63,7 +65,7 @@ def list_deployments(
"""
try:
client = new_v2_client(with_project=True)
deployments = client.list_deployments()
deployments = client.list_deployments(query={"phases": phase, "deviceName": device})
deployments = sorted(deployments, key=lambda d: d.metadata.name.lower())
display_deployment_list(deployments, show_header=True)
except Exception as e:
Expand Down
2 changes: 1 addition & 1 deletion riocli/deployment/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def status(deployment_name: str) -> None:
try:
client = new_v2_client()
deployment = client.get_deployment(deployment_name)
click.secho(deployment.status)
click.secho(deployment.status.aggregateStatus)
except Exception as e:
click.secho(str(e), fg=Colors.RED)
raise SystemExit(1)
34 changes: 7 additions & 27 deletions riocli/deployment/wait.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import click
import typing
import time

from click_help_colors import HelpColorsCommand
from rapyuta_io.utils import RetriesExhausted, DeploymentNotRunningException
from riocli.config import new_v2_client
from riocli.constants import Colors, Symbols, Status
from riocli.deployment.util import name_to_guid
from riocli.constants import Colors, Symbols
from riocli.utils.spinner import with_spinner
from riocli.v2client.error import RetriesExhausted, DeploymentNotRunning

from rapyuta_io import Client

def poll_deployment_till_ready(client: Client, deployment: typing.Any, retry_count=50, sleep_interval=6):
for _ in range(retry_count):
if deployment.status.status == Status.RUNNING:
return deployment

time.sleep(sleep_interval)
deployment = client.get_deployment(deployment.metadata.name)
return deployment

@click.command(
'wait',
Expand All @@ -50,25 +37,18 @@ def wait_for_deployment(
"""
try:
client = new_v2_client()
deployment = client.get_deployment(deployment_name)

retry_count = int(kwargs.get('retry_count'))
retry_interval = int(kwargs.get('retry_interval'))
deployment = poll_deployment_till_ready(client, deployment, retry_count, retry_interval)
deployment = client.poll_deployment(deployment_name)
spinner.text = click.style('Deployment status: {}'.format(deployment.status.status), fg=Colors.GREEN)
spinner.green.ok(Symbols.SUCCESS)
except RetriesExhausted as e:
spinner.write(click.style(str(e), fg=Colors.RED))
spinner.text = click.style('Try again?', Colors.RED)
spinner.text = click.style('Try again', Colors.RED)
spinner.red.fail(Symbols.ERROR)
except DeploymentNotRunningException as e:
if 'DEP_E151' in e.deployment_status.errors:
spinner.text = click.style('Device is either offline or not reachable', fg=Colors.RED)
else:
spinner.text = click.style(str(e), fg=Colors.RED)
except DeploymentNotRunning as e:
spinner.text = click.style(str(e), fg=Colors.RED)
spinner.red.fail(Symbols.ERROR)
raise SystemExit(1)
except Exception as e:
spinner.text = click.style(str(e), fg=Colors.RED)
spinner.red.fail(Symbols.ERROR)
raise SystemExit(1)
raise SystemExit(1)
65 changes: 53 additions & 12 deletions riocli/v2client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,26 @@
import http
import json
import os
import time
from hashlib import md5
from typing import List, Optional, Dict, Any

import click
import magic
import requests
from munch import munchify, Munch

from rapyuta_io.utils.rest_client import HttpMethod, RestClient

from riocli.v2client.enums import DeploymentPhaseConstants
from riocli.v2client.error import RetriesExhausted, DeploymentNotRunning


class DeploymentNotFound(Exception):
def __init__(self, message='deployment not found!'):
self.message = message
super().__init__(self.message)


def handle_server_errors(response: requests.Response):
status_code = response.status_code
# 500 Internal Server Error
Expand All @@ -51,11 +57,13 @@ def handle_server_errors(response: requests.Response):
if status_code > 504:
raise Exception('unknown server error')


class NetworkNotFound(Exception):
def __init__(self, message='network not found!'):
self.message = message
super().__init__(self.message)


class Client(object):
"""
v2 API Client
Expand Down Expand Up @@ -722,8 +730,6 @@ def _walk_pages(self, c: RestClient, params: dict = {}, limit: Optional[int] = N

return munchify(result)



def list_packages(
self,
query: dict = None
Expand Down Expand Up @@ -816,7 +822,6 @@ def delete_package(self, package_name: str,
raise Exception("package: {}".format(err_msg))

return munchify(data)


def list_networks(
self,
Expand Down Expand Up @@ -911,13 +916,13 @@ def delete_network(self, network_name: str,
data = json.loads(response.text)
if not response.ok:
err_msg = data.get('error')
raise Exception("package: {}".format(err_msg))
raise Exception("network: {}".format(err_msg))

return munchify(data)

def list_deployments(
self,
query: dict = None
self,
query: dict = None
) -> Munch:
"""
List all deployments in a project
Expand Down Expand Up @@ -947,7 +952,7 @@ def list_deployments(
result.extend(deployments)

return munchify(result)

def create_deployment(self, deployment: dict) -> Munch:
"""
Create a new deployment
Expand All @@ -965,11 +970,11 @@ def create_deployment(self, deployment: dict) -> Munch:
raise Exception("deployment: {}".format(err_msg))

return munchify(data)

def get_deployment(
self,
name: str,
query: dict = None
self,
name: str,
query: dict = None
):
url = "{}/v2/deployments/{}/".format(self._host, name)
headers = self._config.get_auth_header()
Expand Down Expand Up @@ -1024,6 +1029,42 @@ def delete_deployment(self, name: str, query: dict = None) -> Munch:

return munchify(data)

def poll_deployment(
self,
name: str,
retry_count: int = 50,
sleep_interval: int = 6,
ready_phases: List[str] = None,
) -> Munch:
if ready_phases is None:
ready_phases = []

deployment = self.get_deployment(name)

status = deployment.status

for _ in range(retry_count):
if status.phase in ready_phases:
return deployment

if status.phase == DeploymentPhaseConstants.DeploymentPhaseProvisioning.value:
errors = status.error_codes or []
if 'DEP_E153' in errors: # DEP_E153 (image-pull error) will persist across retries
return deployment
elif status.phase == DeploymentPhaseConstants.DeploymentPhaseSucceeded.value:
return deployment
elif status.phase in [DeploymentPhaseConstants.DeploymentPhaseFailedToUpdate.value,
DeploymentPhaseConstants.DeploymentPhaseFailedToStart.value,
DeploymentPhaseConstants.DeploymentPhaseStopped.value]:
raise DeploymentNotRunning('Deployment not running. Deployment status: {}'.format(status.phase))

time.sleep(sleep_interval)
deployment = self.get_deployment(name)
status = deployment.status

raise RetriesExhausted('Retried {} time done with an interval of {} seconds. Deployment status: {}'.format(
retry_count, sleep_interval, status.phase))

def list_disks(
self,
query: dict = None
Expand Down
33 changes: 33 additions & 0 deletions riocli/v2client/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import enum


class DeploymentPhaseConstants(str, enum.Enum):
"""
Enumeration variables for the deployment phase
"""

def __str__(self):
return str(self.value)

DeploymentPhaseInProgress = "InProgress"
DeploymentPhaseProvisioning = "Provisioning"
DeploymentPhaseSucceeded = "Succeeded"
DeploymentPhaseFailedToUpdate = "FailedToUpdate"
DeploymentPhaseFailedToStart = "FailedToStart"
DeploymentPhaseStopped = "Stopped"


class DeploymentStatusConstants(str, enum.Enum):
"""
Enumeration variables for the deployment status
"""

def __str__(self):
return str(self.value)

DeploymentStatusRunning = "Running"
DeploymentStatusPending = "Pending"
DeploymentStatusError = "Error"
DeploymentStatusUnknown = "Unknown"
DeploymentStatusStopped = "Stopped"
9 changes: 9 additions & 0 deletions riocli/v2client/error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

class RetriesExhausted(Exception):
def __init__(self, msg=None):
Exception.__init__(self, msg)


class DeploymentNotRunning(Exception):
def __init__(self, msg=None):
Exception.__init__(self, msg)

0 comments on commit 0e3ea14

Please sign in to comment.