mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-28 04:19:41 -08:00
feat: parse azure config files
This commit is contained in:
parent
4ecf674e62
commit
ad5c77a61b
|
@ -8,11 +8,6 @@ sidebar_label: Azure
|
|||
|
||||
Display the currently active Azure subscription information.
|
||||
|
||||
:::caution
|
||||
PowerShell offers support for the `Az.Accounts` module, but it is disabled by default.
|
||||
To enable this, set `$env:AZ_ENABLED = $true` in your `$PROFILE`.
|
||||
:::
|
||||
|
||||
## Sample Configuration
|
||||
|
||||
```json
|
||||
|
@ -36,10 +31,6 @@ properties below - defaults to `{{.Name}}`
|
|||
|
||||
## Template Properties
|
||||
|
||||
:::caution
|
||||
When using the PowerShell module, only `.EnvironmentName`, `.ID`, `.Name` and `.User.Name` are available.
|
||||
:::
|
||||
|
||||
- `.EnvironmentName`: `string` - the account environment name
|
||||
- `.HomeTenantID`: `string` - the home tenant id
|
||||
- `.ID`: `string` - the account/subscription id
|
|
@ -15,10 +15,6 @@ $env:POWERLINE_COMMAND = "oh-my-posh"
|
|||
$env:CONDA_PROMPT_MODIFIER = $false
|
||||
|
||||
# specific module support (disabled by default)
|
||||
$omp_value = $env:AZ_ENABLED
|
||||
if ($null -eq $omp_value) {
|
||||
$env:AZ_ENABLED = $false
|
||||
}
|
||||
$omp_value = $env:POSH_GIT_ENABLED
|
||||
if ($null -eq $omp_value) {
|
||||
$env:POSH_GIT_ENABLED = $false
|
||||
|
@ -50,24 +46,6 @@ function global:Initialize-ModuleSupport {
|
|||
$global:GitStatus = Get-GitStatus
|
||||
$env:POSH_GIT_STATUS = Write-GitStatus -Status $global:GitStatus
|
||||
}
|
||||
|
||||
$env:AZ_ENVIRONMENT_NAME = $null
|
||||
$env:AZ_USER_NAME = $null
|
||||
$env:AZ_SUBSCRIPTION_ID = $null
|
||||
$env:AZ_ACCOUNT_NAME = $null
|
||||
|
||||
if ($env:AZ_ENABLED -eq $true) {
|
||||
try {
|
||||
$context = Get-AzContext
|
||||
if ($null -ne $context) {
|
||||
$env:AZ_ENVIRONMENT_NAME = $context.Environment.Name
|
||||
$env:AZ_USER_NAME = $context.Account.Id
|
||||
$env:AZ_SUBSCRIPTION_ID = $context.Subscription.Id
|
||||
$env:AZ_ACCOUNT_NAME = $context.Subscription.Name
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
}
|
||||
|
||||
[ScriptBlock]$Prompt = {
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -9,32 +10,75 @@ type az struct {
|
|||
props properties
|
||||
env environmentInfo
|
||||
|
||||
EnvironmentName string `json:"environmentName"`
|
||||
HomeTenantID string `json:"homeTenantId"`
|
||||
ID string `json:"id"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
Name string `json:"name"`
|
||||
State string `json:"state"`
|
||||
TenantID string `json:"tenantId"`
|
||||
User *AzureUser `json:"user"`
|
||||
AzureSubscription
|
||||
}
|
||||
|
||||
const (
|
||||
updateConsentNeeded = "Do you want to continue?"
|
||||
updateMessage = "AZ CLI: Update needed!"
|
||||
updateForeground = "#ffffff"
|
||||
updateBackground = "#ff5349"
|
||||
)
|
||||
type AzureConfig struct {
|
||||
Subscriptions []*AzureSubscription `json:"subscriptions"`
|
||||
InstallationID string `json:"installationId"`
|
||||
}
|
||||
|
||||
type AzureSubscription struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
State string `json:"state"`
|
||||
User *AzureUser `json:"user"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
TenantID string `json:"tenantId"`
|
||||
EnvironmentName string `json:"environmentName"`
|
||||
HomeTenantID string `json:"homeTenantId"`
|
||||
ManagedByTenants []interface{} `json:"managedByTenants"`
|
||||
}
|
||||
|
||||
type AzureUser struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AzurePowerShellConfig struct {
|
||||
DefaultContextKey string `json:"DefaultContextKey"`
|
||||
Contexts map[string]*AzurePowerShellSubscription `json:"Contexts"`
|
||||
}
|
||||
|
||||
type AzurePowerShellSubscription struct {
|
||||
Account struct {
|
||||
ID string `json:"Id"`
|
||||
Credential interface{} `json:"Credential"`
|
||||
Type string `json:"Type"`
|
||||
TenantMap struct {
|
||||
} `json:"TenantMap"`
|
||||
ExtendedProperties struct {
|
||||
Subscriptions string `json:"Subscriptions"`
|
||||
Tenants string `json:"Tenants"`
|
||||
HomeAccountID string `json:"HomeAccountId"`
|
||||
} `json:"ExtendedProperties"`
|
||||
} `json:"Account"`
|
||||
Tenant struct {
|
||||
ID string `json:"Id"`
|
||||
Directory interface{} `json:"Directory"`
|
||||
IsHome bool `json:"IsHome"`
|
||||
ExtendedProperties struct {
|
||||
} `json:"ExtendedProperties"`
|
||||
} `json:"Tenant"`
|
||||
Subscription struct {
|
||||
ID string `json:"Id"`
|
||||
Name string `json:"Name"`
|
||||
State string `json:"State"`
|
||||
ExtendedProperties struct {
|
||||
HomeTenant string `json:"HomeTenant"`
|
||||
AuthorizationSource string `json:"AuthorizationSource"`
|
||||
SubscriptionPolices string `json:"SubscriptionPolices"`
|
||||
Tenants string `json:"Tenants"`
|
||||
Account string `json:"Account"`
|
||||
Environment string `json:"Environment"`
|
||||
} `json:"ExtendedProperties"`
|
||||
} `json:"Subscription"`
|
||||
Environment struct {
|
||||
Name string `json:"Name"`
|
||||
} `json:"Environment"`
|
||||
}
|
||||
|
||||
func (a *az) string() string {
|
||||
if a != nil && a.Name == updateMessage {
|
||||
return updateMessage
|
||||
}
|
||||
segmentTemplate := a.props.getString(SegmentTemplate, "{{.Name}}")
|
||||
segmentTemplate := a.props.getString(SegmentTemplate, "{{ .EnvironmentName }}")
|
||||
template := &textTemplate{
|
||||
Template: segmentTemplate,
|
||||
Context: a,
|
||||
|
@ -52,52 +96,53 @@ func (a *az) init(props properties, env environmentInfo) {
|
|||
a.env = env
|
||||
}
|
||||
|
||||
func (a *az) enabled() bool {
|
||||
if a.getFromEnvVars() {
|
||||
return true
|
||||
}
|
||||
|
||||
return a.getFromAzCli()
|
||||
func (a *az) getFileContentWithoutBom(file string) string {
|
||||
const ByteOrderMark = "\ufeff"
|
||||
file = filepath.Join(a.env.homeDir(), file)
|
||||
config := a.env.getFileContent(file)
|
||||
return strings.TrimLeft(config, ByteOrderMark)
|
||||
}
|
||||
|
||||
func (a *az) getFromEnvVars() bool {
|
||||
environmentName := a.env.getenv("AZ_ENVIRONMENT_NAME")
|
||||
userName := a.env.getenv("AZ_USER_NAME")
|
||||
id := a.env.getenv("AZ_SUBSCRIPTION_ID")
|
||||
accountName := a.env.getenv("AZ_ACCOUNT_NAME")
|
||||
func (a *az) enabled() bool {
|
||||
return a.getAzureProfile() || a.getAzureRmContext()
|
||||
}
|
||||
|
||||
if userName == "" && environmentName == "" {
|
||||
func (a *az) getAzureProfile() bool {
|
||||
var content string
|
||||
if content = a.getFileContentWithoutBom(".azure/azureProfile.json"); len(content) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
a.EnvironmentName = environmentName
|
||||
a.Name = accountName
|
||||
a.ID = id
|
||||
a.User = &AzureUser{
|
||||
Name: userName,
|
||||
var config AzureConfig
|
||||
if err := json.Unmarshal([]byte(content), &config); err != nil {
|
||||
return false
|
||||
}
|
||||
for _, subscription := range config.Subscriptions {
|
||||
if subscription.IsDefault {
|
||||
a.AzureSubscription = *subscription
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *az) getAzureRmContext() bool {
|
||||
var content string
|
||||
if content = a.getFileContentWithoutBom(".azure/AzureRmContext.json"); len(content) == 0 {
|
||||
return false
|
||||
}
|
||||
var config AzurePowerShellConfig
|
||||
if err := json.Unmarshal([]byte(content), &config); err != nil {
|
||||
return false
|
||||
}
|
||||
defaultContext := config.Contexts[config.DefaultContextKey]
|
||||
if defaultContext == nil {
|
||||
return false
|
||||
}
|
||||
a.IsDefault = true
|
||||
a.EnvironmentName = defaultContext.Environment.Name
|
||||
a.TenantID = defaultContext.Tenant.ID
|
||||
a.ID = defaultContext.Subscription.ID
|
||||
a.Name = defaultContext.Subscription.Name
|
||||
a.State = defaultContext.Subscription.State
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *az) getFromAzCli() bool {
|
||||
cmd := "az"
|
||||
if !a.env.hasCommand(cmd) {
|
||||
return false
|
||||
}
|
||||
|
||||
output, _ := a.env.runCommand(cmd, "account", "show")
|
||||
if len(output) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.Contains(output, updateConsentNeeded) {
|
||||
a.props[ForegroundOverride] = updateForeground
|
||||
a.props[BackgroundOverride] = updateBackground
|
||||
a.Name = updateMessage
|
||||
return true
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(output), a)
|
||||
return err == nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -9,141 +10,59 @@ import (
|
|||
|
||||
func TestAzSegment(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedEnabled bool
|
||||
ExpectedString string
|
||||
EnvEnvironmentName string
|
||||
EnvUserName string
|
||||
AccountName string
|
||||
EnvSubscriptionID string
|
||||
CLIExists bool
|
||||
CLIEnvironmentname string
|
||||
CLISubscriptionID string
|
||||
CLIAccountName string
|
||||
CLIUserName string
|
||||
Template string
|
||||
Case string
|
||||
ExpectedEnabled bool
|
||||
ExpectedString string
|
||||
HasCLI bool
|
||||
HasPowerShell bool
|
||||
Template string
|
||||
}{
|
||||
{
|
||||
Case: "display account name",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "foobar",
|
||||
CLIExists: true,
|
||||
CLIEnvironmentname: "foo",
|
||||
CLISubscriptionID: "bar",
|
||||
CLIAccountName: "foobar",
|
||||
Template: "{{.Name}}",
|
||||
},
|
||||
{
|
||||
Case: "envvars present",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "foo$bar",
|
||||
EnvEnvironmentName: "foo",
|
||||
EnvUserName: "bar",
|
||||
CLIExists: false,
|
||||
Template: "{{.EnvironmentName}}${{.User.Name}}",
|
||||
},
|
||||
{
|
||||
Case: "envvar environment name present",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "foo",
|
||||
EnvEnvironmentName: "foo",
|
||||
CLIExists: false,
|
||||
Template: "{{.EnvironmentName}}",
|
||||
},
|
||||
{
|
||||
Case: "envvar user name present",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "bar",
|
||||
EnvUserName: "bar",
|
||||
CLIExists: false,
|
||||
Template: "{{.User.Name}}",
|
||||
},
|
||||
{
|
||||
Case: "envvar subscription id",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "foobar",
|
||||
EnvSubscriptionID: "foobar",
|
||||
EnvUserName: "bar",
|
||||
CLIExists: false,
|
||||
Template: "{{.ID}}",
|
||||
},
|
||||
{
|
||||
Case: "cli not found",
|
||||
Case: "no config files found",
|
||||
ExpectedEnabled: false,
|
||||
ExpectedString: "",
|
||||
CLIExists: false,
|
||||
},
|
||||
{
|
||||
Case: "cli contains data",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "foo$bar",
|
||||
CLIExists: true,
|
||||
CLIEnvironmentname: "foo",
|
||||
CLISubscriptionID: "bar",
|
||||
Template: "{{.EnvironmentName}}${{.ID}}",
|
||||
Case: "Az CLI Profile",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "AzureCliCloud",
|
||||
Template: "{{ .EnvironmentName }}",
|
||||
HasCLI: true,
|
||||
},
|
||||
{
|
||||
Case: "print only environment ame",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "foo",
|
||||
CLIExists: true,
|
||||
CLIEnvironmentname: "foo",
|
||||
CLISubscriptionID: "bar",
|
||||
Template: "{{.EnvironmentName}}",
|
||||
Case: "Az Pwsh Profile",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "AzurePoshCloud",
|
||||
Template: "{{ .EnvironmentName }}",
|
||||
HasPowerShell: true,
|
||||
},
|
||||
{
|
||||
Case: "print only id",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "bar",
|
||||
CLIExists: true,
|
||||
CLIEnvironmentname: "foo",
|
||||
CLISubscriptionID: "bar",
|
||||
Template: "{{.ID}}",
|
||||
},
|
||||
{
|
||||
Case: "print none",
|
||||
ExpectedEnabled: true,
|
||||
CLIExists: true,
|
||||
CLIEnvironmentname: "foo",
|
||||
CLISubscriptionID: "bar",
|
||||
},
|
||||
{
|
||||
Case: "update needed",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: updateMessage,
|
||||
CLIExists: true,
|
||||
CLIEnvironmentname: "Do you want to continue? (Y/n): Visual Studio Enterprise",
|
||||
Case: "Faulty template",
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: incorrectTemplate,
|
||||
Template: "{{ .Burp }}",
|
||||
HasPowerShell: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getenv", "AZ_ENVIRONMENT_NAME").Return(tc.EnvEnvironmentName)
|
||||
env.On("getenv", "AZ_USER_NAME").Return(tc.EnvUserName)
|
||||
env.On("getenv", "AZ_SUBSCRIPTION_ID").Return(tc.EnvSubscriptionID)
|
||||
env.On("getenv", "AZ_ACCOUNT_NAME").Return(tc.AccountName)
|
||||
env.On("hasCommand", "az").Return(tc.CLIExists)
|
||||
env.On("runCommand", "az", []string{"account", "show"}).Return(
|
||||
fmt.Sprintf(`{
|
||||
"environmentName": "%s",
|
||||
"homeTenantId": "8d934305-ac9f-46fe-b0e7-50fd32ad2acf",
|
||||
"id": "%s",
|
||||
"isDefault": true,
|
||||
"managedByTenants": [],
|
||||
"name": "%s",
|
||||
"state": "Enabled",
|
||||
"tenantId": "8d934305-ac9f-46fe-b0e7-50fd32ad2acf",
|
||||
"user": {
|
||||
"name": "%s",
|
||||
"type": "user"
|
||||
}
|
||||
}`, tc.CLIEnvironmentname, tc.CLISubscriptionID, tc.CLIAccountName, tc.CLIUserName),
|
||||
nil,
|
||||
)
|
||||
home := "/Users/posh"
|
||||
env.On("homeDir", nil).Return(home)
|
||||
var azureProfile, azureRmContext string
|
||||
if tc.HasCLI {
|
||||
content, _ := ioutil.ReadFile("./test/azureProfile.json")
|
||||
azureProfile = string(content)
|
||||
}
|
||||
if tc.HasPowerShell {
|
||||
content, _ := ioutil.ReadFile("./test/AzureRmContext.json")
|
||||
azureRmContext = string(content)
|
||||
}
|
||||
env.On("getFileContent", filepath.Join(home, ".azure/azureProfile.json")).Return(azureProfile)
|
||||
env.On("getFileContent", filepath.Join(home, ".azure/AzureRmContext.json")).Return(azureRmContext)
|
||||
|
||||
var props properties = map[Property]interface{}{
|
||||
SegmentTemplate: tc.Template,
|
||||
}
|
||||
|
||||
az := &az{
|
||||
env: env,
|
||||
props: props,
|
||||
|
|
81
src/test/AzureRmContext.json
Normal file
81
src/test/AzureRmContext.json
Normal file
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"DefaultContextKey": "My Azure Subscription (subscription_id) - tenant_id - user_name",
|
||||
"EnvironmentTable": {},
|
||||
"Contexts": {
|
||||
"My Azure Subscription (subscription_id) - tenant_id - user_name": {
|
||||
"Account": {
|
||||
"Id": "232-232-232-232",
|
||||
"Type": "User",
|
||||
"TenantMap": {},
|
||||
"ExtendedProperties": {
|
||||
"Subscriptions": "subscription_ids",
|
||||
"Tenants": "tenants_ids",
|
||||
"HomeAccountId": "tenants_ids"
|
||||
}
|
||||
},
|
||||
"Tenant": {
|
||||
"Id": "4777-4777-4777-4777",
|
||||
"Directory": null,
|
||||
"IsHome": true,
|
||||
"ExtendedProperties": {}
|
||||
},
|
||||
"Subscription": {
|
||||
"Id": "97hkk-97hkk-97hkk-97hkk",
|
||||
"Name": "AzurePosh",
|
||||
"State": "Poshfull",
|
||||
"ExtendedProperties": {
|
||||
"HomeTenant": "688ab8f8-d8d8-4c8b-b8b8-b8b8b8b8b8b8",
|
||||
"AuthorizationSource": "Legacy",
|
||||
"SubscriptionPolices": "{\"locationPlacementId\":\"Public_2014-09-01\",\"quotaId\":\"MSDN_2014-09-01\",\"spendingLimit\":\"On\"}",
|
||||
"Tenants": "4777-4777-4777-4777",
|
||||
"Account": "Bill",
|
||||
"Environment": "AzurePoshCloud"
|
||||
}
|
||||
},
|
||||
"Environment": {
|
||||
"Name": "AzurePoshCloud",
|
||||
"Type": "Built-in",
|
||||
"OnPremise": false,
|
||||
"ServiceManagementUrl": "https://management.core.windows.net/",
|
||||
"ResourceManagerUrl": "https://management.azure.com/",
|
||||
"ManagementPortalUrl": "https://portal.azure.com/",
|
||||
"PublishSettingsFileUrl": "https://go.microsoft.com/fwlink/?LinkID=301775",
|
||||
"ActiveDirectoryAuthority": "https://login.microsoftonline.com/",
|
||||
"GalleryUrl": "https://gallery.azure.com/",
|
||||
"GraphUrl": "https://graph.windows.net/",
|
||||
"ActiveDirectoryServiceEndpointResourceId": "https://management.core.windows.net/",
|
||||
"StorageEndpointSuffix": "core.windows.net",
|
||||
"SqlDatabaseDnsSuffix": ".database.windows.net",
|
||||
"TrafficManagerDnsSuffix": "trafficmanager.net",
|
||||
"AzureKeyVaultDnsSuffix": "vault.azure.net",
|
||||
"AzureKeyVaultServiceEndpointResourceId": "https://vault.azure.net",
|
||||
"GraphEndpointResourceId": "https://graph.windows.net/",
|
||||
"DataLakeEndpointResourceId": "https://datalake.azure.net/",
|
||||
"BatchEndpointResourceId": "https://batch.core.windows.net/",
|
||||
"AzureDataLakeAnalyticsCatalogAndJobEndpointSuffix": "azuredatalakeanalytics.net",
|
||||
"AzureDataLakeStoreFileSystemEndpointSuffix": "azuredatalakestore.net",
|
||||
"AdTenant": "Common",
|
||||
"ContainerRegistryEndpointSuffix": "azurecr.io",
|
||||
"VersionProfiles": [],
|
||||
"ExtendedProperties": {
|
||||
"OperationalInsightsEndpoint": "https://api.loganalytics.io/v1",
|
||||
"OperationalInsightsEndpointResourceId": "https://api.loganalytics.io",
|
||||
"AzureAnalysisServicesEndpointSuffix": "asazure.windows.net",
|
||||
"AnalysisServicesEndpointResourceId": "https://region.asazure.windows.net",
|
||||
"AzureAttestationServiceEndpointSuffix": "attest.azure.net",
|
||||
"AzureAttestationServiceEndpointResourceId": "https://attest.azure.net",
|
||||
"AzureSynapseAnalyticsEndpointSuffix": "dev.azuresynapse.net",
|
||||
"AzureSynapseAnalyticsEndpointResourceId": "https://dev.azuresynapse.net",
|
||||
"ManagedHsmServiceEndpointResourceId": "https://managedhsm.azure.net",
|
||||
"ManagedHsmServiceEndpointSuffix": "managedhsm.azure.net",
|
||||
"MicrosoftGraphEndpointResourceId": "https://graph.microsoft.com/",
|
||||
"MicrosoftGraphUrl": "https://graph.microsoft.com"
|
||||
}
|
||||
},
|
||||
"VersionProfile": null,
|
||||
"TokenCache": { "CacheData": null },
|
||||
"ExtendedProperties": {}
|
||||
}
|
||||
},
|
||||
"ExtendedProperties": {}
|
||||
}
|
16
src/test/azureProfile.json
Normal file
16
src/test/azureProfile.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"installationId": "8d2919ac-a393-11eb-9100-acde48001122",
|
||||
"subscriptions": [
|
||||
{
|
||||
"id": "g51ds77-a393-11eb-9100-acde48001122",
|
||||
"name": "AzureCli",
|
||||
"state": "Powerfull",
|
||||
"user": { "name": "Melinda", "type": "user" },
|
||||
"isDefault": true,
|
||||
"tenantId": "6js98d-a393-11eb-9100-acde48001122",
|
||||
"environmentName": "AzureCliCloud",
|
||||
"homeTenantId": "8d934305-ac9f-46fe-b0e7-50fd32ad2acf",
|
||||
"managedByTenants": []
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue