Skip to content

Commit

Permalink
Generate azure_resource_id (open-telemetry#2897)
Browse files Browse the repository at this point in the history
Code taken from
https://github.com/signalfx/signalfx-agent/blob/master/pkg/core/hostid/azure.go#L18
with minor modifications.

Tested on Azure (standalone VM and Scale Set).
  • Loading branch information
pmcollins committed Apr 1, 2021
1 parent a835321 commit 7276360
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 9 deletions.
78 changes: 69 additions & 9 deletions internal/splunk/hostid.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package splunk

import (
"fmt"
"strings"

"go.opentelemetry.io/collector/consumer/pdata"
"go.opentelemetry.io/collector/translator/conventions"
Expand All @@ -29,6 +30,8 @@ const (
HostIDKeyAWS HostIDKey = "AWSUniqueId"
// GCP
HostIDKeyGCP HostIDKey = "gcp_id"
// Azure
HostIDKeyAzure HostIDKey = "azure_resource_id"
// Host
HostIDKeyHost HostIDKey = conventions.AttributeHostName
)
Expand All @@ -45,27 +48,32 @@ type HostID struct {
// ResourceToHostID returns a boolean determining whether or not a HostID was able to be
// computed or not.
func ResourceToHostID(res pdata.Resource) (HostID, bool) {
var cloudAccount, region, hostID, provider string
var cloudAccount, hostID, provider string

if res.Attributes().Len() == 0 {
attrs := res.Attributes()

if attrs.Len() == 0 {
return HostID{}, false
}

if attr, ok := res.Attributes().Get(conventions.AttributeCloudAccount); ok {
if attr, ok := attrs.Get(conventions.AttributeCloudAccount); ok {
cloudAccount = attr.StringVal()
}
if attr, ok := res.Attributes().Get(conventions.AttributeCloudRegion); ok {
region = attr.StringVal()
}
if attr, ok := res.Attributes().Get(conventions.AttributeHostID); ok {

if attr, ok := attrs.Get(conventions.AttributeHostID); ok {
hostID = attr.StringVal()
}
if attr, ok := res.Attributes().Get(conventions.AttributeCloudProvider); ok {

if attr, ok := attrs.Get(conventions.AttributeCloudProvider); ok {
provider = attr.StringVal()
}

switch provider {
case conventions.AttributeCloudProviderAWS:
var region string
if attr, ok := attrs.Get(conventions.AttributeCloudRegion); ok {
region = attr.StringVal()
}
if hostID == "" || region == "" || cloudAccount == "" {
break
}
Expand All @@ -81,9 +89,21 @@ func ResourceToHostID(res pdata.Resource) (HostID, bool) {
Key: HostIDKeyGCP,
ID: fmt.Sprintf("%s_%s", cloudAccount, hostID),
}, true
case conventions.AttributeCloudProviderAzure:
if cloudAccount == "" {
break
}
id := azureID(attrs, cloudAccount)
if id == "" {
break
}
return HostID{
Key: HostIDKeyAzure,
ID: id,
}, true
}

if attr, ok := res.Attributes().Get(conventions.AttributeHostName); ok {
if attr, ok := attrs.Get(conventions.AttributeHostName); ok {
return HostID{
Key: HostIDKeyHost,
ID: attr.StringVal(),
Expand All @@ -92,3 +112,43 @@ func ResourceToHostID(res pdata.Resource) (HostID, bool) {

return HostID{}, false
}

func azureID(attrs pdata.AttributeMap, cloudAccount string) string {
var resourceGroupName string
if attr, ok := attrs.Get("azure.resourcegroup.name"); ok {
resourceGroupName = attr.StringVal()
}
if resourceGroupName == "" {
return ""
}

var hostname string
if attr, ok := attrs.Get(conventions.AttributeHostName); ok {
hostname = attr.StringVal()
}
if hostname == "" {
return ""
}

var vmScaleSetName string
if attr, ok := attrs.Get("azure.vm.scaleset.name"); ok {
vmScaleSetName = attr.StringVal()
}
if vmScaleSetName == "" {
return strings.ToLower(fmt.Sprintf(
"%s/%s/microsoft.compute/virtualmachines/%s",
cloudAccount,
resourceGroupName,
hostname,
))
}

instanceID := strings.TrimPrefix(hostname, vmScaleSetName+"_")
return strings.ToLower(fmt.Sprintf(
"%s/%s/microsoft.compute/virtualmachinescalesets/%s/virtualmachines/%s",
cloudAccount,
resourceGroupName,
vmScaleSetName,
instanceID,
))
}
107 changes: 107 additions & 0 deletions internal/splunk/hostid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,67 @@ var (
attr.InsertString(conventions.AttributeCloudAccount, "1234")
return res
}()
azureResource = func() pdata.Resource {
res := pdata.NewResource()
attrs := res.Attributes()
attrs.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure)
attrs.InsertString(conventions.AttributeCloudInfrastructureService, conventions.AttributeCloudProviderAzureVM)
attrs.InsertString(conventions.AttributeHostName, "myHostName")
attrs.InsertString(conventions.AttributeCloudRegion, "myCloudRegion")
attrs.InsertString(conventions.AttributeHostID, "myHostID")
attrs.InsertString(conventions.AttributeCloudAccount, "myCloudAccount")
attrs.InsertString("azure.vm.size", "42")
attrs.InsertString("azure.resourcegroup.name", "myResourcegroupName")
return res
}()
azureScalesetResource = func() pdata.Resource {
res := pdata.NewResource()
attrs := res.Attributes()
attrs.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure)
attrs.InsertString(conventions.AttributeCloudInfrastructureService, conventions.AttributeCloudProviderAzureVM)
attrs.InsertString(conventions.AttributeHostName, "myVMScalesetName_1")
attrs.InsertString(conventions.AttributeCloudRegion, "myCloudRegion")
attrs.InsertString(conventions.AttributeHostID, "myHostID")
attrs.InsertString(conventions.AttributeCloudAccount, "myCloudAccount")
attrs.InsertString("azure.vm.size", "42")
attrs.InsertString("azure.vm.scaleset.name", "myVMScalesetName")
attrs.InsertString("azure.resourcegroup.name", "myResourcegroupName")
return res
}()
azureMissingCloudAcct = func() pdata.Resource {
res := pdata.NewResource()
attrs := res.Attributes()
attrs.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure)
attrs.InsertString(conventions.AttributeCloudInfrastructureService, conventions.AttributeCloudProviderAzureVM)
attrs.InsertString(conventions.AttributeCloudRegion, "myCloudRegion")
attrs.InsertString(conventions.AttributeHostID, "myHostID")
attrs.InsertString("azure.vm.size", "42")
attrs.InsertString("azure.resourcegroup.name", "myResourcegroupName")
return res
}()
azureMissingResourceGroup = func() pdata.Resource {
res := pdata.NewResource()
attrs := res.Attributes()
attrs.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure)
attrs.InsertString(conventions.AttributeCloudInfrastructureService, conventions.AttributeCloudProviderAzureVM)
attrs.InsertString(conventions.AttributeCloudRegion, "myCloudRegion")
attrs.InsertString(conventions.AttributeHostID, "myHostID")
attrs.InsertString(conventions.AttributeCloudAccount, "myCloudAccount")
attrs.InsertString("azure.vm.size", "42")
return res
}()
azureMissingHostName = func() pdata.Resource {
res := pdata.NewResource()
attrs := res.Attributes()
attrs.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure)
attrs.InsertString(conventions.AttributeCloudInfrastructureService, conventions.AttributeCloudProviderAzureVM)
attrs.InsertString(conventions.AttributeCloudRegion, "myCloudRegion")
attrs.InsertString(conventions.AttributeHostID, "myHostID")
attrs.InsertString(conventions.AttributeCloudAccount, "myCloudAccount")
attrs.InsertString("azure.resourcegroup.name", "myResourcegroupName")
attrs.InsertString("azure.vm.size", "42")
return res
}()
hostResource = func() pdata.Resource {
res := pdata.NewResource()
attr := res.Attributes()
Expand Down Expand Up @@ -123,6 +184,42 @@ func TestResourceToHostID(t *testing.T) {
},
ok: true,
},
{
name: "azure",
args: args{azureResource},
want: HostID{
Key: "azure_resource_id",
ID: "mycloudaccount/myresourcegroupname/microsoft.compute/virtualmachines/myhostname",
},
ok: true,
},
{
name: "azure scaleset",
args: args{azureScalesetResource},
want: HostID{
Key: "azure_resource_id",
ID: "mycloudaccount/myresourcegroupname/microsoft.compute/virtualmachinescalesets/myvmscalesetname/virtualmachines/1",
},
ok: true,
},
{
name: "azure cloud account missing",
args: args{azureMissingCloudAcct},
want: HostID{},
ok: false,
},
{
name: "azure resource group missing",
args: args{azureMissingResourceGroup},
want: HostID{},
ok: false,
},
{
name: "azure hostname missing",
args: args{azureMissingHostName},
want: HostID{},
ok: false,
},
{
name: "ec2 attributes missing",
args: args{ec2PartialResource},
Expand Down Expand Up @@ -159,3 +256,13 @@ func TestResourceToHostID(t *testing.T) {
})
}
}

func TestAzureID(t *testing.T) {
attrs := pdata.NewAttributeMap()
attrs.Insert("azure.resourcegroup.name", pdata.NewAttributeValueString("myResourceGroup"))
attrs.Insert("azure.vm.scaleset.name", pdata.NewAttributeValueString("myScalesetName"))
attrs.Insert(conventions.AttributeHostName, pdata.NewAttributeValueString("myScalesetName_1"))
id := azureID(attrs, "myCloudAccount")
expected := "mycloudaccount/myresourcegroup/microsoft.compute/virtualmachinescalesets/myscalesetname/virtualmachines/1"
assert.Equal(t, expected, id)
}

0 comments on commit 7276360

Please sign in to comment.