/pkg/provider/terraform/instance/softlayer_test.go

https://github.com/docker/infrakit · Go · 235 lines · 211 code · 16 blank · 8 comment · 0 complexity · 5e82aeb1927db5cb0a1410e5b12b69ee MD5 · raw file

  1. package instance // import "github.com/docker/infrakit/pkg/provider/terraform/instance"
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/docker/infrakit/pkg/provider/ibmcloud/client"
  6. "github.com/docker/infrakit/pkg/spi/flavor"
  7. "github.com/softlayer/softlayer-go/datatypes"
  8. "github.com/softlayer/softlayer-go/filter"
  9. "github.com/stretchr/testify/require"
  10. )
  11. func TestMergeLabelsIntoTagSliceEmpty(t *testing.T) {
  12. result := mergeLabelsIntoTagSlice([]interface{}{}, map[string]string{})
  13. require.Equal(t, []string{}, result)
  14. }
  15. func TestMergeLabelsIntoTagSliceTagsOnly(t *testing.T) {
  16. result := mergeLabelsIntoTagSlice(
  17. []interface{}{
  18. "tag1:val1",
  19. "tag2:val2",
  20. },
  21. map[string]string{},
  22. )
  23. require.Len(t, result, 2)
  24. require.Contains(t, result, "tag1:val1")
  25. require.Contains(t, result, "tag2:val2")
  26. }
  27. func TestMergeLabelsIntoTagSliceLabelsOnly(t *testing.T) {
  28. result := mergeLabelsIntoTagSlice(
  29. []interface{}{},
  30. map[string]string{
  31. "label1": "val1",
  32. "label2": "val2",
  33. },
  34. )
  35. require.Len(t, result, 2)
  36. require.Contains(t, result, "label1:val1")
  37. require.Contains(t, result, "label2:val2")
  38. }
  39. func TestMergeLabelsIntoTagSlice(t *testing.T) {
  40. result := mergeLabelsIntoTagSlice(
  41. []interface{}{
  42. "tag1:val1",
  43. "tag2:val2",
  44. },
  45. map[string]string{
  46. "label1": "val1",
  47. "label2": "val2",
  48. },
  49. )
  50. require.Len(t, result, 4)
  51. require.Contains(t, result, "tag1:val1")
  52. require.Contains(t, result, "tag2:val2")
  53. require.Contains(t, result, "label1:val1")
  54. require.Contains(t, result, "label2:val2")
  55. }
  56. func TestFilterVMsByTagsEmpty(t *testing.T) {
  57. vms := []datatypes.Virtual_Guest{}
  58. filterVMsByTags(&vms, []string{})
  59. require.Equal(t, []datatypes.Virtual_Guest{}, vms)
  60. }
  61. func TestGetUniqueVMByTagsEmpty(t *testing.T) {
  62. id, err := getUniqueVMByTags([]datatypes.Virtual_Guest{}, []string{})
  63. require.NoError(t, err)
  64. require.Nil(t, id)
  65. }
  66. func TestGetUniqueVMByTagsOneMatch(t *testing.T) {
  67. vmID := 123
  68. vmTagName := "some-tag"
  69. vmTag := datatypes.Tag{Name: &vmTagName}
  70. vms := []datatypes.Virtual_Guest{{Id: &vmID, TagReferences: []datatypes.Tag_Reference{{Tag: &vmTag}}}}
  71. id, err := getUniqueVMByTags(vms, []string{vmTagName})
  72. require.NoError(t, err)
  73. require.Equal(t, vmID, *id)
  74. }
  75. func TestGetUniqueVMByTagsOneMatchNilID(t *testing.T) {
  76. vmTagName := "some-tag"
  77. vmHostname := "some-hostname"
  78. vmTag := datatypes.Tag{Name: &vmTagName}
  79. vms := []datatypes.Virtual_Guest{
  80. {
  81. Hostname: &vmHostname,
  82. TagReferences: []datatypes.Tag_Reference{{Tag: &vmTag}},
  83. },
  84. }
  85. id, err := getUniqueVMByTags(vms, []string{vmTagName})
  86. require.Equal(t, "VM 'some-hostname' missing ID", err.Error())
  87. require.Nil(t, id)
  88. }
  89. func TestGetUniqueVMByTagsTwoMatches(t *testing.T) {
  90. vmID1 := 123
  91. vmID2 := 234
  92. vmTagName := "some-tag"
  93. vmTag := datatypes.Tag{Name: &vmTagName}
  94. vms := []datatypes.Virtual_Guest{
  95. {Id: &vmID1, TagReferences: []datatypes.Tag_Reference{{Tag: &vmTag}}},
  96. {Id: &vmID2, TagReferences: []datatypes.Tag_Reference{{Tag: &vmTag}}},
  97. }
  98. id, err := getUniqueVMByTags(vms, []string{vmTagName})
  99. require.Equal(t,
  100. fmt.Sprintf("Only a single VM should match tags, but VMs %v match tags: %v", []int{vmID1, vmID2}, []string{vmTagName}),
  101. err.Error())
  102. require.Nil(t, id)
  103. }
  104. // getVMs is a utility function to get datatypes.Virtual_Guest with tags
  105. func getVMs() []datatypes.Virtual_Guest {
  106. vmID0 := 0
  107. vmID1 := 1
  108. vmID2 := 2
  109. vmID3 := 3
  110. tag1Name := "tag1"
  111. tag1 := datatypes.Tag{Name: &tag1Name}
  112. tag2Name := "tag2"
  113. tag2 := datatypes.Tag{Name: &tag2Name}
  114. tag3Name := "tag3"
  115. tag3 := datatypes.Tag{Name: &tag3Name}
  116. vms := []datatypes.Virtual_Guest{
  117. {
  118. TagReferences: []datatypes.Tag_Reference{},
  119. Id: &vmID0,
  120. },
  121. {
  122. TagReferences: []datatypes.Tag_Reference{{Tag: &tag1}},
  123. Id: &vmID1,
  124. },
  125. {
  126. TagReferences: []datatypes.Tag_Reference{{Tag: &tag1}, {Tag: &tag2}},
  127. Id: &vmID2,
  128. },
  129. {
  130. TagReferences: []datatypes.Tag_Reference{{Tag: &tag1}, {Tag: &tag2}, {Tag: &tag3}},
  131. Id: &vmID3,
  132. },
  133. }
  134. return vms
  135. }
  136. func TestFilterVMsByTags(t *testing.T) {
  137. // No tags given, everything matches
  138. vms := getVMs()
  139. filterVMsByTags(&vms, []string{})
  140. require.Len(t, vms, 4)
  141. require.Equal(t, 0, *vms[0].Id)
  142. require.Equal(t, 1, *vms[1].Id)
  143. require.Equal(t, 2, *vms[2].Id)
  144. require.Equal(t, 3, *vms[3].Id)
  145. // Empty tag, nothing matches
  146. vms = getVMs()
  147. filterVMsByTags(&vms, []string{""})
  148. require.Len(t, vms, 0)
  149. // 1 tag matches
  150. vms = getVMs()
  151. filterVMsByTags(&vms, []string{"tag1"})
  152. require.Len(t, vms, 3)
  153. require.Equal(t, 1, *vms[0].Id)
  154. require.Equal(t, 2, *vms[1].Id)
  155. require.Equal(t, 3, *vms[2].Id)
  156. // 2 tags match
  157. vms = getVMs()
  158. filterVMsByTags(&vms, []string{"tag1", "tag2"})
  159. require.Len(t, vms, 2)
  160. require.Equal(t, 2, *vms[0].Id)
  161. require.Equal(t, 3, *vms[1].Id)
  162. // 3 tags match
  163. vms = getVMs()
  164. filterVMsByTags(&vms, []string{"tag1", "tag2", "tag3"})
  165. require.Len(t, vms, 1)
  166. require.Equal(t, 3, *vms[0].Id)
  167. // A tag that doesn't match
  168. vms = getVMs()
  169. filterVMsByTags(&vms, []string{"tag1", "foo"})
  170. require.Len(t, vms, 0)
  171. }
  172. func TestGetIBMCloudVMByTagAPIError(t *testing.T) {
  173. fake := client.FakeSoftlayer{
  174. GetVirtualGuestsStub: func(mask, filters *string) (resp []datatypes.Virtual_Guest, err error) {
  175. return []datatypes.Virtual_Guest{}, fmt.Errorf("Custom error")
  176. },
  177. }
  178. b, err := GetIBMCloudVMByTag(&fake, nil)
  179. require.Error(t, err)
  180. require.Equal(t, "Custom error", err.Error())
  181. require.Empty(t, b)
  182. }
  183. func TestGetIBMCloudVMByTagNoVMs(t *testing.T) {
  184. vmID1 := 1
  185. vmID2 := 2
  186. tag1Val := "tag1:val1"
  187. tag1 := datatypes.Tag{Name: &tag1Val}
  188. tagClusterIDVal := flavor.ClusterIDTag + ":my-cluster-id"
  189. tag2 := datatypes.Tag{Name: &tagClusterIDVal}
  190. tag3Val := "tag1:no-match"
  191. tag3 := datatypes.Tag{Name: &tag3Val}
  192. fake := client.FakeSoftlayer{
  193. GetVirtualGuestsStub: func(mask, filters *string) (resp []datatypes.Virtual_Guest, err error) {
  194. return []datatypes.Virtual_Guest{
  195. {
  196. TagReferences: []datatypes.Tag_Reference{{Tag: &tag1}, {Tag: &tag2}},
  197. Id: &vmID1,
  198. },
  199. {
  200. TagReferences: []datatypes.Tag_Reference{{Tag: &tag2}, {Tag: &tag3}},
  201. Id: &vmID2,
  202. },
  203. }, nil
  204. },
  205. }
  206. tags := []string{"tag1:val1", flavor.ClusterIDTag + ":my-cluster-id"}
  207. id, err := GetIBMCloudVMByTag(&fake, tags)
  208. require.NoError(t, err)
  209. require.Equal(t, vmID1, *id)
  210. // Verify args
  211. expectedMask := "id,hostname,tagReferences[id,tag[name]]"
  212. expectedFilter := filter.New(filter.Path("virtualGuests.tagReferences.tag.name").Eq(flavor.ClusterIDTag + ":my-cluster-id")).Build()
  213. require.Equal(t,
  214. []struct {
  215. Mask *string
  216. Filters *string
  217. }{{&expectedMask, &expectedFilter}},
  218. fake.GetVirtualGuestsArgs)
  219. }