# Path: slo_generator/cli.py
# @click.group(invoke_without_command=True)
# @click.option('--version',
#               '-v',
#               is_flag=True,
#               help='Show slo-generator version.')
# @click.pass_context
# def main(ctx, version):
#     """CLI entrypoint."""
#     utils.setup_logging()
#     if ctx.invoked_subcommand is None or version:
#         ver = get_distribution('slo-generator').version
#         print(f'slo-generator v{ver}')
#         sys.exit(0)
# 
# Path: slo_generator/utils.py
# def load_config(path, ctx=os.environ, kind=None):
#     """Load any slo-generator config, from a local path, a GCS URL, or directly
#     from a string content.
# 
#     Args:
#         path (str): GCS URL, file path, or data as string.
#         ctx (dict): Context for variable replacement.
#         kind (str): Config kind filter.
# 
#     Returns:
#         dict: Config downloaded and parsed.
#     """
#     abspath = Path(path)
#     try:
#         if path.startswith('gs://'):
#             if not GCS_ENABLED:
#                 warnings.warn(
#                     'To load a file from GCS, you need `google-cloud-storage` '
#                     'installed. Please install it using pip by running '
#                     '`pip install google-cloud-storage`', ImportWarning)
#                 sys.exit(1)
#             config = parse_config(content=download_gcs_file(str(path)), ctx=ctx)
#         elif abspath.is_file():
#             config = parse_config(path=str(abspath.resolve()), ctx=ctx)
#         else:
#             LOGGER.debug(f'Path {path} not found. Trying to load from string')
#             config = parse_config(content=str(path), ctx=ctx)
# 
#         # Filter on 'kind'
#         if kind and (
#             not isinstance(config, dict) or kind != config.get('kind', '')
#         ):
#             config = None
#         return config
# 
#     except OSError as exc:
#         if exc.errno == errno.ENAMETOOLONG:
#             return parse_config(content=str(path), ctx=ctx)
#         raise
# 
# Path: tests/unit/test_stubs.py
# CTX = {
#     'PROJECT_ID': 'fake',
#     'PUBSUB_PROJECT_ID': 'fake',
#     'PUBSUB_TOPIC_NAME': 'fake',
#     'GAE_PROJECT_ID': 'fake',
#     'GAE_MODULE_ID': 'fake',
#     'GKE_MESH_UID': 'fake',
#     'GKE_PROJECT_ID': 'fake',
#     'GKE_CLUSTER_NAME': 'fake',
#     'GKE_LOCATION': 'fake',
#     'GKE_SERVICE_NAMESPACE': 'fake',
#     'GKE_SERVICE_NAME': 'fake',
#     'LB_PROJECT_ID': 'fake',
#     'PROMETHEUS_URL': 'http://localhost:9090',
#     'PROMETHEUS_PUSHGATEWAY_URL': 'http://localhost:9091',
#     'ELASTICSEARCH_URL': 'http://localhost:9200',
#     'STACKDRIVER_HOST_PROJECT_ID': 'fake',
#     'STACKDRIVER_LOG_METRIC_NAME': 'fake',
#     'BIGQUERY_PROJECT_ID': 'fake',
#     'BIGQUERY_TABLE_ID': 'fake',
#     'BIGQUERY_DATASET_ID': 'fake',
#     'BIGQUERY_TABLE_NAME': 'fake',
#     'DATADOG_API_KEY': 'fake',
#     'DATADOG_APP_KEY': 'fake',
#     'DATADOG_SLO_ID': 'fake',
#     'DYNATRACE_API_URL': 'fake',
#     'DYNATRACE_API_TOKEN': 'fake',
#     'DYNATRACE_SLO_ID': 'fake'
# }
# 
# def mock_sd(nresp=1):
#     """Fake Stackdriver Monitoring API response for the ListTimeSeries endpoint.
# 
#     Args:
#         nresp (int): Number of responses to add to response.
# 
#     Returns:
#         ChannelStub: Mocked gRPC channel stub.
#     """
#     timeserie = load_fixture('time_series_proto.json')
#     response = {"next_page_token": "", "time_series": [timeserie]}
#     return mock_grpc_stub(
#         response=response,
#         proto_method=metric_service_pb2.ListTimeSeriesResponse,
#         nresp=nresp)


import os
import unittest
from mock import patch
from click.testing import CliRunner
from slo_generator.cli import main
from slo_generator.utils import load_config
from .test_stubs import CTX, mock_sd





cwd = os.path.dirname(os.path.abspath(__file__))
root = os.path.dirname(os.path.dirname(cwd))


