Skip to content

Commit b62ecac

Browse files
Migrate opentsdb string fields to int (#401)
This fixes a migration bug introduced by #398 We unfortunately have to add a schema migration function to convert the strings to int Since 1.20.0 is released, we cannot just go back to a string at this point, so a migration is the way forward Fixes #400 We should release 1.20.1 once that's merged
1 parent 2828480 commit b62ecac

File tree

2 files changed

+190
-4
lines changed

2 files changed

+190
-4
lines changed

grafana/resource_data_source.go

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ The required arguments for this resource vary depending on the type of data
2626
source selected (via the 'type' argument).
2727
`,
2828

29-
CreateContext: CreateDataSource,
30-
UpdateContext: UpdateDataSource,
31-
DeleteContext: DeleteDataSource,
32-
ReadContext: ReadDataSource,
29+
CreateContext: CreateDataSource,
30+
UpdateContext: UpdateDataSource,
31+
DeleteContext: DeleteDataSource,
32+
ReadContext: ReadDataSource,
33+
StateUpgraders: []schema.StateUpgrader{resourceDataSourceV0Upgrader},
34+
SchemaVersion: 1,
3335

3436
// Import either by ID or UID
3537
Importer: &schema.ResourceImporter{
@@ -704,3 +706,59 @@ func makeSecureJSONData(d *schema.ResourceData) gapi.SecureJSONData {
704706
TLSClientKey: d.Get("secure_json_data.0.tls_client_key").(string),
705707
}
706708
}
709+
710+
// TSDB Version and Resolution used to be strings, but now are integers.
711+
func resourceDataSourceV0Schema() *schema.Resource {
712+
return &schema.Resource{
713+
Schema: map[string]*schema.Schema{
714+
"json_data": {
715+
Type: schema.TypeList,
716+
Optional: true,
717+
Elem: &schema.Resource{
718+
Schema: map[string]*schema.Schema{
719+
"tsdb_resolution": {
720+
Type: schema.TypeInt,
721+
Optional: true,
722+
Description: "(OpenTSDB) Resolution.",
723+
},
724+
"tsdb_version": {
725+
Type: schema.TypeInt,
726+
Optional: true,
727+
Description: "(OpenTSDB) Version.",
728+
},
729+
},
730+
},
731+
},
732+
},
733+
}
734+
}
735+
736+
var resourceDataSourceV0Upgrader = schema.StateUpgrader{
737+
Version: 0,
738+
Type: resourceDataSourceV0Schema().CoreConfigSchema().ImpliedType(),
739+
Upgrade: func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
740+
convertToInt := func(m map[string]interface{}, key string) {
741+
if value, hasValue := m[key]; hasValue {
742+
m[key] = 0
743+
if valueStr, ok := value.(string); ok {
744+
if valueInt, err := strconv.Atoi(valueStr); err == nil {
745+
m[key] = valueInt
746+
}
747+
}
748+
}
749+
}
750+
751+
var jsonData map[string]interface{}
752+
if jsonDataList, ok := rawState["json_data"].([]interface{}); ok && len(jsonDataList) > 0 {
753+
jsonData = jsonDataList[0].(map[string]interface{})
754+
} else if jsonDataMap, ok := rawState["json_data"].(map[string]interface{}); ok {
755+
jsonData = jsonDataMap
756+
}
757+
if jsonData != nil {
758+
convertToInt(jsonData, "tsdb_version")
759+
convertToInt(jsonData, "tsdb_resolution")
760+
}
761+
762+
return rawState, nil
763+
},
764+
}

grafana/resource_data_source_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package grafana
22

33
import (
44
"fmt"
5+
"reflect"
56
"strconv"
67
"testing"
78

@@ -566,6 +567,133 @@ func TestAccDataSource_basic(t *testing.T) {
566567
}
567568
}
568569

570+
func TestDatasourceMigrationV0(t *testing.T) {
571+
cases := []struct {
572+
name string
573+
state map[string]interface{}
574+
expected map[string]interface{}
575+
}{
576+
{
577+
name: "no json data",
578+
state: map[string]interface{}{
579+
"name": "test",
580+
"type": "prometheus",
581+
},
582+
expected: map[string]interface{}{
583+
"name": "test",
584+
"type": "prometheus",
585+
},
586+
},
587+
{
588+
name: "no tsdb fields",
589+
state: map[string]interface{}{
590+
"name": "test",
591+
"type": "prometheus",
592+
"json_data": []map[string]interface{}{
593+
{
594+
"url": "http://localhost:9090",
595+
},
596+
},
597+
},
598+
expected: map[string]interface{}{
599+
"name": "test",
600+
"type": "prometheus",
601+
"json_data": []map[string]interface{}{
602+
{
603+
"url": "http://localhost:9090",
604+
},
605+
},
606+
},
607+
},
608+
{
609+
name: "nil or empty tsdb fields",
610+
state: map[string]interface{}{
611+
"name": "test",
612+
"type": "test",
613+
"json_data": []map[string]interface{}{
614+
{
615+
"tsdb_version": "",
616+
"tsdb_resolution": nil,
617+
"url": "http://localhost:9090",
618+
},
619+
},
620+
},
621+
expected: map[string]interface{}{
622+
"name": "test",
623+
"type": "test",
624+
"json_data": []map[string]interface{}{
625+
{
626+
"tsdb_version": 0,
627+
"tsdb_resolution": 0,
628+
"url": "http://localhost:9090",
629+
},
630+
},
631+
},
632+
},
633+
{
634+
name: "already int",
635+
state: map[string]interface{}{
636+
"name": "test",
637+
"type": "test",
638+
"json_data": []map[string]interface{}{
639+
{
640+
"tsdb_version": 0,
641+
"tsdb_resolution": 2,
642+
"url": "http://localhost:9090",
643+
},
644+
},
645+
},
646+
expected: map[string]interface{}{
647+
"name": "test",
648+
"type": "test",
649+
"json_data": []map[string]interface{}{
650+
{
651+
"tsdb_version": 0,
652+
"tsdb_resolution": 2,
653+
"url": "http://localhost:9090",
654+
},
655+
},
656+
},
657+
},
658+
{
659+
name: "migration",
660+
state: map[string]interface{}{
661+
"name": "test",
662+
"type": "test",
663+
"json_data": []map[string]interface{}{
664+
{
665+
"tsdb_version": "0",
666+
"tsdb_resolution": "2",
667+
"url": "http://localhost:9090",
668+
},
669+
},
670+
},
671+
expected: map[string]interface{}{
672+
"name": "test",
673+
"type": "test",
674+
"json_data": []map[string]interface{}{
675+
{
676+
"tsdb_version": 0,
677+
"tsdb_resolution": 2,
678+
"url": "http://localhost:9090",
679+
},
680+
},
681+
},
682+
},
683+
}
684+
for _, tc := range cases {
685+
t.Run(tc.name, func(t *testing.T) {
686+
actual, err := resourceDataSourceV0Upgrader.Upgrade(nil, tc.expected, nil)
687+
if err != nil {
688+
t.Fatal(err)
689+
}
690+
if !reflect.DeepEqual(actual, tc.expected) {
691+
t.Errorf("Expected %#v, got %#v", tc.expected, actual)
692+
}
693+
})
694+
}
695+
}
696+
569697
func testAccDataSourceCheckExists(rn string, dataSource *gapi.DataSource) resource.TestCheckFunc {
570698
return func(s *terraform.State) error {
571699
rs, ok := s.RootModule().Resources[rn]

0 commit comments

Comments
 (0)