Coverage for frappe_manager / commands / ssl / dns_helpers.py: 14%

76 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-07-02 18:13 +0530

1"""Helper functions for DNS provider credential management.""" 

2 

3import typer 

4 

5from frappe_manager.logger.context import LoggerContext 

6from frappe_manager.metadata_manager import FMCloudflareConfig, FMConfigManager 

7from frappe_manager.output_manager import get_global_output_handler 

8from frappe_manager.site_manager.bench_config import DNSProviderConfig 

9from frappe_manager.site_manager.site import Bench 

10from frappe_manager.ssl_manager import DNS_PROVIDER 

11 

12from .helpers import get_output_handler 

13 

14 

15def _show_dns_credentials(ctx: typer.Context, provider_name: str, benchname: str | None = None): 

16 """Show DNS credentials for a provider.""" 

17 if benchname: 

18 # Show bench-level config 

19 services_manager = ctx.obj["services"] 

20 context = LoggerContext(bench=benchname, operation="dns-config-show") 

21 output = get_output_handler(ctx, context=context) 

22 logger = ctx.obj.get("logger") 

23 bench = Bench.get_object(benchname, services_manager, logger=logger, output_handler=output) 

24 

25 if bench.bench_config.dns_providers and provider_name in bench.bench_config.dns_providers: 

26 config = bench.bench_config.dns_providers[provider_name] 

27 output.print(f"\n[bold cyan]DNS Credentials for bench '{benchname}':[/bold cyan]", emoji_code="") 

28 output.print(f"Provider: [green]{provider_name}[/green]", emoji_code="") 

29 output.print(f"Email: {config.email if config.email else '[dim]Not set[/dim]'}", emoji_code="") 

30 output.print( 

31 f"API Token: {'[green]*** (set)[/green]' if config.api_token else '[dim]Not set[/dim]'}", 

32 emoji_code="", 

33 ) 

34 output.print( 

35 f"API Key: {'[yellow]*** (set)[/yellow]' if config.api_key else '[dim]Not set[/dim]'}", 

36 emoji_code="", 

37 ) 

38 else: 

39 output.print( 

40 f"\n[yellow]No {provider_name} credentials configured for bench '{benchname}'[/yellow]", 

41 emoji_code=":warning:", 

42 ) 

43 output.print("[dim]Falling back to global configuration (if any)[/dim]", emoji_code="") 

44 

45 # Show global config (always show, no output handler needed for global info display) 

46 fm_config = FMConfigManager.import_from_toml() 

47 output = get_global_output_handler() 

48 output.print("\n[bold cyan]Global DNS Credentials:[/bold cyan]") 

49 output.print(f"Provider: [green]{provider_name}[/green]") 

50 

51 if provider_name == DNS_PROVIDER.cloudflare.value: 

52 output.print(f"Email: {fm_config.cloudflare.email if fm_config.cloudflare.email else '[dim]Not set[/dim]'}") 

53 output.print( 

54 f"API Token: {'[green]*** (set)[/green]' if fm_config.cloudflare.api_token else '[dim]Not set[/dim]'}", 

55 ) 

56 output.print( 

57 f"API Key: {'[yellow]*** (set)[/yellow]' if fm_config.cloudflare.api_key else '[dim]Not set[/dim]'}", 

58 ) 

59 

60 

61def _remove_dns_credentials(ctx: typer.Context, provider_name: str, benchname: str | None = None): 

62 """Remove DNS credentials for a provider.""" 

63 if benchname: 

64 services_manager = ctx.obj["services"] 

65 context = LoggerContext(bench=benchname, operation="dns-config-remove") 

66 output = get_output_handler(ctx, context=context) 

67 logger = ctx.obj.get("logger") 

68 bench = Bench.get_object(benchname, services_manager, logger=logger, output_handler=output) 

69 

70 if bench.bench_config.dns_providers and provider_name in bench.bench_config.dns_providers: 

71 bench.bench_config.dns_providers.pop(provider_name) 

72 if not bench.bench_config.dns_providers: 

73 bench.bench_config.dns_providers = None 

74 bench.bench_config.export_to_toml(bench.bench_config.root_path) 

75 output.print( 

76 f"Removed [green]{provider_name}[/green] credentials for bench '{benchname}'", 

77 emoji_code=":white_check_mark:", 

78 ) 

79 else: 

80 output.warning(f"No {provider_name} credentials configured for bench '{benchname}'") 

81 else: 

82 # Remove global config 

83 fm_config = FMConfigManager.import_from_toml() 

84 

85 if provider_name == DNS_PROVIDER.cloudflare.value: 

86 fm_config.cloudflare = FMCloudflareConfig(email=None, api_token=None, api_key=None) 

87 

88 fm_config.export_to_toml() 

89 output = get_global_output_handler() 

90 output.print(f"✅ Removed global [green]{provider_name}[/green] credentials") 

91 

92 

93def _configure_dns_credentials( 

94 ctx: typer.Context, 

95 provider_name: str, 

96 benchname: str | None, 

97 api_token: str | None, 

98 api_key: str | None, 

99 email: str | None, 

100): 

101 """Configure DNS credentials for a provider.""" 

102 if benchname: 

103 services_manager = ctx.obj["services"] 

104 context = LoggerContext(bench=benchname, operation="dns-config") 

105 output = get_output_handler(ctx, context=context) 

106 logger = ctx.obj.get("logger") 

107 bench = Bench.get_object(benchname, services_manager, logger=logger, output_handler=output) 

108 

109 output.change_head(f"Configuring {provider_name} credentials for bench '{benchname}'") 

110 

111 if not bench.bench_config.dns_providers: 

112 bench.bench_config.dns_providers = {} 

113 

114 bench.bench_config.dns_providers[provider_name] = DNSProviderConfig( 

115 email=email, 

116 api_token=api_token, 

117 api_key=api_key, 

118 ) 

119 

120 # Save bench config 

121 bench.bench_config.export_to_toml(bench.bench_config.root_path) 

122 

123 output.print( 

124 f"[green]{provider_name}[/green] credentials configured for bench '{benchname}'", 

125 emoji_code=":white_check_mark:", 

126 ) 

127 output.print("[dim]These credentials will be used for DNS-01 challenges on this bench[/dim]", emoji_code="") 

128 output.print(f"[dim]Saved to: {bench.bench_config.root_path}[/dim]", emoji_code="") 

129 else: 

130 # Configure global credentials (use output handler for global operations) 

131 output = get_global_output_handler() 

132 output.change_head(f"Configuring global {provider_name} credentials") 

133 

134 fm_config = FMConfigManager.import_from_toml() 

135 

136 if provider_name == DNS_PROVIDER.cloudflare.value: 

137 fm_config.cloudflare = FMCloudflareConfig( 

138 email=email, 

139 api_token=api_token, 

140 api_key=api_key, 

141 ) 

142 

143 # Save global config 

144 fm_config.export_to_toml() 

145 

146 output.print(f"✅ Global [green]{provider_name}[/green] credentials configured") 

147 output.print("[dim]These credentials will be used by all benches unless overridden at bench level[/dim]") 

148 output.print("[dim]Saved to: ~/frappe/fm_config.toml[/dim]")