mirror of
https://github.com/grafana/grafana.git
synced 2024-12-23 15:40:19 -06:00
Cloudwatch: Fix parsing for ec2 resource attributes (#96501)
This commit is contained in:
parent
420db99d16
commit
fcd88d356c
@ -97,39 +97,13 @@ func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context,
|
||||
dupCheck := make(map[string]bool)
|
||||
for _, reservation := range instances.Reservations {
|
||||
for _, instance := range reservation.Instances {
|
||||
tags := make(map[string]string)
|
||||
for _, tag := range instance.Tags {
|
||||
tags[*tag.Key] = *tag.Value
|
||||
data, found, err := getInstanceAttributeValue(attributeName, instance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var data string
|
||||
if strings.Index(attributeName, "Tags.") == 0 {
|
||||
tagName := attributeName[5:]
|
||||
data = tags[tagName]
|
||||
} else {
|
||||
attributePath := strings.Split(attributeName, ".")
|
||||
v := reflect.ValueOf(instance)
|
||||
for _, key := range attributePath {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil, errors.New("invalid attribute path")
|
||||
}
|
||||
v = v.FieldByName(key)
|
||||
if !v.IsValid() {
|
||||
return nil, errors.New("invalid attribute path")
|
||||
}
|
||||
}
|
||||
if attr, ok := v.Interface().(*string); ok {
|
||||
data = *attr
|
||||
} else if attr, ok := v.Interface().(*time.Time); ok {
|
||||
data = attr.String()
|
||||
} else {
|
||||
return nil, errors.New("invalid attribute path")
|
||||
}
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, exists := dupCheck[data]; exists {
|
||||
continue
|
||||
}
|
||||
@ -146,6 +120,54 @@ func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context,
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getInstanceAttributeValue(attributeName string, instance *ec2.Instance) (value string, found bool, err error) {
|
||||
tags := make(map[string]string)
|
||||
for _, tag := range instance.Tags {
|
||||
tags[*tag.Key] = *tag.Value
|
||||
}
|
||||
|
||||
var data string
|
||||
if strings.Index(attributeName, "Tags.") == 0 {
|
||||
tagName := attributeName[5:]
|
||||
data = tags[tagName]
|
||||
} else {
|
||||
attributePath := strings.Split(attributeName, ".")
|
||||
v := reflect.ValueOf(instance)
|
||||
for _, key := range attributePath {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return "", false, nil
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
return "", false, errors.New("invalid attribute path")
|
||||
}
|
||||
v = v.FieldByName(key)
|
||||
if !v.IsValid() {
|
||||
return "", false, errors.New("invalid attribute path")
|
||||
}
|
||||
}
|
||||
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
return "", false, nil
|
||||
}
|
||||
if attr, ok := v.Interface().(*string); ok {
|
||||
data = *attr
|
||||
} else if attr, ok := v.Interface().(*time.Time); ok {
|
||||
data = attr.String()
|
||||
} else if _, ok := v.Interface().(*bool); ok {
|
||||
data = fmt.Sprint(v.Elem().Bool())
|
||||
} else if v.Kind() == reflect.Ptr && v.Elem().CanInt() {
|
||||
data = fmt.Sprint(v.Elem().Int())
|
||||
} else {
|
||||
return "", false, errors.New("cannot parse attribute")
|
||||
}
|
||||
}
|
||||
|
||||
return data, true, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, pluginCtx backend.PluginContext, parameters url.Values) ([]suggestData, error) {
|
||||
region := parameters.Get("region")
|
||||
resourceType := parameters.Get("resourceType")
|
||||
|
@ -80,6 +80,86 @@ func TestQuery_InstanceAttributes(t *testing.T) {
|
||||
}
|
||||
assert.Equal(t, expResponse, resp)
|
||||
})
|
||||
|
||||
t.Run("Get different types", func(t *testing.T) {
|
||||
var expectedInt int64 = 3
|
||||
var expectedBool = true
|
||||
var expectedArn = "arn"
|
||||
cli = oldEC2Client{
|
||||
reservations: []*ec2.Reservation{
|
||||
{
|
||||
Instances: []*ec2.Instance{
|
||||
{
|
||||
AmiLaunchIndex: &expectedInt,
|
||||
EbsOptimized: &expectedBool,
|
||||
IamInstanceProfile: &ec2.IamInstanceProfile{
|
||||
Arn: &expectedArn,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
return DataSource{Settings: models.CloudWatchSettings{}, sessions: &fakeSessionCache{}}, nil
|
||||
})
|
||||
|
||||
executor := newExecutor(im, log.NewNullLogger())
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
attributeName string
|
||||
expResponse []suggestData
|
||||
}{
|
||||
{
|
||||
"int field",
|
||||
"AmiLaunchIndex",
|
||||
[]suggestData{
|
||||
{Text: "3", Value: "3", Label: "3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"bool field",
|
||||
"EbsOptimized",
|
||||
[]suggestData{
|
||||
{Text: "true", Value: "true", Label: "true"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"nested field",
|
||||
"IamInstanceProfile.Arn",
|
||||
[]suggestData{
|
||||
{Text: expectedArn, Value: expectedArn, Label: expectedArn},
|
||||
},
|
||||
},
|
||||
{
|
||||
"nil field",
|
||||
"InstanceLifecycle",
|
||||
[]suggestData{},
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
filterMap := map[string][]string{}
|
||||
filterJson, err := json.Marshal(filterMap)
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := executor.handleGetEc2InstanceAttribute(
|
||||
context.Background(),
|
||||
backend.PluginContext{
|
||||
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
|
||||
}, url.Values{
|
||||
"region": []string{"us-east-1"},
|
||||
"attributeName": []string{tc.attributeName},
|
||||
"filters": []string{string(filterJson)},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.expResponse, resp)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestQuery_EBSVolumeIDs(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user