Refactor Azure VM discovery metadata and status (#67590)

* Refactor Azure VM discovery metadata and status

Move immutable Azure VM discovery metadata into a dedicated embedded
AzureInstancesMetadata type. This lets enrollment, status, audit, usage event,
and user-task paths pass metadata separately from the mutable Instances slice,
which is filtered during enrollment.

Change the resource status from a primitive map type into a struct. This
will make the status map more flexible for further changes that
introduce parallel installation and status updates.

This also logs the instance count after filtering enrolled instances.

* Update AzureInstances godoc

* Make metadata an unembedded field

* rename loop var from group to status

* revert failed azure enrollment func to lambda

* re-eval VMs log value iff some VMs were filtered
This commit is contained in:
Gavin Frazar
2026-06-11 21:44:44 +00:00
committed by GitHub
parent 9306e190ec
commit 05775bc5dc
6 changed files with 177 additions and 135 deletions
+7
View File
@@ -484,6 +484,13 @@ func (c *runCommandClient) Run(ctx context.Context, req RunCommandRequest) (*Run
runCommand := armcompute.VirtualMachineRunCommand{
Location: to.Ptr(req.Region),
Properties: &armcompute.VirtualMachineRunCommandProperties{
// NOTE: The AsyncExecution option can be very misleading.
// It has no effect on whether BeginCreateOrUpdate blocks.
// Instead, it affects poller.PollUntilDone.
// If set to true, then calling poller.PollUntilDone will actually
// return as soon as the script is "provisioned" even if
// the script execution state is still "running".
// We always want this option set to false.
AsyncExecution: to.Ptr(false),
Source: &armcompute.VirtualMachineRunCommandScriptSource{
Script: to.Ptr(req.Script),
@@ -23,8 +23,16 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/gravitational/teleport/api/types/usertasks"
"github.com/gravitational/teleport/lib/srv/server"
)
func classifyAzureInstallResultIssue(installResult server.AzureInstallResult) string {
if installResult.CommandResult != nil {
return usertasks.AutoDiscoverAzureVMIssueEnrollmentError
}
return classifyAzureVMEnrollmentError(installResult.APIError)
}
// classifyAzureVMEnrollmentError classifies Azure API errors into user-facing
// messages for VM auto-discovery. This is best-effort based on error strings
// which may change without notice. The matching logic may require future
+52 -52
View File
@@ -455,7 +455,7 @@ type Server struct {
awsEC2Tasks awsEC2Tasks
awsEKSTasks awsEKSTasks
awsRDSTasks awsRDSTasks
azureVMStatus atomic.Pointer[resourceStatusMap]
azureVMStatus atomic.Pointer[discoveryStatus]
// caRotationCh receives nodes that need to have their CAs rotated.
caRotationCh chan []types.Server
@@ -1456,9 +1456,9 @@ func (s *Server) startAWSServerDiscovery() {
go s.watchCARotation(s.ctx)
}
func (s *Server) emitAzureInstallEvents(log *slog.Logger, instances *server.AzureInstances, result server.AzureInstallResult) {
func (s *Server) emitAzureInstallEvents(log *slog.Logger, md server.AzureInstancesMetadata, result server.AzureInstallResult) {
// emit run event.
runEvent := instances.MakeRunEvent(result)
runEvent := md.MakeRunEvent(result)
err := s.Emitter.EmitAuditEvent(s.ctx, runEvent)
if err != nil {
log.WarnContext(s.ctx, "Failed to emit audit event", "error", err)
@@ -1469,7 +1469,7 @@ func (s *Server) emitAzureInstallEvents(log *slog.Logger, instances *server.Azur
}
// on success, emit usage event.
vmKey, usageEvent := instances.MakeUsageEvent(result.Instance)
vmKey, usageEvent := md.MakeUsageEvent(result.Instance)
err = s.emitUsageEvent(vmKey, usageEvent)
if err != nil {
log.WarnContext(s.ctx, "Failed to emit usage event", "error", err)
@@ -1533,12 +1533,12 @@ func (e *limitedErrorReporter) summary(ctx context.Context) {
}
func (s *Server) enrollAzureVirtualMachines(log *slog.Logger, instances *server.AzureInstances) ([]server.AzureInstallResult, error) {
azureClients, err := s.getAzureClients(s.ctx, instances.Integration)
azureClients, err := s.getAzureClients(s.ctx, instances.Metadata.Integration)
if err != nil {
return nil, trace.Wrap(err)
}
runClient, err := azureClients.GetRunCommandClient(s.ctx, instances.SubscriptionID)
runClient, err := azureClients.GetRunCommandClient(s.ctx, instances.Metadata.SubscriptionID)
if err != nil {
return nil, trace.Wrap(err)
}
@@ -1554,12 +1554,12 @@ func (s *Server) enrollAzureVirtualMachines(log *slog.Logger, instances *server.
req := server.AzureInstallRequest{
Instances: instances.Instances,
Region: instances.Region,
ResourceGroup: instances.ResourceGroup,
InstallerParams: instances.InstallerParams,
Region: instances.Metadata.Region,
ResourceGroup: instances.Metadata.ResourceGroup,
InstallerParams: instances.Metadata.InstallerParams,
ProxyAddrGetter: s.publicProxyAddress,
OnRunCommandFinished: func(result server.AzureInstallResult) {
s.emitAzureInstallEvents(log, instances, result)
s.emitAzureInstallEvents(log, instances.Metadata, result)
if result.Failure() {
reporter.report(s.ctx, result)
@@ -1616,7 +1616,7 @@ func (s *Server) startAzureServerDiscovery() {
azureWatcher.ReplaceFetchers(replaceMap)
}
var sm *resourceStatusMap
var sm *discoveryStatus
var vmTasks *azureVMTasks
var runStart time.Time
@@ -1639,22 +1639,22 @@ func (s *Server) startAzureServerDiscovery() {
// "0 found/enrolled/failed" update instead of leaving stale non-zero status from a
// previous iteration.
for _, fetcher := range fetchers {
fgKey := fetcherGroupKey{
key := discoveryGroupStatusKey{
discoveryConfigName: fetcher.GetDiscoveryConfigName(),
integration: fetcher.IntegrationName(),
}
sm.add(fgKey, make(map[statusType]int))
sm.add(key, discoveryGroupStatus{})
}
s.updateDiscoveryConfigStatus(sm.discoveryConfigs()...)
}),
server.WithPerInstanceHookFn(func(instanceGroups []*server.AzureInstances) {
for _, group := range instanceGroups {
fgKey := fetcherGroupKey{
discoveryConfigName: group.DiscoveryConfigName,
integration: group.Integration,
key := discoveryGroupStatusKey{
discoveryConfigName: group.Metadata.DiscoveryConfigName,
integration: group.Metadata.Integration,
}
results := s.installAzureServers(group, vmTasks)
sm.add(fgKey, results)
status := s.installAzureServers(group, vmTasks)
sm.add(key, status)
}
}),
server.WithPostFetchHookFn[*server.AzureInstances](func() {
@@ -1681,94 +1681,95 @@ func (s *Server) startAzureServerDiscovery() {
go azureWatcher.Run()
}
func (s *Server) installAzureServers(instances *server.AzureInstances, vmTasks *azureVMTasks) (results map[statusType]int) {
results = make(map[statusType]int)
func (s *Server) installAzureServers(instances *server.AzureInstances, vmTasks *azureVMTasks) discoveryGroupStatus {
var status discoveryGroupStatus
log := s.Log.With("group", instances)
log.DebugContext(s.ctx, "Processing instance group")
allFound := len(instances.Instances)
results[statusFound] = allFound
if allFound == 0 {
found := len(instances.Instances)
if found == 0 {
log.DebugContext(s.ctx, "No Azure instances found, skipping installation")
return
return status
}
status.found += found
nodes, err := s.nodeWatcher.CurrentResources(s.ctx)
if err != nil {
log.WarnContext(s.ctx, "Failed to get current node resources", "error", err)
return
return status
}
instances.FilterExistingNodes(nodes)
// count machines that have already been enrolled in previous cycles.
needInstall := len(instances.Instances)
results[statusEnrolled] = allFound - needInstall
enrolled := found - needInstall
if enrolled > 0 {
status.enrolled += enrolled
log.DebugContext(s.ctx, "Filtered out Azure instances that have already been enrolled",
"enrolled", enrolled,
)
// re-evaluate the instances log value after filtering
log = s.Log.With("group", instances)
}
if len(instances.Instances) == 0 {
log.DebugContext(s.ctx, "No Azure instances remain to enroll, skipping installation")
return
return status
}
addFailedEnrollment := func(vm *azure.VirtualMachine, issueType string) {
addFailedAzureEnrollment := func(vm *azure.VirtualMachine, issueType string) {
// Static matchers don't have a discovery config resource, so skip creating user tasks
// because validation requires a discovery config name.
if instances.DiscoveryConfigName == noDiscoveryConfig {
if instances.Metadata.DiscoveryConfigName == noDiscoveryConfig {
return
}
tg := usertasks.TaskGroup{
Integration: instances.Integration,
Integration: instances.Metadata.Integration,
IssueType: issueType,
}
vmTasks.addFailedEnrollment(
tg,
azureVMTaskKey{
subscriptionID: instances.SubscriptionID,
resourceGroup: instances.ResourceGroup,
region: instances.Region,
subscriptionID: instances.Metadata.SubscriptionID,
resourceGroup: instances.Metadata.ResourceGroup,
region: instances.Metadata.Region,
},
usertasksv1.DiscoverAzureVMInstance_builder{
VmId: vm.VMID,
ResourceId: vm.ID,
Name: vm.Name,
DiscoveryConfig: instances.DiscoveryConfigName,
DiscoveryConfig: instances.Metadata.DiscoveryConfigName,
DiscoveryGroup: s.DiscoveryGroup,
SyncTime: timestamppb.New(s.clock.Now()),
}.Build(),
)
}
log.DebugContext(s.ctx, "Running Teleport installation on virtual machines", "group", instances, "vms", genAzureInstancesLogStr(instances.Instances))
log.DebugContext(s.ctx, "Running Teleport installation on virtual machines", "vms", genAzureInstancesLogStr(instances.Instances))
failures, err := s.enrollAzureVirtualMachines(log, instances)
if err != nil {
// treat non-nil err as deployment failure affecting all machines.
log.WarnContext(s.ctx, "Failed to enroll discovered Azure VMs", "error", err, "count", len(instances.Instances))
results[statusFailed] = len(instances.Instances)
log.WarnContext(s.ctx, "Failed to enroll all discovered Azure VMs", "error", err)
status.failed += len(instances.Instances)
issueType := classifyAzureVMEnrollmentError(err)
for _, vm := range instances.Instances {
addFailedEnrollment(vm, issueType)
addFailedAzureEnrollment(vm, issueType)
}
return
return status
}
if len(failures) > 0 {
log.WarnContext(s.ctx, "Failed to enroll some discovered Azure VMs", "count", len(failures))
log.WarnContext(s.ctx, "Failed to enroll some discovered Azure VMs", "failures", len(failures))
}
// count individual failed enrollments.
results[statusFailed] = len(failures)
status.failed += len(failures)
// Record failures as user tasks.
for _, result := range failures {
if result.CommandResult != nil {
// TODO (Tener): check exit codes and create more detailed user tasks.
addFailedEnrollment(result.Instance, usertasks.AutoDiscoverAzureVMIssueEnrollmentError)
} else {
addFailedEnrollment(result.Instance, classifyAzureVMEnrollmentError(result.APIError))
}
// TODO (Tener): check exit codes and create more detailed user tasks.
addFailedAzureEnrollment(result.Instance, classifyAzureInstallResultIssue(result))
}
pendingCount := len(instances.Instances) - len(failures)
@@ -1780,8 +1781,7 @@ func (s *Server) installAzureServers(instances *server.AzureInstances, vmTasks *
// There is no easy way to close that gap in the current architecture.
log.DebugContext(s.ctx, "Installation attempt finished. If the machines have joined the cluster successfully, they will be counted as enrolled during the next iteration.", "pending", pendingCount)
}
return
return status
}
func (s *Server) filterExistingGCPNodes(instances *server.GCPInstances) error {
+31 -35
View File
@@ -1071,66 +1071,62 @@ func (s *taskUpdater) mergeAzure(oldSpec *usertasksv1.UserTaskSpec, newSpec *use
mergeExistingInstances(s, oldSpec.GetDiscoverAzureVm().GetInstances(), newSpec.GetDiscoverAzureVm().GetInstances())
}
type statusType int
const (
statusFound statusType = iota
statusEnrolled
statusFailed
)
type fetcherGroupKey struct {
type discoveryGroupStatusKey struct {
discoveryConfigName string
integration string
}
// resourceStatusMap tracks discovery status (found/enrolled/failed counts)
// per fetcher group key (discovery config + integration combination).
type resourceStatusMap struct {
type discoveryGroupStatus struct {
found int
enrolled int
failed int
}
// discoveryStatus tracks discovery status (found/enrolled/failed counts) per
// discovery group key (discovery config + integration combination).
type discoveryStatus struct {
resourceType string
results map[fetcherGroupKey]map[statusType]int
statuses map[discoveryGroupStatusKey]*discoveryGroupStatus
syncStart *time.Time
syncEnd *time.Time
}
func newStatusMap(resourceType string, syncStart time.Time) *resourceStatusMap {
return &resourceStatusMap{
func newStatusMap(resourceType string, syncStart time.Time) *discoveryStatus {
return &discoveryStatus{
resourceType: resourceType,
results: make(map[fetcherGroupKey]map[statusType]int),
statuses: make(map[discoveryGroupStatusKey]*discoveryGroupStatus),
syncStart: &syncStart,
}
}
func (s *resourceStatusMap) syncEnded(syncEnd time.Time) {
func (s *discoveryStatus) syncEnded(syncEnd time.Time) {
s.syncEnd = &syncEnd
}
func (s *resourceStatusMap) add(key fetcherGroupKey, results map[statusType]int) {
if s.results[key] == nil {
s.results[key] = make(map[statusType]int)
}
for k, v := range results {
s.results[key][k] += v
func (s *discoveryStatus) add(key discoveryGroupStatusKey, update discoveryGroupStatus) {
if s.statuses[key] == nil {
s.statuses[key] = &update
return
}
status := s.statuses[key]
status.found += update.found
status.enrolled += update.enrolled
status.failed += update.failed
}
func (s *resourceStatusMap) mergeIntoGlobalStatus(discoveryConfigName string, existingStatus discoveryconfig.Status) discoveryconfig.Status {
func (s *discoveryStatus) mergeIntoGlobalStatus(discoveryConfigName string, existingStatus discoveryconfig.Status) discoveryconfig.Status {
if s == nil {
// nil resourceStatusMap is valid, just empty.
return existingStatus
}
for key, results := range s.results {
for key, status := range s.statuses {
if key.discoveryConfigName != discoveryConfigName {
continue
}
if results == nil {
continue
}
// Update global discovered resources count.
existingStatus.DiscoveredResources = existingStatus.DiscoveredResources + uint64(results[statusFound])
existingStatus.DiscoveredResources += uint64(status.found)
// Initialize map if needed.
if existingStatus.IntegrationDiscoveredResources == nil {
@@ -1153,9 +1149,9 @@ func (s *resourceStatusMap) mergeIntoGlobalStatus(discoveryConfigName string, ex
}
resourcesSummary := discoveryconfigv1.ResourcesDiscoveredSummary_builder{
Found: uint64(results[statusFound]),
Enrolled: uint64(results[statusEnrolled]),
Failed: uint64(results[statusFailed]),
Found: uint64(status.found),
Enrolled: uint64(status.enrolled),
Failed: uint64(status.failed),
SyncStart: syncStart,
SyncEnd: syncEnd,
}.Build()
@@ -1168,13 +1164,13 @@ func (s *resourceStatusMap) mergeIntoGlobalStatus(discoveryConfigName string, ex
return existingStatus
}
func (s *resourceStatusMap) discoveryConfigs() []string {
func (s *discoveryStatus) discoveryConfigs() []string {
if s == nil {
return nil
}
names := map[string]struct{}{}
for key := range s.results {
for key := range s.statuses {
names[key.discoveryConfigName] = struct{}{}
}
return slices.Collect(maps.Keys(names))
+44 -31
View File
@@ -38,8 +38,8 @@ import (
const azureEventPrefix = "azure/"
// AzureInstances contains information about discovered Azure virtual machines.
type AzureInstances struct {
// AzureInstancesMetadata contains information about discovered Azure virtual machines.
type AzureInstancesMetadata struct {
// DiscoveryConfigName is the name of discovery config.
DiscoveryConfigName string
// Integration is the optional name of the integration to use for auth.
@@ -54,43 +54,37 @@ type AzureInstances struct {
// InstallerParams are the installer parameters used for installation.
InstallerParams *types.InstallerParams
// Instances is a list of discovered Azure virtual machines.
Instances []*azure.VirtualMachine
}
func (instances *AzureInstances) LogValue() slog.Value {
if instances == nil {
return slog.StringValue("<nil>")
}
func (md AzureInstancesMetadata) LogValue() slog.Value {
return slog.GroupValue(
slog.Int("total_instances", len(instances.Instances)),
slog.String("discovery_config", instances.DiscoveryConfigName),
slog.String("integration", instances.Integration),
slog.String("region", instances.Region),
slog.String("resource_group", instances.ResourceGroup),
slog.String("subscription_id", instances.SubscriptionID),
slog.String("discovery_config", md.DiscoveryConfigName),
slog.String("integration", md.Integration),
slog.String("region", md.Region),
slog.String("resource_group", md.ResourceGroup),
slog.String("subscription_id", md.SubscriptionID),
)
}
func (instances *AzureInstances) resourceType() string {
if instances.InstallerParams != nil && instances.InstallerParams.ScriptName == installers.InstallerScriptNameAgentless {
func (md *AzureInstancesMetadata) resourceType() string {
if md.InstallerParams != nil && md.InstallerParams.ScriptName == installers.InstallerScriptNameAgentless {
return types.DiscoveredResourceAgentlessNode
}
return types.DiscoveredResourceNode
}
// MakeUsageEvent builds usage event for a single installation result.
func (instances *AzureInstances) MakeUsageEvent(instance *azure.VirtualMachine) (string, *usageeventsv1.ResourceCreateEvent) {
func (md *AzureInstancesMetadata) MakeUsageEvent(instance *azure.VirtualMachine) (string, *usageeventsv1.ResourceCreateEvent) {
return azureEventPrefix + instance.ID, &usageeventsv1.ResourceCreateEvent{
ResourceType: instances.resourceType(),
ResourceType: md.resourceType(),
ResourceOrigin: types.OriginCloud,
CloudProvider: types.CloudAzure,
DiscoveryConfigName: instances.DiscoveryConfigName,
DiscoveryConfigName: md.DiscoveryConfigName,
}
}
// MakeRunEvent builds run event for a single command run.
func (instances *AzureInstances) MakeRunEvent(result AzureInstallResult) *apievents.AzureRun {
func (md *AzureInstancesMetadata) MakeRunEvent(result AzureInstallResult) *apievents.AzureRun {
eventCode := libevents.AzureRunSuccessCode
if result.Failure() {
@@ -110,10 +104,10 @@ func (instances *AzureInstances) MakeRunEvent(result AzureInstallResult) *apieve
Code: eventCode,
},
AzureMetadata: apievents.AzureMetadata{
SubscriptionID: instances.SubscriptionID,
ResourceGroup: instances.ResourceGroup,
SubscriptionID: md.SubscriptionID,
ResourceGroup: md.ResourceGroup,
ResourceID: resourceID,
Region: instances.Region,
Region: md.Region,
},
AzureVMMetadata: apievents.AzureVMMetadata{
VMID: vmID,
@@ -143,13 +137,30 @@ func (instances *AzureInstances) MakeRunEvent(result AzureInstallResult) *apieve
return evt
}
// AzureInstances contains a list of discovered Azure virtual machines and
// metadata.
type AzureInstances struct {
Metadata AzureInstancesMetadata
// Instances is a list of discovered Azure virtual machines.
Instances []*azure.VirtualMachine
}
// LogValue implements [slog.LogValuer].
func (instances *AzureInstances) LogValue() slog.Value {
return slog.GroupValue(
slog.Int("count", len(instances.Instances)),
slog.Any("metadata", instances.Metadata),
)
}
// FilterExistingNodes removes instances matching existing nodes in place.
func (instances *AzureInstances) FilterExistingNodes(existingNodes []types.Server) {
vmIDs := make(map[string]struct{})
for _, node := range existingNodes {
labels := node.GetAllLabels()
subscriptionID := labels[types.SubscriptionIDLabelInternal]
if subscriptionID != instances.SubscriptionID {
if subscriptionID != instances.Metadata.SubscriptionID {
continue
}
vmID := labels[types.VMIDLabelInternal]
@@ -320,13 +331,15 @@ func (f *azureInstanceFetcher) GetInstances(ctx context.Context, _ bool) ([]*Azu
var instances []*AzureInstances
for batchGroup, vms := range instanceGroups {
instances = append(instances, &AzureInstances{
SubscriptionID: f.Subscription,
Region: batchGroup.location,
ResourceGroup: batchGroup.resourceGroup,
Instances: vms,
Integration: f.Integration,
InstallerParams: f.InstallerParams,
DiscoveryConfigName: f.DiscoveryConfigName,
Metadata: AzureInstancesMetadata{
SubscriptionID: f.Subscription,
Region: batchGroup.location,
ResourceGroup: batchGroup.resourceGroup,
Integration: f.Integration,
InstallerParams: f.InstallerParams,
DiscoveryConfigName: f.DiscoveryConfigName,
},
Instances: vms,
})
}
+35 -17
View File
@@ -276,8 +276,8 @@ func TestAzureWatcher(t *testing.T) {
vmID := parsedResource.Name
vmIDs = append(vmIDs, vmID)
}
require.NotEqual(t, "*", results.ResourceGroup, "Discovered VM's ResourceGroup should never be the wildcard")
require.NotEqual(t, "*", results.SubscriptionID, "Discovered VM's SubscriptionID should never be the wildcard")
require.NotEqual(t, "*", results.Metadata.ResourceGroup, "Discovered VM's ResourceGroup should never be the wildcard")
require.NotEqual(t, "*", results.Metadata.SubscriptionID, "Discovered VM's SubscriptionID should never be the wildcard")
case <-ctx.Done():
require.ElementsMatch(t, tc.wantVMs, vmIDs, "timed out while waiting for expected VMs")
}
@@ -300,7 +300,9 @@ func TestAzureInstances_FilterExistingNodes(t *testing.T) {
{
name: "no existing nodes",
instances: &AzureInstances{
SubscriptionID: "sub-1",
Metadata: AzureInstancesMetadata{
SubscriptionID: "sub-1",
},
Instances: []*azure.VirtualMachine{
{
ID: "/subscriptions/sub-1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
@@ -318,7 +320,9 @@ func TestAzureInstances_FilterExistingNodes(t *testing.T) {
{
name: "filter out matching node",
instances: &AzureInstances{
SubscriptionID: "sub-1",
Metadata: AzureInstancesMetadata{
SubscriptionID: "sub-1",
},
Instances: []*azure.VirtualMachine{
{
ID: "/subscriptions/sub-1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
@@ -338,7 +342,9 @@ func TestAzureInstances_FilterExistingNodes(t *testing.T) {
{
name: "filter out all matching nodes",
instances: &AzureInstances{
SubscriptionID: "sub-1",
Metadata: AzureInstancesMetadata{
SubscriptionID: "sub-1",
},
Instances: []*azure.VirtualMachine{
{
ID: "/subscriptions/sub-1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
@@ -359,7 +365,9 @@ func TestAzureInstances_FilterExistingNodes(t *testing.T) {
{
name: "different subscription is not filtered",
instances: &AzureInstances{
SubscriptionID: "sub-1",
Metadata: AzureInstancesMetadata{
SubscriptionID: "sub-1",
},
Instances: []*azure.VirtualMachine{
{
ID: "/subscriptions/sub-1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
@@ -375,7 +383,9 @@ func TestAzureInstances_FilterExistingNodes(t *testing.T) {
{
name: "node without vm id is not used for filtering",
instances: &AzureInstances{
SubscriptionID: "sub-1",
Metadata: AzureInstancesMetadata{
SubscriptionID: "sub-1",
},
Instances: []*azure.VirtualMachine{
{
ID: "/subscriptions/sub-1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
@@ -391,7 +401,9 @@ func TestAzureInstances_FilterExistingNodes(t *testing.T) {
{
name: "instance without properties is not filtered",
instances: &AzureInstances{
SubscriptionID: "sub-1",
Metadata: AzureInstancesMetadata{
SubscriptionID: "sub-1",
},
Instances: []*azure.VirtualMachine{
{
ID: "/subscriptions/sub-1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
@@ -612,11 +624,13 @@ func TestMakeRunEvent(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
instances := &AzureInstances{
SubscriptionID: subscriptionID,
ResourceGroup: resourceGroup,
Region: region,
Metadata: AzureInstancesMetadata{
SubscriptionID: subscriptionID,
ResourceGroup: resourceGroup,
Region: region,
},
}
evt := instances.MakeRunEvent(tc.result)
evt := instances.Metadata.MakeRunEvent(tc.result)
require.Equal(t, tc.want, evt)
})
}
@@ -643,7 +657,9 @@ func TestMakeUsageEvent(t *testing.T) {
{
name: "node",
instances: &AzureInstances{
DiscoveryConfigName: discoveryConfig,
Metadata: AzureInstancesMetadata{
DiscoveryConfigName: discoveryConfig,
},
},
wantKey: azureEventPrefix + resourceID,
want: &usageeventsv1.ResourceCreateEvent{
@@ -656,9 +672,11 @@ func TestMakeUsageEvent(t *testing.T) {
{
name: "agentless node",
instances: &AzureInstances{
DiscoveryConfigName: discoveryConfig,
InstallerParams: &types.InstallerParams{
ScriptName: installers.InstallerScriptNameAgentless,
Metadata: AzureInstancesMetadata{
DiscoveryConfigName: discoveryConfig,
InstallerParams: &types.InstallerParams{
ScriptName: installers.InstallerScriptNameAgentless,
},
},
},
wantKey: azureEventPrefix + resourceID,
@@ -673,7 +691,7 @@ func TestMakeUsageEvent(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
key, evt := tc.instances.MakeUsageEvent(vm)
key, evt := tc.instances.Metadata.MakeUsageEvent(vm)
require.Equal(t, tc.wantKey, key)
require.Equal(t, tc.want, evt)
})