class TestCLI(unittest.TestCase):

    def setUp(self):
        for key, value in CTX.items():
            os.environ[key] = value
        slo_config = f'{root}/samples/cloud_monitoring/slo_gae_app_availability.yaml'  # noqa: E501
        config = f'{root}/samples/config.yaml'
        self.slo_config = slo_config
        self.slo_metadata_name = load_config(slo_config,
                                             ctx=CTX)['metadata']['name']
        self.config = config
        self.cli = CliRunner()

    @patch('google.api_core.grpc_helpers.create_channel',
           return_value=mock_sd(8))
    def test_cli_compute(self, mock):
        args = ['compute', '-f', self.slo_config, '-c', self.config]
        result = self.cli.invoke(main, args)
        self.assertEqual(result.exit_code, 0)

    @patch('google.api_core.grpc_helpers.create_channel',

# Path: slo_generator/cli.py
# @click.group(invoke_without_command=True)
# @click.option('--version',
#               '-v',
#               is_flag=True,
#               help='Show slo-generator version.')
# @click.pass_context
# def main(ctx, version):
#     """CLI entrypoint."""
#     utils.setup_logging()
#     if ctx.invoked_subcommand is None or version:
#         ver = get_distribution('slo-generator').version
#         print(f'slo-generator v{ver}')
#         sys.exit(0)
# 
# Path: slo_generator/utils.py
# def load_config(path, ctx=os.environ, kind=None):
#     """Load any slo-generator config, from a local path, a GCS URL, or directly
#     from a string content.
# 
#     Args:
#         path (str): GCS URL, file path, or data as string.
#         ctx (dict): Context for variable replacement.
#         kind (str): Config kind filter.
# 
#     Returns:
#         dict: Config downloaded and parsed.
#     """
#     abspath = Path(path)
#     try:
#         if path.startswith('gs://'):
#             if not GCS_ENABLED:
#                 warnings.warn(
#                     'To load a file from GCS, you need `google-cloud-storage` '
#                     'installed. Please install it using pip by running '
#                     '`pip install google-cloud-storage`', ImportWarning)
#                 sys.exit(1)
#             config = parse_config(content=download_gcs_file(str(path)), ctx=ctx)
#         elif abspath.is_file():
#             config = parse_config(path=str(abspath.resolve()), ctx=ctx)
#         else:
#             LOGGER.debug(f'Path {path} not found. Trying to load from string')
#             config = parse_config(content=str(path), ctx=ctx)
# 
#         # Filter on 'kind'
#         if kind and (
#             not isinstance(config, dict) or kind != config.get('kind', '')
#         ):
#             config = None
#         return config
# 
#     except OSError as exc:
#         if exc.errno == errno.ENAMETOOLONG:
#             return parse_config(content=str(path), ctx=ctx)
#         raise
# 
# Path: tests/unit/test_stubs.py
# CTX = {
#     'PROJECT_ID': 'fake',
#     'PUBSUB_PROJECT_ID': 'fake',
#     'PUBSUB_TOPIC_NAME': 'fake',
#     'GAE_PROJECT_ID': 'fake',
#     'GAE_MODULE_ID': 'fake',
#     'GKE_MESH_UID': 'fake',
#     'GKE_PROJECT_ID': 'fake',
#     'GKE_CLUSTER_NAME': 'fake',
#     'GKE_LOCATION': 'fake',
#     'GKE_SERVICE_NAMESPACE': 'fake',
#     'GKE_SERVICE_NAME': 'fake',
#     'LB_PROJECT_ID': 'fake',
#     'PROMETHEUS_URL': 'http://localhost:9090',
#     'PROMETHEUS_PUSHGATEWAY_URL': 'http://localhost:9091',
#     'ELASTICSEARCH_URL': 'http://localhost:9200',
#     'STACKDRIVER_HOST_PROJECT_ID': 'fake',
#     'STACKDRIVER_LOG_METRIC_NAME': 'fake',
#     'BIGQUERY_PROJECT_ID': 'fake',
#     'BIGQUERY_TABLE_ID': 'fake',
#     'BIGQUERY_DATASET_ID': 'fake',
#     'BIGQUERY_TABLE_NAME': 'fake',
#     'DATADOG_API_KEY': 'fake',
#     'DATADOG_APP_KEY': 'fake',
#     'DATADOG_SLO_ID': 'fake',
#     'DYNATRACE_API_URL': 'fake',
#     'DYNATRACE_API_TOKEN': 'fake',
#     'DYNATRACE_SLO_ID': 'fake'
# }
# 
# def mock_sd(nresp=1):
#     """Fake Stackdriver Monitoring API response for the ListTimeSeries endpoint.
# 
#     Args:
#         nresp (int): Number of responses to add to response.
# 
#     Returns:
#         ChannelStub: Mocked gRPC channel stub.
#     """
#     timeserie = load_fixture('time_series_proto.json')
#     response = {"next_page_token": "", "time_series": [timeserie]}
#     return mock_grpc_stub(
#         response=response,
#         proto_method=metric_service_pb2.ListTimeSeriesResponse,
#         nresp=nresp)


# Path: tests/unit/test_cli.py
import os
import unittest
from mock import patch
from click.testing import CliRunner
from slo_generator.cli import main
from slo_generator.utils import load_config
from .test_stubs import CTX, mock_sd






cwd = os.path.dirname(os.path.abspath(__file__))
root = os.path.dirname(os.path.dirname(cwd))


class TestCLI(unittest.TestCase):

    def setUp(self):
        for key, value in CTX.items():
            os.environ[key] = value
        slo_config = f'{root}/samples/cloud_monitoring/slo_gae_app_availability.yaml'  # noqa: E501
        config = f'{root}/samples/config.yaml'
        self.slo_config = slo_config
        self.slo_metadata_name = load_config(slo_config,
                                             ctx=CTX)['metadata']['name']
        self.config = config
        self.cli = CliRunner()

    @patch('google.api_core.grpc_helpers.create_channel',
           return_value=mock_sd(8))
    def test_cli_compute(self, mock):
        args = ['compute', '-f', self.slo_config, '-c', self.config]
        result = self.cli.invoke(main, args)
        self.assertEqual(result.exit_code, 0)

    @patch('google.api_core.grpc_helpers.create_channel',

           return_value=mock_sd(40))