ImageService v2: Collect all properties of images (#376)
* ImageService v2: Add VirtualSize field
* ImageService v2: Have Images.Properties collect all remaining fields
Related-PROD: PROD-28126
Change-Id: Ib6311d3bafc1e5e6e6a2c6d043d2a63a1eaa96cf
diff --git a/acceptance/openstack/imageservice/v2/images_test.go b/acceptance/openstack/imageservice/v2/images_test.go
index 5fe1c16..7f06faa 100644
--- a/acceptance/openstack/imageservice/v2/images_test.go
+++ b/acceptance/openstack/imageservice/v2/images_test.go
@@ -7,8 +7,62 @@
"gerrit.mcp.mirantis.net/debian/gophercloud.git/acceptance/clients"
"gerrit.mcp.mirantis.net/debian/gophercloud.git/acceptance/tools"
+ "gerrit.mcp.mirantis.net/debian/gophercloud.git/openstack/imageservice/v2/images"
+ "gerrit.mcp.mirantis.net/debian/gophercloud.git/pagination"
)
+func TestImagesListEachPage(t *testing.T) {
+ client, err := clients.NewImageServiceV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create an image service client: %v", err)
+ }
+
+ listOpts := images.ListOpts{
+ Limit: 1,
+ }
+
+ pager := images.List(client, listOpts)
+ err = pager.EachPage(func(page pagination.Page) (bool, error) {
+ images, err := images.ExtractImages(page)
+ if err != nil {
+ t.Fatalf("Unable to extract images: %v", err)
+ }
+
+ for _, image := range images {
+ tools.PrintResource(t, image)
+ tools.PrintResource(t, image.Properties)
+ }
+
+ return true, nil
+ })
+}
+
+func TestImagesListAllPages(t *testing.T) {
+ client, err := clients.NewImageServiceV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create an image service client: %v", err)
+ }
+
+ listOpts := images.ListOpts{
+ Limit: 1,
+ }
+
+ allPages, err := images.List(client, listOpts).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to retrieve all images: %v", err)
+ }
+
+ allImages, err := images.ExtractImages(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract images: %v", err)
+ }
+
+ for _, image := range allImages {
+ tools.PrintResource(t, image)
+ tools.PrintResource(t, image.Properties)
+ }
+}
+
func TestImagesCreateDestroyEmptyImage(t *testing.T) {
client, err := clients.NewImageServiceV2Client()
if err != nil {
diff --git a/openstack/imageservice/v2/images/results.go b/openstack/imageservice/v2/images/results.go
index 8f46463..e670076 100644
--- a/openstack/imageservice/v2/images/results.go
+++ b/openstack/imageservice/v2/images/results.go
@@ -7,6 +7,7 @@
"time"
"gerrit.mcp.mirantis.net/debian/gophercloud.git"
+ "gerrit.mcp.mirantis.net/debian/gophercloud.git/internal"
"gerrit.mcp.mirantis.net/debian/gophercloud.git/pagination"
)
@@ -63,7 +64,7 @@
Metadata map[string]string `json:"metadata"`
// Properties is a set of key-value pairs, if any, that are associated with the image.
- Properties map[string]string `json:"properties"`
+ Properties map[string]interface{} `json:"-"`
// CreatedAt is the date when the image has been created.
CreatedAt time.Time `json:"created_at"`
@@ -77,6 +78,9 @@
// Schema is the path to the JSON-schema that represent the image or image entity.
Schema string `json:"schema"`
+
+ // VirtualSize is the virtual size of the image
+ VirtualSize int64 `json:"virtual_size"`
}
func (r *Image) UnmarshalJSON(b []byte) error {
@@ -102,6 +106,17 @@
return fmt.Errorf("Unknown type for SizeBytes: %v (value: %v)", reflect.TypeOf(t), t)
}
+ // Bundle all other fields into Properties
+ var result interface{}
+ err = json.Unmarshal(b, &result)
+ if err != nil {
+ return err
+ }
+ if resultMap, ok := result.(map[string]interface{}); ok {
+ delete(resultMap, "self")
+ r.Properties = internal.RemainingKeys(Image{}, resultMap)
+ }
+
return err
}
diff --git a/openstack/imageservice/v2/images/testing/fixtures.go b/openstack/imageservice/v2/images/testing/fixtures.go
index 0f74929..ca0987d 100644
--- a/openstack/imageservice/v2/images/testing/fixtures.go
+++ b/openstack/imageservice/v2/images/testing/fixtures.go
@@ -43,7 +43,10 @@
"owner": "cba624273b8344e59dd1fd18685183b0",
"virtual_size": null,
"min_ram": 0,
- "schema": "/v2/schemas/image"
+ "schema": "/v2/schemas/image",
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi"
}`}
images[1] = imageEntry{"cirros-0.3.4-x86_64-uec-ramdisk",
`{
@@ -65,7 +68,10 @@
"owner": "cba624273b8344e59dd1fd18685183b0",
"virtual_size": null,
"min_ram": 0,
- "schema": "/v2/schemas/image"
+ "schema": "/v2/schemas/image",
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi"
}`}
images[2] = imageEntry{"cirros-0.3.4-x86_64-uec-kernel",
`{
@@ -87,7 +93,10 @@
"owner": "cba624273b8344e59dd1fd18685183b0",
"virtual_size": null,
"min_ram": 0,
- "schema": "/v2/schemas/image"
+ "schema": "/v2/schemas/image",
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi"
}`}
th.Mux.HandleFunc("/images", func(w http.ResponseWriter, r *http.Request) {
@@ -187,7 +196,10 @@
"schema": "/v2/schemas/image",
"size": 0,
"checksum": "",
- "virtual_size": 0
+ "virtual_size": 0,
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi"
}`)
})
}
@@ -261,7 +273,10 @@
"size": 13167616,
"min_ram": 0,
"schema": "/v2/schemas/image",
- "virtual_size": "None"
+ "virtual_size": null,
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi"
}`)
})
}
@@ -323,7 +338,10 @@
"min_disk": 0,
"disk_format": "",
"virtual_size": 0,
- "container_format": ""
+ "container_format": "",
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi"
}`)
})
}
diff --git a/openstack/imageservice/v2/images/testing/requests_test.go b/openstack/imageservice/v2/images/testing/requests_test.go
index e8f7d6a..ad4b88b 100644
--- a/openstack/imageservice/v2/images/testing/requests_test.go
+++ b/openstack/imageservice/v2/images/testing/requests_test.go
@@ -102,11 +102,17 @@
Owner: owner,
- Visibility: images.ImageVisibilityPrivate,
- File: file,
- CreatedAt: createdDate,
- UpdatedAt: lastUpdate,
- Schema: schema,
+ Visibility: images.ImageVisibilityPrivate,
+ File: file,
+ CreatedAt: createdDate,
+ UpdatedAt: lastUpdate,
+ Schema: schema,
+ VirtualSize: 0,
+ Properties: map[string]interface{}{
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi",
+ },
}
th.AssertDeepEquals(t, &expectedImage, actualImage)
@@ -204,12 +210,18 @@
Protected: false,
Visibility: images.ImageVisibilityPublic,
- Checksum: checksum,
- SizeBytes: sizeBytes,
- File: file,
- CreatedAt: createdDate,
- UpdatedAt: lastUpdate,
- Schema: schema,
+ Checksum: checksum,
+ SizeBytes: sizeBytes,
+ File: file,
+ CreatedAt: createdDate,
+ UpdatedAt: lastUpdate,
+ Schema: schema,
+ VirtualSize: 0,
+ Properties: map[string]interface{}{
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi",
+ },
}
th.AssertDeepEquals(t, &expectedImage, actualImage)
@@ -269,6 +281,12 @@
CreatedAt: createdDate,
UpdatedAt: lastUpdate,
Schema: schema,
+ VirtualSize: 0,
+ Properties: map[string]interface{}{
+ "hw_disk_bus": "scsi",
+ "hw_disk_bus_model": "virtio-scsi",
+ "hw_scsi_model": "virtio-scsi",
+ },
}
th.AssertDeepEquals(t, &expectedImage, actualImage)