Compare commits

...

51 Commits

Author SHA1 Message Date
swapnil-signoz
9bd65cd2d8 Merge branch 'main' into feat/cloudintegration-azure-dashboards 2026-04-24 21:01:15 +05:30
swapnil-signoz
9fd8b94372 feat: adding dashboards for azure 2026-04-24 20:59:50 +05:30
swapnil-signoz
2f1f7bf0e3 Merge branch 'main' into feat/cloudintegration-azure-impl 2026-04-24 18:14:07 +05:30
swapnil-signoz
e896054c60 refactor: using template for Azure connection artifact creation and update tests 2026-04-24 18:12:23 +05:30
swapnil-signoz
df5c91f78c feat: implement Azure connection commands and add unit tests 2026-04-24 17:26:31 +05:30
swapnil-signoz
c7f656bf5b Merge branch 'main' into feat/cloudintegration-azure-impl 2026-04-24 00:31:20 +05:30
swapnil-signoz
8533a85dcf refactor: adding missing case for azure service update 2026-04-23 23:36:24 +05:30
swapnil-signoz
bc49a19f15 Merge branch 'main' into feat/cloudintegration-azure-impl 2026-04-23 23:02:01 +05:30
swapnil-signoz
bb16d92176 Merge branch 'feat/cloudintegration-azure-service-def' into feat/cloudintegration-azure-impl 2026-04-23 23:01:14 +05:30
swapnil-signoz
2efa776de2 Merge branch 'main' into feat/cloudintegration-azure-service-def 2026-04-23 20:39:17 +05:30
swapnil-signoz
97d4f29d3a Merge branch 'feat/cloudintegration-azure-service-def' into feat/cloudintegration-azure-impl 2026-04-23 01:34:51 +05:30
swapnil-signoz
7aa720a6e1 Merge branch 'feat/cloudintegration-azure-types' into feat/cloudintegration-azure-service-def 2026-04-23 01:34:32 +05:30
swapnil-signoz
1296ae627d refactor: updating types 2026-04-23 01:34:10 +05:30
swapnil-signoz
4771391b9d Merge branch 'feat/cloudintegration-azure-impl' of https://github.com/SigNoz/signoz into feat/cloudintegration-azure-impl 2026-04-22 23:56:55 +05:30
swapnil-signoz
79e6485379 refactor: updating deny settings mode 2026-04-22 23:56:39 +05:30
swapnil-signoz
69f0508b15 Merge branch 'main' into feat/cloudintegration-azure-impl 2026-04-22 22:57:19 +05:30
swapnil-signoz
481e94e5d2 fix: update integration account ID and add agent version to Azure CLI and PowerShell commands 2026-04-22 19:33:20 +05:30
swapnil-signoz
4eadc17fd1 Merge branch 'feat/cloudintegration-azure-service-def' into feat/cloudintegration-azure-impl 2026-04-22 17:48:18 +05:30
swapnil-signoz
2acee1a8eb refactor: updating service defs 2026-04-22 17:47:34 +05:30
swapnil-signoz
f3c9129fa6 Merge branch 'feat/cloudintegration-azure-types' into feat/cloudintegration-azure-service-def 2026-04-22 17:43:16 +05:30
swapnil-signoz
3ab42a9012 refactor: update Azure service identifiers 2026-04-22 17:42:23 +05:30
swapnil-signoz
f870efbdac Merge branch 'feat/cloudintegration-azure-service-def' into feat/cloudintegration-azure-impl 2026-04-22 14:43:08 +05:30
swapnil-signoz
5068f412e6 Merge branch 'feat/cloudintegration-azure-types' into feat/cloudintegration-azure-service-def 2026-04-22 14:42:10 +05:30
swapnil-signoz
7f5d1d8ddb refactor: updating azure blob storage service name 2026-04-22 14:41:02 +05:30
swapnil-signoz
a81501bd87 refactor: updating blob storage service name 2026-04-22 14:39:37 +05:30
swapnil-signoz
06cc2b71c6 refactor: updating connection artifact struct 2026-04-22 14:28:05 +05:30
swapnil-signoz
2a23522510 Merge branch 'feat/cloudintegration-azure-service-def' into feat/cloudintegration-azure-impl 2026-04-22 13:58:58 +05:30
swapnil-signoz
f3dfff6de1 refactor: updating telemetry strategy 2026-04-22 13:58:16 +05:30
swapnil-signoz
841c928b90 Merge branch 'feat/cloudintegration-azure-types' into feat/cloudintegration-azure-service-def 2026-04-22 13:53:10 +05:30
swapnil-signoz
e3374d0bf3 refactor: updating strategy struct 2026-04-22 13:52:30 +05:30
swapnil-signoz
a7cd98dd8f feat: wip 2026-04-22 13:46:16 +05:30
swapnil-signoz
2714ded0b5 fix: handle optional connection URL in AWS integration 2026-04-22 01:45:56 +05:30
swapnil-signoz
c54513c327 Merge branch 'main' into feat/cloudintegration-azure-types 2026-04-22 01:44:25 +05:30
swapnil-signoz
7050a9a841 refactor: updating command key 2026-04-20 22:05:42 +05:30
swapnil-signoz
aea5447f55 Merge branch 'feat/cloudintegration-azure-types' into feat/cloudintegration-azure-service-def 2026-04-20 18:48:05 +05:30
swapnil-signoz
d65628d989 Merge branch 'main' into feat/cloudintegration-azure-types 2026-04-20 18:47:53 +05:30
swapnil-signoz
2d96ea84e5 Merge branch 'feat/cloudintegration-azure-types' into feat/cloudintegration-azure-service-def 2026-04-20 18:43:04 +05:30
swapnil-signoz
ff38502517 Merge branch 'main' into feat/cloudintegration-azure-types 2026-04-20 16:32:34 +05:30
swapnil-signoz
e50d0684b3 refactor: updating definitions with metrics and strategy 2026-04-20 15:01:39 +05:30
swapnil-signoz
6463029786 refactor: update service names for Azure Blob Storage telemetry 2026-04-20 15:01:39 +05:30
swapnil-signoz
806108d7b6 feat: adding service definitions for azure 2026-04-20 15:01:39 +05:30
swapnil-signoz
617afeb64b refactor: lint issues 2026-04-20 15:01:26 +05:30
swapnil-signoz
3737905670 feat: completing azure types 2026-04-20 14:37:49 +05:30
swapnil-signoz
54c79642f5 refactor: updating azure integration config 2026-04-20 11:19:41 +05:30
swapnil-signoz
0682c528da refactor: updating omitempty tags 2026-04-20 10:26:08 +05:30
swapnil-signoz
3377bc8a2b feat: adding azure services 2026-04-20 09:51:43 +05:30
swapnil-signoz
3b0d5dcf0e feat: adding cloud integration azure types 2026-04-19 19:20:06 +05:30
swapnil-signoz
aa8c4471dc refactor: using upper case key for AWS 2026-04-19 00:49:02 +05:30
swapnil-signoz
04b8ef4d86 refactor: separating cloud provider types 2026-04-19 00:24:13 +05:30
swapnil-signoz
9aee83607f Merge branch 'main' into refactor/cloudprovider-types-separation 2026-04-19 00:17:15 +05:30
swapnil-signoz
d8abbce47e refactor: moving types to cloud provider specific namespace/pkg 2026-04-17 11:57:41 +05:30
11 changed files with 3896 additions and 12 deletions

