Skip to content

Commit

Permalink
feat(status_cmd): add the api-status command
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Desanlis authored and Jguer committed Jul 1, 2021
1 parent 0345c8f commit 419d331
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 2 deletions.
9 changes: 8 additions & 1 deletion ggshield/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .ignore import ignore
from .install import install
from .quota import quota
from .status import status
from .utils import json_output_option_decorator, retrieve_client


Expand Down Expand Up @@ -124,7 +125,13 @@ def exit_code(ctx: click.Context, exit_code: int, **kwargs: Any) -> None:

@click.group(
context_settings=CONTEXT_SETTINGS,
commands={"scan": scan, "install": install, "ignore": ignore, "quota": quota},
commands={
"scan": scan,
"install": install,
"ignore": ignore,
"quota": quota,
"api-status": status,
},
)
@click.option(
"-c",
Expand Down
12 changes: 11 additions & 1 deletion ggshield/output/text/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from io import StringIO
from typing import Dict, List, Optional, Set, Tuple

from pygitguardian.models import Match, PolicyBreak
from pygitguardian.models import HealthCheckResponse, Match, PolicyBreak

from ggshield.text_utils import STYLE, Line, format_text, pluralize

Expand Down Expand Up @@ -340,3 +340,13 @@ def format_quota_color(remaining: int, limit: int) -> str:
color = "green"

return format_text(str(remaining), {"fg": color})


def format_healthcheck_status(health_check: HealthCheckResponse) -> str:
(color, status) = (
("red", f"unhealthy ({health_check.detail})")
if health_check.status_code != 200
else ("green", "healthy")
)

return format_text(status, {"fg": color})
36 changes: 36 additions & 0 deletions ggshield/status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/python3

import click
from pygitguardian import GGClient
from pygitguardian.models import HealthCheckResponse

from ggshield.output.text.message import format_healthcheck_status

from .utils import json_output_option_decorator, retrieve_client


@click.command()
@click.pass_context
def status(ctx: click.Context, json_output: bool) -> int:
"""Command to show api status."""
client: GGClient = retrieve_client(ctx)
response: HealthCheckResponse = client.health_check()

if not isinstance(response, HealthCheckResponse):
raise click.ClickException("Unexpected health check response")

click.echo(
response.to_json()
if json_output
else (
f"status: {format_healthcheck_status(response)}\n"
f"app-version: {response.app_version or 'Unknown'}\n"
"secrets-engine-version-version: "
f"{response.secrets_engine_version or 'Unknown'}\n"
)
)

return 0


status = json_output_option_decorator(status)
86 changes: 86 additions & 0 deletions tests/cassettes/test_health_check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
interactions:
- request:
body: null
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- pygitguardian/1.1.0 (Linux;py3.8.3)
method: GET
uri: https://api.gitguardian.com/v1/health
response:
body:
string: '{"detail":"Valid API key."}'
headers:
Allow:
- OPTIONS, GET
Connection:
- keep-alive
Content-Length:
- "27"
Content-Type:
- application/json
Date:
- Fri, 19 Jun 2020 13:32:39 GMT
Server:
- nginx
Vary:
- Cookie
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-App-Version:
- 1.26.0-rc.4
X-Secrets-Engine-Version:
- 2.43.0
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- pygitguardian/1.1.0 (Linux;py3.8.3)
method: GET
uri: https://api.gitguardian.com/v1/health
response:
body:
string: '{"detail":"Valid API key."}'
headers:
Allow:
- OPTIONS, GET
Connection:
- keep-alive
Content-Length:
- "27"
Content-Type:
- application/json
Date:
- Fri, 19 Jun 2020 14:58:35 GMT
Server:
- nginx
Vary:
- Cookie
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-App-Version:
- 1.26.0-rc.4
X-Secrets-Engine-Version:
- 2.43.0
status:
code: 200
message: OK
version: 1
86 changes: 86 additions & 0 deletions tests/cassettes/test_health_check_error.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
interactions:
- request:
body: null
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- pygitguardian/1.1.0 (Linux;py3.8.3)
method: GET
uri: https://api.gitguardian.com/v1/health
response:
body:
string: '{"error":"Configuration error."}'
headers:
Allow:
- OPTIONS, GET
Connection:
- keep-alive
Content-Length:
- "27"
Content-Type:
- application/json
Date:
- Fri, 19 Jun 2020 13:32:39 GMT
Server:
- nginx
Vary:
- Cookie
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-App-Version:
- 1.26.0-rc.4
X-Secrets-Engine-Version:
- 2.43.0
status:
code: 400
message: OK
- request:
body: null
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- pygitguardian/1.1.0 (Linux;py3.8.3)
method: GET
uri: https://api.gitguardian.com/v1/health
response:
body:
string: '{"detail":"Valid API key."}'
headers:
Allow:
- OPTIONS, GET
Connection:
- keep-alive
Content-Length:
- "27"
Content-Type:
- application/json
Date:
- Fri, 19 Jun 2020 14:58:35 GMT
Server:
- nginx
Vary:
- Cookie
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-App-Version:
- 1.26.0-rc.4
X-Secrets-Engine-Version:
- 2.43.0
status:
code: 200
message: OK
version: 1
15 changes: 15 additions & 0 deletions tests/snapshots/snap_test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@

snapshots = Snapshot()

snapshots['test_api_status[test_health_check-False] 1'] = '''status: \x1b[32m\x1b[22m\x1b[22mhealthy\x1b[0m
app-version: 1.26.0-rc.4
secrets-engine-version-version: 2.43.0
'''

snapshots['test_api_status[test_health_check-True] 1'] = '''{"detail": "Valid API key.", "status_code": 200, "app_version": "1.26.0-rc.4", "secrets_engine_version": "2.43.0"}
'''

snapshots['test_api_status[test_health_check_error-False] 1'] = '''status: \x1b[31m\x1b[22m\x1b[22munhealthy (Configuration error.)\x1b[0m
app-version: 1.26.0-rc.4
secrets-engine-version-version: 2.43.0
'''

snapshots['test_quota[quota-False] 1'] = '''Quota available: \x1b[32m\x1b[22m\x1b[22m4998\x1b[0m
Quota used in the last 30 days: 2
Total Quota of the workspace: 5000
Expand Down
16 changes: 16 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,19 @@ def test_quota(cassette, json_output, snapshot, cli_fs_runner):
result = cli_fs_runner.invoke(cli, cmd, color=True)
assert result.exit_code == 0
snapshot.assert_match(result.output)


@pytest.mark.parametrize(
"cassette, json_output",
[
("test_health_check", True),
("test_health_check", False),
("test_health_check_error", False),
],
)
def test_api_status(cassette, json_output, snapshot, cli_fs_runner):
with my_vcr.use_cassette(cassette):
cmd = ["api-status", "--json"] if json_output else ["api-status"]
result = cli_fs_runner.invoke(cli, cmd, color=True)
assert result.exit_code == 0
snapshot.assert_match(result.output)

0 comments on commit 419d331

Please sign in to comment.