Coverage for cli / main.py: 100.00%

71 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-10-28 16:19 +0000

1""" 

2GCO CLI - Main entry point. 

3 

4A comprehensive CLI for managing GCO multi-region EKS clusters. 

5 

6Commands: 

7 gco stacks deploy-all -y # Deploy all infrastructure 

8 gco jobs submit-sqs job.yaml -r us-east-1 # Submit job via SQS (recommended) 

9 gco jobs submit job.yaml -n gco-jobs # Submit job via API Gateway 

10 gco jobs list --all-regions # List jobs across regions 

11 gco capacity check -i g4dn.xlarge # Check GPU capacity 

12 gco inference deploy my-llm -i ... # Deploy inference endpoint 

13 gco stacks destroy-all -y # Tear down everything 

14 

15Full reference: docs/CLI.md 

16""" 

17 

18import logging 

19import os 

20 

21import click 

22 

23from . import __version__ 

24from .commands import ( 

25 analytics, 

26 autopilot, 

27 capacity, 

28 cluster, 

29 config_cmd, 

30 costs, 

31 crossplane, 

32 dag, 

33 deps, 

34 examples, 

35 files, 

36 gitops, 

37 images, 

38 inference, 

39 jobs, 

40 mission_cmd, 

41 models, 

42 monitoring, 

43 nodepools, 

44 queue, 

45 release, 

46 slurm, 

47 stacks, 

48 status, 

49 storage, 

50 swarm_cmd, 

51 tasks, 

52 templates, 

53 upgrade, 

54 vector, 

55 webhooks, 

56) 

57from .config import get_config 

58from .output import StructuredOutputGroup 

59 

60 

61def _configure_cli_logging(verbose: bool) -> None: 

62 """ 

63 Configure logging for the CLI. 

64 

65 By default, the CLI is quiet: only WARNING and above from our own code, 

66 and the chatty AWS SDK / HTTP stack loggers (``botocore``, ``boto3``, 

67 ``urllib3``, ``s3transfer``, ``kubernetes``) are pinned at WARNING so 

68 credential-discovery INFO messages and retry-attempt INFO messages don't 

69 clutter normal output. 

70 

71 ``--verbose`` / ``-v`` (or ``GCO_LOG_LEVEL=DEBUG``) turns on DEBUG for 

72 everything, which is the right escape hatch when something is actually 

73 wrong and you need to see what the SDK is doing. 

74 

75 This function also calls ``logging.basicConfig`` with ``force=True`` so 

76 it overrides any ``basicConfig`` that might have been called at import 

77 time by a library module (the CLI owns its log configuration). 

78 """ 

79 env_level = os.environ.get("GCO_LOG_LEVEL") 

80 if verbose or (env_level and env_level.upper() == "DEBUG"): 

81 level = logging.DEBUG 

82 elif env_level: 

83 level = getattr(logging, env_level.upper(), logging.WARNING) 

84 else: 

85 level = logging.WARNING 

86 

87 logging.basicConfig( 

88 level=level, 

89 format="%(asctime)s %(levelname)s %(name)s: %(message)s", 

90 force=True, 

91 ) 

92 

93 # Pin noisy third-party loggers even when we're at DEBUG, unless the 

94 # user explicitly asked for verbose output. This keeps ``-v`` useful 

95 # for seeing OUR logs without being drowned by boto's retry chatter. 

96 third_party_level = logging.DEBUG if verbose else logging.WARNING 

97 for name in ("botocore", "boto3", "urllib3", "s3transfer", "kubernetes"): 

98 logging.getLogger(name).setLevel(third_party_level) 

99 

100 

101@click.group(cls=StructuredOutputGroup) 

102@click.version_option(version=__version__, prog_name="gco") 

103@click.option("--config", "-c", "config_file", help="Path to config file") 

104@click.option("--region", "-r", "default_region", help="Default AWS region") 

105@click.option( 

106 "--output", 

107 "-o", 

108 "output_format", 

109 type=click.Choice(["table", "json", "yaml"]), 

110 default=None, 

111 help="Output format (defaults to the configured value)", 

112) 

113@click.option("--verbose", "-v", is_flag=True, default=None, help="Verbose output") 

114@click.option( 

115 "--regional-api/--global-api", 

116 default=None, 

117 help="Use regional API endpoints, or explicitly use the global endpoint", 

118) 

119@click.pass_context 

120def cli( 

121 ctx: click.Context, 

122 config_file: str | None, 

123 default_region: str | None, 

124 output_format: str | None, 

125 verbose: bool | None, 

126 regional_api: bool | None, 

127) -> None: 

128 """GCO CLI - Manage multi-region EKS clusters for AI/ML workloads.""" 

129 config = get_config(config_file) 

130 

131 if default_region: 

132 config.default_region = default_region 

133 if output_format: 

134 config.output_format = output_format 

135 if verbose is not None: 

136 config.verbose = verbose 

137 if regional_api is not None: 

138 config.use_regional_api = regional_api 

139 

140 _configure_cli_logging(config.verbose) 

141 ctx.obj = config 

142 

143 

144# Register command groups 

145cli.add_command(autopilot) 

146cli.add_command(jobs) 

147cli.add_command(dag) 

148cli.add_command(deps) 

149cli.add_command(queue) 

150cli.add_command(release) 

151cli.add_command(examples) 

152cli.add_command(templates) 

153cli.add_command(webhooks) 

154cli.add_command(capacity) 

155cli.add_command(cluster) 

156cli.add_command(inference) 

157cli.add_command(images) 

158cli.add_command(models) 

159cli.add_command(nodepools) 

160cli.add_command(costs) 

161cli.add_command(stacks) 

162cli.add_command(storage) 

163cli.add_command(files) 

164cli.add_command(config_cmd) 

165cli.add_command(analytics) 

166cli.add_command(monitoring) 

167cli.add_command(gitops) 

168cli.add_command(crossplane) 

169cli.add_command(tasks) 

170cli.add_command(mission_cmd) 

171cli.add_command(swarm_cmd) 

172cli.add_command(vector) 

173cli.add_command(status) 

174cli.add_command(upgrade) 

175cli.add_command(slurm) 

176 

177 

178def main() -> None: 

179 """Main entry point for the CLI.""" 

180 cli(obj=None) 

181 

182 

183if __name__ == "__main__": 

184 main()