Skip to content

Commit

Permalink
Merge pull request #117 from 2ndWatch/add/report_function
Browse files Browse the repository at this point in the history
CLI helper functions to audit CloudEndure
  • Loading branch information
twarnock authored May 19, 2020
2 parents b589875 + c6dab32 commit 3898a3a
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ SHA1 := $$(git log -1 --pretty=%h)
CURRENT_BRANCH := $$(git symbolic-ref -q --short HEAD)
LATEST_TAG := ${REPO_NAME}:latest
GIT_TAG := ${REPO_NAME}:${SHA1}
VERSION := v0.2.8
VERSION := v0.2.9

info: ## Show information about the current git state.
@echo "Github Project: https://github.com/${REPO_NAME}\nCurrent Branch: ${CURRENT_BRANCH}\nSHA1: ${SHA1}\n"
Expand Down
2 changes: 1 addition & 1 deletion cloudendure/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.8"
__version__ = "0.2.9"
70 changes: 70 additions & 0 deletions cloudendure/cloudendure.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import json
import os
import pprint
from datetime import datetime, timezone
from typing import Any, Dict, List

import boto3
Expand Down Expand Up @@ -446,6 +447,75 @@ def check_licenses(self) -> Dict[str, Any]:

return response_dict

def get_machine_sync_details(self) -> List[Any]:
"""Checks CloudEndure Project inventory and returns register machine's
replication state.
"""
response_list: List[Any] = []
print(f"INFO: Retreiving sync status for all machines in Project: ({self.project_name})")
machines_response: Response = self.api.api_call(f"projects/{self.project_id}/machines")
if not machines_response.ok:
print(f"ERROR: API response did not return a 2XX status; Returned {machines_response.status_code} ...")
return {}
ce_project_inventory = json.loads(machines_response.text).get("items", [])
for _query_value in ce_project_inventory:
machine_name: str = _query_value["sourceProperties"]["name"]
sync_details: Dict[str, Any] = {
"machine_name": machine_name,
"in_inventory": _query_value["isAgentInstalled"],
"replication_status": _query_value["replicationStatus"],
"last_seen_utc": _query_value["replicationInfo"]["lastSeenDateTime"],
"total_storage_bytes": _query_value["replicationInfo"]["totalStorageBytes"],
"replicated_storage_bytes": _query_value["replicationInfo"]["replicatedStorageBytes"],
"rescanned_storage_bytes": 0,
"backlogged_storage_bytes": _query_value["replicationInfo"]["backloggedStorageBytes"],
}
if "rescannedStorageBytes" in _query_value["replicationInfo"]:
sync_details["recanned_storage_bytes"] = _query_value["replicationInfo"]["rescannedStorageBytes"]
response_list.append(sync_details)
# Project is still printing to console as a convention; Emitting an
# output to stdout for interactive usage
return response_list

def inspect_ce_project(self, check_type: str) -> List[Any]:
if not check_type:
print(
f"ERROR: Unknown check_type of '{check_type}'; Please use 'not_synced', 'not_started', or 'not_current' ..."
)
return
result: List[Any] = []
sync_report: List[Any] = self.get_machine_sync_details()
print(f"INFO: Using check '{check_type}' on Project: ({self.project_name})")
inspector = getattr(self, check_type)
for item in sync_report:
mcheck = inspector(machine=item)
if mcheck:
result.append(item)
print(f"INFO: Check '{check_type}' completed; {len(result)} machines matched in Project: ({self.project_name})")
return result

def not_synced(self, machine) -> bool:
if machine["backlogged_storage_bytes"] > 0 or machine["rescanned_storage_bytes"] > 0:
return True
else:
return False

def not_started(self, machine) -> bool:
if machine["replication_status"] == "STARTED":
return False
else:
return True

def not_current(self, machine, delta_seconds: int = 86400) -> bool:
now: datetime = datetime.now(timezone.utc)
machine_last_seen: datetime = datetime.fromisoformat(machine["last_seen_utc"])
last_seen_delta: datetime = now - machine_last_seen
# If you're exceeding the size of int, you have bigger problems
if int(last_seen_delta.total_seconds()) >= delta_seconds:
return True
else:
return False

def update_blueprint(self) -> bool:
"""Update the blueprint associated with the specified machines."""
print(f"Updating CloudEndure Blueprints - Name: ({self.project_name}) - Dry Run: ({self.dry_run})")
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "cloudendure"
version = "0.2.8"
version = "0.2.9"
description = "Python wrapper and CLI for CloudEndure"
authors = ["Mark Beacom <mark@markbeacom.com>", "Tom Warnock <twarnock@2ndwatch.com>"]
maintainers = ["Evan Lucchesi <evan@2ndwatch.com>", "Nick Selpa <nselpa@2ndwatch.com>"]
Expand Down

0 comments on commit 3898a3a

Please sign in to comment.