View File

@@ -167,7 +167,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
if err != nil {
return nil, err
}
azureCloudProviderModule := implcloudprovider.NewAzureCloudProvider()
azureCloudProviderModule := implcloudprovider.NewAzureCloudProvider(defStore)
cloudProvidersMap := map[cloudintegrationtypes.CloudProviderType]cloudintegration.CloudProviderModule{
cloudintegrationtypes.CloudProviderTypeAWS: awsCloudProviderModule,
cloudintegrationtypes.CloudProviderTypeAzure: azureCloudProviderModule,

View File

@@ -18,6 +18,7 @@ func NewAWSCloudProvider(defStore cloudintegrationtypes.ServiceDefinitionStore)
return &awscloudprovider{serviceDefinitions: defStore}, nil
}
// TODO: move URL construction logic to cloudintegrationtypes and add unit tests for it.
func (provider *awscloudprovider) GetConnectionArtifact(ctx context.Context, account *cloudintegrationtypes.Account, req *cloudintegrationtypes.GetConnectionArtifactRequest) (*cloudintegrationtypes.ConnectionArtifact, error) {
baseURL := fmt.Sprintf(cloudintegrationtypes.CloudFormationQuickCreateBaseURL.StringValue(), req.Config.AWS.DeploymentRegion)
u, _ := url.Parse(baseURL)

View File

@@ -2,27 +2,48 @@ package implcloudprovider
import (
"context"
"sort"
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
"github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
)
type azurecloudprovider struct{}
type azurecloudprovider struct {
serviceDefinitions cloudintegrationtypes.ServiceDefinitionStore
}
func NewAzureCloudProvider() cloudintegration.CloudProviderModule {
return &azurecloudprovider{}
func NewAzureCloudProvider(defStore cloudintegrationtypes.ServiceDefinitionStore) cloudintegration.CloudProviderModule {
return &azurecloudprovider{
serviceDefinitions: defStore,
}
}
func (provider *azurecloudprovider) GetConnectionArtifact(ctx context.Context, account *cloudintegrationtypes.Account, req *cloudintegrationtypes.GetConnectionArtifactRequest) (*cloudintegrationtypes.ConnectionArtifact, error) {
panic("implement me")
connectionArtifact, err := cloudintegrationtypes.NewAzureConnectionArtifact(account.ID, req.Config.AgentVersion, req.Credentials, req.Config.Azure)
if err != nil {
return nil, err
}
return &cloudintegrationtypes.ConnectionArtifact{
Azure: connectionArtifact,
}, nil
}
func (provider *azurecloudprovider) ListServiceDefinitions(ctx context.Context) ([]*cloudintegrationtypes.ServiceDefinition, error) {
panic("implement me")
return provider.serviceDefinitions.List(ctx, cloudintegrationtypes.CloudProviderTypeAzure)
}
func (provider *azurecloudprovider) GetServiceDefinition(ctx context.Context, serviceID cloudintegrationtypes.ServiceID) (*cloudintegrationtypes.ServiceDefinition, error) {
panic("implement me")
serviceDef, err := provider.serviceDefinitions.Get(ctx, cloudintegrationtypes.CloudProviderTypeAzure, serviceID)
if err != nil {
return nil, err
}
// override cloud integration dashboard id.
for index, dashboard := range serviceDef.Assets.Dashboards {
serviceDef.Assets.Dashboards[index].ID = cloudintegrationtypes.GetCloudIntegrationDashboardID(cloudintegrationtypes.CloudProviderTypeAzure, serviceID.StringValue(), dashboard.ID)
}
return serviceDef, nil
}
func (provider *azurecloudprovider) BuildIntegrationConfig(
@@ -30,5 +51,56 @@ func (provider *azurecloudprovider) BuildIntegrationConfig(
account *cloudintegrationtypes.Account,
services []*cloudintegrationtypes.StorableCloudIntegrationService,
) (*cloudintegrationtypes.ProviderIntegrationConfig, error) {
panic("implement me")
sort.Slice(services, func(i, j int) bool {
return services[i].Type.StringValue() < services[j].Type.StringValue()
})
var strategies []*cloudintegrationtypes.AzureTelemetryCollectionStrategy
for _, storedSvc := range services {
svcCfg, err := cloudintegrationtypes.NewServiceConfigFromJSON(cloudintegrationtypes.CloudProviderTypeAzure, storedSvc.Config)
if err != nil {
return nil, err
}
svcDef, err := provider.GetServiceDefinition(ctx, storedSvc.Type)
if err != nil {
return nil, err
}
strategy := svcDef.TelemetryCollectionStrategy.Azure
if strategy == nil {
continue
}
logsEnabled := svcCfg.IsLogsEnabled(cloudintegrationtypes.CloudProviderTypeAzure)
metricsEnabled := svcCfg.IsMetricsEnabled(cloudintegrationtypes.CloudProviderTypeAzure)
if !logsEnabled && !metricsEnabled {
continue
}
entry := &cloudintegrationtypes.AzureTelemetryCollectionStrategy{
ResourceProvider: strategy.ResourceProvider,
ResourceType: strategy.ResourceType,
}
if metricsEnabled && strategy.Metrics != nil {
entry.Metrics = strategy.Metrics
}
if logsEnabled && strategy.Logs != nil {
entry.Logs = strategy.Logs
}
strategies = append(strategies, entry)
}
return &cloudintegrationtypes.ProviderIntegrationConfig{
Azure: cloudintegrationtypes.NewAzureIntegrationConfig(
account.Config.Azure.DeploymentRegion,
account.Config.Azure.ResourceGroups,
strategies,
),
}, nil
}

View File

@@ -429,9 +429,13 @@ func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[strin
stats["cloudintegration.aws.connectedaccounts.count"] = awsAccountsCount
}
// NOTE: not adding stats for services for now.
// get connected accounts for Azure
azureAccountsCount, err := module.store.CountConnectedAccounts(ctx, orgID, cloudintegrationtypes.CloudProviderTypeAzure)
if err == nil {
stats["cloudintegration.azure.connectedaccounts.count"] = azureAccountsCount
}
// TODO: add more cloud providers when supported
// NOTE: not adding stats for services for now.
return stats, nil
}

View File

@@ -134,6 +134,24 @@
"unit": "Count",
"type": "Gauge",
"description": ""
},
{
"name": "azure_webapplicationfirewallcaptcharequestcount_total",
"unit": "Count",
"type": "Gauge",
"description": ""
},
{
"name": "azure_webapplicationfirewalljsrequestcount_total",
"unit": "Count",
"type": "Gauge",
"description": ""
},
{
"name": "azure_websocketconnections_total",
"unit": "Count",
"type": "Gauge",
"description": ""
}
],
"logs": [

View File

@@ -440,3 +440,4 @@ func (handler *handler) AgentCheckIn(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusOK, cloudintegrationtypes.NewGettableAgentCheckIn(provider, resp))
}

