Skip to content

Commit 8afc58a

Browse files
committed
cirun auto connect azure
1 parent ad333b8 commit 8afc58a

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

cirun/cloud.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import subprocess
23

34
import typer
45
from rich.console import Console
@@ -24,8 +25,18 @@
2425
context_settings={"help_option_names": ["-h", "--help"]},
2526
)
2627

28+
cloud_create = typer.Typer(
29+
cls=OrderCommands,
30+
help="Create cloud provider credentials",
31+
add_completion=False,
32+
no_args_is_help=True,
33+
rich_markup_mode="rich",
34+
context_settings={"help_option_names": ["-h", "--help"]},
35+
)
36+
2737

2838
cloud_app.add_typer(cloud_connect, name="connect")
39+
cloud_app.add_typer(cloud_create, name="create")
2940

3041

3142
@cloud_connect.command()
@@ -106,6 +117,119 @@ def oracle(
106117
_connect_cloud(name="oracle", credentials=credentials)
107118

108119

120+
@cloud_create.command()
121+
def azure(
122+
name: str = typer.Option(
123+
None,
124+
"--name",
125+
help="Name for the service principal (optional, auto-generated if not provided)"
126+
),
127+
auto_connect: bool = typer.Option(
128+
False,
129+
"--auto-connect",
130+
help="Automatically connect the created credentials to Cirun"
131+
),
132+
):
133+
"""Create Azure Service Principal credentials for Cirun"""
134+
import time
135+
136+
console = Console()
137+
error_console = Console(stderr=True, style="bold red")
138+
139+
# Check if Azure CLI is installed
140+
try:
141+
subprocess.run(
142+
["az", "--version"],
143+
capture_output=True,
144+
check=True
145+
)
146+
except (subprocess.CalledProcessError, FileNotFoundError):
147+
error_console.print("Error: Azure CLI is not installed or not found in PATH")
148+
error_console.print("Install it from: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli")
149+
raise typer.Exit(code=1)
150+
151+
# Check if user is logged in and get account details
152+
console.print("[bold blue]Checking Azure CLI login status...[/bold blue]")
153+
try:
154+
result = subprocess.run(
155+
["az", "account", "show", "--output", "json"],
156+
capture_output=True,
157+
check=True,
158+
text=True
159+
)
160+
account_info = json.loads(result.stdout)
161+
except subprocess.CalledProcessError:
162+
error_console.print("Error: Not logged in to Azure CLI")
163+
error_console.print("Please run: az login")
164+
raise typer.Exit(code=1)
165+
166+
# Display account details
167+
console.print("\n[bold green]Azure Account Details:[/bold green]")
168+
console.print(f" Account Name: [bold]{account_info.get('user', {}).get('name', 'N/A')}[/bold]")
169+
console.print(f" Subscription Name: [bold]{account_info.get('name', 'N/A')}[/bold]")
170+
console.print(f" Subscription ID: [bold]{account_info.get('id', 'N/A')}[/bold]")
171+
console.print(f" Tenant ID: [bold]{account_info.get('tenantId', 'N/A')}[/bold]")
172+
console.print(f" State: [bold]{account_info.get('state', 'N/A')}[/bold]")
173+
console.print("")
174+
175+
subscription_id = account_info.get('id')
176+
177+
# Generate service principal name if not provided
178+
if not name:
179+
name = f"cirun-{int(time.time())}"
180+
181+
# Create service principal
182+
console.print(f"[bold blue]Creating service principal '[bold green]{name}[/bold green]'...[/bold blue]")
183+
try:
184+
result = subprocess.run(
185+
[
186+
"az", "ad", "sp", "create-for-rbac",
187+
"--name", name,
188+
"--role", "contributor",
189+
"--scopes", f"/subscriptions/{subscription_id}",
190+
"--output", "json"
191+
],
192+
capture_output=True,
193+
check=True,
194+
text=True
195+
)
196+
except subprocess.CalledProcessError as e:
197+
error_console.print(f"Error creating service principal: {e.stderr}")
198+
raise typer.Exit(code=1)
199+
200+
# Parse output
201+
sp_data = json.loads(result.stdout)
202+
client_id = sp_data.get("appId")
203+
client_secret = sp_data.get("password")
204+
tenant_id = sp_data.get("tenant")
205+
206+
# Display credentials
207+
success_console = Console(style="bold green")
208+
success_console.rule("[bold green]")
209+
success_console.print("[bold green]✓[/bold green] Service principal created successfully!")
210+
success_console.print("")
211+
success_console.print("[bold yellow]Azure Credentials for Cirun:[/bold yellow]")
212+
success_console.print("")
213+
success_console.print(f"AZURE_SUBSCRIPTION_ID: [bold]{subscription_id}[/bold]")
214+
success_console.print(f"AZURE_CLIENT_ID: [bold]{client_id}[/bold]")
215+
success_console.print(f"AZURE_CLIENT_SECRET: [bold]{client_secret}[/bold]")
216+
success_console.print(f"AZURE_TENANT_ID: [bold]{tenant_id}[/bold]")
217+
success_console.print("")
218+
success_console.print("[bold red]⚠️ Save the CLIENT_SECRET - it won't be shown again![/bold red]")
219+
success_console.rule("[bold green]")
220+
221+
# Auto-connect if requested
222+
if auto_connect:
223+
console.print("\n[bold blue]Connecting credentials to Cirun...[/bold blue]")
224+
credentials = {
225+
"subscription_id": subscription_id,
226+
"tenant_id": tenant_id,
227+
"client_id": client_id,
228+
"client_secret": client_secret,
229+
}
230+
_connect_cloud(name="azure", credentials=credentials)
231+
232+
109233
def _connect_cloud(name, credentials):
110234
cirun = Cirun()
111235
response_json = cirun.cloud_connect(

0 commit comments

Comments
 (0)