View File

@@ -1,5 +1,39 @@
package cloudintegrationtypes
import (
"bytes"
"fmt"
"text/template"
"github.com/SigNoz/signoz/pkg/valuer"
)
var (
AgentArmTemplateStorePath = "https://signoz-integrations.s3.us-east-1.amazonaws.com/azure-arm-template-%s.json"
AgentDeploymentStackName = "signoz-integration"
// Default values for fixed ARM template parameters.
armDefaultRgName = "signoz-integration-rg"
armDefaultContainerEnvName = "signoz-integration-agent-env"
armDefaultDeploymentEnv = "production"
// ARM template parameter key names used in both CLI and PowerShell deployment commands.
armParamLocation = "location"
armParamSignozAPIKey = "signozApiKey"
armParamSignozAPIUrl = "signozApiUrl"
armParamSignozIngestionURL = "signozIngestionUrl"
armParamSignozIngestionKey = "signozIngestionKey"
armParamAccountID = "signozIntegrationAccountId"
armParamAgentVersion = "signozIntegrationAgentVersion"
armParamRgName = "rgName"
armParamContainerEnvName = "containerEnvName"
armParamDeploymentEnv = "deploymentEnv"
// command templates.
azureCLITemplate = template.Must(template.New("azureCLI").Parse(azureCLITemplateStr()))
azurePowerShellTemplate = template.Must(template.New("azurePS").Parse(azurePowerShellTemplateStr()))
)
type AzureAccountConfig struct {
DeploymentRegion string `json:"deploymentRegion" required:"true"`
ResourceGroups []string `json:"resourceGroups" required:"true" nullable:"false"`
@@ -51,6 +85,36 @@ type AzureIntegrationConfig struct {
TelemetryCollectionStrategy []*AzureTelemetryCollectionStrategy `json:"telemetryCollectionStrategy" required:"true" nullable:"false"`
}
// azureTemplateData is the data struct passed to both command templates.
// All fields are exported so text/template can access them.
type azureTemplateData struct {
// Deploy parameter values.
TemplateURL string
Location string
SignozAPIKey string
SignozAPIUrl string
SignozIngestionURL string
SignozIngestionKey string
AccountID string
AgentVersion string
// ARM parameter key names (from package-level vars).
StackName string
ParamLocation string
ParamSignozAPIKey string
ParamSignozAPIUrl string
ParamSignozIngestionURL string
ParamSignozIngestionKey string
ParamAccountID string
ParamAgentVersion string
ParamRgName string
ParamContainerEnvName string
ParamDeploymentEnv string
// Fixed default values.
DefaultRgName string
DefaultContainerEnvName string
DefaultDeploymentEnv string
}
func NewAzureIntegrationConfig(
deploymentRegion string,
resourceGroups []string,
@@ -62,3 +126,105 @@ func NewAzureIntegrationConfig(
TelemetryCollectionStrategy: strategies,
}
}
func NewAzureConnectionArtifact(
accountID valuer.UUID,
agentVersion string,
creds *Credentials,
cfg *AzurePostableAccountConfig,
) (*AzureConnectionArtifact, error) {
data := azureTemplateData{
TemplateURL: fmt.Sprintf(AgentArmTemplateStorePath, agentVersion),
Location: cfg.DeploymentRegion,
SignozAPIKey: creds.SigNozAPIKey,
SignozAPIUrl: creds.SigNozAPIURL,
SignozIngestionURL: creds.IngestionURL,
SignozIngestionKey: creds.IngestionKey,
AccountID: accountID.StringValue(),
AgentVersion: agentVersion,
StackName: AgentDeploymentStackName,
ParamLocation: armParamLocation,
ParamSignozAPIKey: armParamSignozAPIKey,
ParamSignozAPIUrl: armParamSignozAPIUrl,
ParamSignozIngestionURL: armParamSignozIngestionURL,
ParamSignozIngestionKey: armParamSignozIngestionKey,
ParamAccountID: armParamAccountID,
ParamAgentVersion: armParamAgentVersion,
ParamRgName: armParamRgName,
ParamContainerEnvName: armParamContainerEnvName,
ParamDeploymentEnv: armParamDeploymentEnv,
DefaultRgName: armDefaultRgName,
DefaultContainerEnvName: armDefaultContainerEnvName,
DefaultDeploymentEnv: armDefaultDeploymentEnv,
}
cliCommand, err := newAzureConnectionCLICommand(data)
if err != nil {
return nil, err
}
psCommand, err := newAzureConnectionPowerShellCommand(data)
if err != nil {
return nil, err
}
return &AzureConnectionArtifact{
CLICommand: cliCommand,
CloudPowerShellCommand: psCommand,
}, nil
}
func newAzureConnectionCLICommand(data azureTemplateData) (string, error) {
var buf bytes.Buffer
err := azureCLITemplate.Execute(&buf, data)
if err != nil {
return "", err
}
return buf.String(), nil
}
func newAzureConnectionPowerShellCommand(data azureTemplateData) (string, error) {
var buf bytes.Buffer
err := azurePowerShellTemplate.Execute(&buf, data)
if err != nil {
return "", err
}
return buf.String(), nil
}
func azureCLITemplateStr() string {
return `az stack sub create \
--name {{.StackName}} \
--location {{.Location}} \
--template-uri {{.TemplateURL}} \
--parameters \
{{.ParamLocation}}='{{.Location}}' \
{{.ParamSignozAPIKey}}='{{.SignozAPIKey}}' \
{{.ParamSignozAPIUrl}}='{{.SignozAPIUrl}}' \
{{.ParamSignozIngestionURL}}='{{.SignozIngestionURL}}' \
{{.ParamSignozIngestionKey}}='{{.SignozIngestionKey}}' \
{{.ParamAccountID}}='{{.AccountID}}' \
{{.ParamAgentVersion}}='{{.AgentVersion}}' \
--action-on-unmanage deleteAll \
--deny-settings-mode denyDelete`
}
func azurePowerShellTemplateStr() string {
return "New-AzSubscriptionDeploymentStack `\n" +
" -Name \"{{.StackName}}\" `\n" +
" -Location \"{{.Location}}\" `\n" +
" -TemplateUri \"{{.TemplateURL}}\" `\n" +
" -TemplateParameterObject @{\n" +
" {{.ParamLocation}} = \"{{.Location}}\"\n" +
" {{.ParamSignozAPIKey}} = \"{{.SignozAPIKey}}\"\n" +
" {{.ParamSignozAPIUrl}} = \"{{.SignozAPIUrl}}\"\n" +
" {{.ParamSignozIngestionURL}} = \"{{.SignozIngestionURL}}\"\n" +
" {{.ParamSignozIngestionKey}} = \"{{.SignozIngestionKey}}\"\n" +
" {{.ParamAccountID}} = \"{{.AccountID}}\"\n" +
" {{.ParamAgentVersion}} = \"{{.AgentVersion}}\"\n" +
" {{.ParamRgName}} = \"{{.DefaultRgName}}\"\n" +
" {{.ParamContainerEnvName}} = \"{{.DefaultContainerEnvName}}\"\n" +
" {{.ParamDeploymentEnv}} = \"{{.DefaultDeploymentEnv}}\"\n" +
" } `\n" +
" -ActionOnUnmanage \"deleteAll\" `\n" +
" -DenySettingsMode \"denyDelete\""
}

View File

@@ -0,0 +1,142 @@
// file is generated by AI
package cloudintegrationtypes
import (
"fmt"
"strings"
"testing"
"github.com/SigNoz/signoz/pkg/valuer"
)
var testTemplateData = azureTemplateData{
TemplateURL: fmt.Sprintf(AgentArmTemplateStorePath, "v0.1.0"),
Location: "eastus",
SignozAPIKey: "test-api-key",
SignozAPIUrl: "https://signoz.example.com",
SignozIngestionURL: "https://ingest.example.com",
SignozIngestionKey: "test-ingest-key",
AccountID: "acct-123",
AgentVersion: "v0.1.0",
StackName: AgentDeploymentStackName,
ParamLocation: armParamLocation,
ParamSignozAPIKey: armParamSignozAPIKey,
ParamSignozAPIUrl: armParamSignozAPIUrl,
ParamSignozIngestionURL: armParamSignozIngestionURL,
ParamSignozIngestionKey: armParamSignozIngestionKey,
ParamAccountID: armParamAccountID,
ParamAgentVersion: armParamAgentVersion,
ParamRgName: armParamRgName,
ParamContainerEnvName: armParamContainerEnvName,
ParamDeploymentEnv: armParamDeploymentEnv,
DefaultRgName: armDefaultRgName,
DefaultContainerEnvName: armDefaultContainerEnvName,
DefaultDeploymentEnv: armDefaultDeploymentEnv,
}
func TestNewAzureConnectionCLICommand(t *testing.T) {
cmd, err := newAzureConnectionCLICommand(testTemplateData)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
mustContain := []string{
"az stack sub create",
fmt.Sprintf("--name %s", AgentDeploymentStackName),
fmt.Sprintf("--location %s", testTemplateData.Location),
fmt.Sprintf("--template-uri %s", testTemplateData.TemplateURL),
fmt.Sprintf("%s='%s'", armParamLocation, testTemplateData.Location),
fmt.Sprintf("%s='%s'", armParamSignozAPIKey, testTemplateData.SignozAPIKey),
fmt.Sprintf("%s='%s'", armParamSignozAPIUrl, testTemplateData.SignozAPIUrl),
fmt.Sprintf("%s='%s'", armParamSignozIngestionURL, testTemplateData.SignozIngestionURL),
fmt.Sprintf("%s='%s'", armParamSignozIngestionKey, testTemplateData.SignozIngestionKey),
fmt.Sprintf("%s='%s'", armParamAccountID, testTemplateData.AccountID),
fmt.Sprintf("%s='%s'", armParamAgentVersion, testTemplateData.AgentVersion),
"--action-on-unmanage deleteAll",
"--deny-settings-mode denyDelete",
}
for _, fragment := range mustContain {
if !strings.Contains(cmd, fragment) {
t.Errorf("CLI command missing %q\ngot:\n%s", fragment, cmd)
}
}
// Lines must be joined with the bash line-continuation separator.
if !strings.Contains(cmd, " \\\n") {
t.Errorf("CLI command missing line-continuation separator ' \\\\\\n'\ngot:\n%s", cmd)
}
}
func TestNewAzureConnectionPowerShellCommand(t *testing.T) {
cmd, err := newAzureConnectionPowerShellCommand(testTemplateData)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
mustContain := []string{
"New-AzSubscriptionDeploymentStack",
fmt.Sprintf("-Name \"%s\"", AgentDeploymentStackName),
fmt.Sprintf("-Location \"%s\"", testTemplateData.Location),
fmt.Sprintf("-TemplateUri \"%s\"", testTemplateData.TemplateURL),
armParamLocation,
armParamSignozAPIKey,
armParamSignozAPIUrl,
armParamSignozIngestionURL,
armParamSignozIngestionKey,
armParamAccountID,
armParamAgentVersion,
armParamRgName,
armParamContainerEnvName,
armParamDeploymentEnv,
armDefaultRgName,
armDefaultContainerEnvName,
armDefaultDeploymentEnv,
"-ActionOnUnmanage \"deleteAll\"",
"-DenySettingsMode \"denyDelete\"",
}
for _, fragment := range mustContain {
if !strings.Contains(cmd, fragment) {
t.Errorf("PowerShell command missing %q\ngot:\n%s", fragment, cmd)
}
}
// Final command must not end with a line-continuation backtick.
if strings.HasSuffix(strings.TrimSpace(cmd), "`") {
t.Errorf("PowerShell command must not end with a backtick\ngot:\n%s", cmd)
}
}
func TestNewAzureConnectionArtifact(t *testing.T) {
accountID := valuer.GenerateUUID()
agentVersion := "v0.1.0"
creds := &Credentials{
SigNozAPIURL: "https://signoz.example.com",
SigNozAPIKey: "test-api-key",
IngestionURL: "https://ingest.example.com",
IngestionKey: "test-ingest-key",
}
cfg := &AzurePostableAccountConfig{
DeploymentRegion: "eastus",
ResourceGroups: []string{"rg1"},
}
artifact, err := NewAzureConnectionArtifact(accountID, agentVersion, creds, cfg)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if artifact.CLICommand == "" {
t.Error("CLICommand must not be empty")
}
if artifact.CloudPowerShellCommand == "" {
t.Error("CloudPowerShellCommand must not be empty")
}
if !strings.Contains(artifact.CLICommand, accountID.StringValue()) {
t.Errorf("CLICommand must contain accountID %q", accountID.StringValue())
}
if !strings.Contains(artifact.CloudPowerShellCommand, accountID.StringValue()) {
t.Errorf("CloudPowerShellCommand must contain accountID %q", accountID.StringValue())
}
}

View File

@@ -239,6 +239,10 @@ func (service *CloudIntegrationService) Update(provider CloudProviderType, servi
}
// other validations happen in newStorableServiceConfig
case CloudProviderTypeAzure:
if config.Azure == nil {
return errors.NewInvalidInputf(ErrCodeCloudProviderInvalidInput, "Azure config is required for Azure service")
}
default:
return errors.NewInvalidInputf(ErrCodeCloudProviderInvalidInput, "invalid cloud provider: %s", provider.StringValue())
}