github.com/gophercloud/gophercloud@v1.11.0/internal/acceptance/openstack/objectstorage/v1/versioning_test.go (about) 1 //go:build acceptance 2 // +build acceptance 3 4 package v1 5 6 import ( 7 "strings" 8 "testing" 9 10 "github.com/gophercloud/gophercloud/internal/acceptance/clients" 11 "github.com/gophercloud/gophercloud/internal/acceptance/tools" 12 "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" 13 "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects" 14 th "github.com/gophercloud/gophercloud/testhelper" 15 ) 16 17 func TestObjectsVersioning(t *testing.T) { 18 clients.SkipReleasesBelow(t, "stable/ussuri") 19 20 client, err := clients.NewObjectStorageV1Client() 21 if err != nil { 22 t.Fatalf("Unable to create client: %v", err) 23 } 24 25 // Make a slice of length numObjects to hold the random object names. 26 oNames := make([]string, numObjects) 27 for i := 0; i < len(oNames); i++ { 28 oNames[i] = tools.RandomString("test-object-", 8) 29 } 30 31 // Create a container to hold the test objects. 32 cName := tools.RandomString("test-container-", 8) 33 opts := containers.CreateOpts{ 34 VersionsEnabled: true, 35 } 36 header, err := containers.Create(client, cName, opts).Extract() 37 th.AssertNoErr(t, err) 38 t.Logf("Create container headers: %+v\n", header) 39 40 // Defer deletion of the container until after testing. 41 defer func() { 42 res := containers.Delete(client, cName) 43 th.AssertNoErr(t, res.Err) 44 }() 45 46 // ensure versioning is enabled 47 get, err := containers.Get(client, cName, nil).Extract() 48 th.AssertNoErr(t, err) 49 t.Logf("Get container headers: %+v\n", get) 50 th.AssertEquals(t, true, get.VersionsEnabled) 51 52 // Create a slice of buffers to hold the test object content. 53 oContents := make([]string, numObjects) 54 oContentVersionIDs := make([]string, numObjects) 55 for i := 0; i < numObjects; i++ { 56 oContents[i] = tools.RandomString("", 10) 57 createOpts := objects.CreateOpts{ 58 Content: strings.NewReader(oContents[i]), 59 } 60 obj, err := objects.Create(client, cName, oNames[i], createOpts).Extract() 61 th.AssertNoErr(t, err) 62 oContentVersionIDs[i] = obj.ObjectVersionID 63 } 64 oNewContents := make([]string, numObjects) 65 for i := 0; i < numObjects; i++ { 66 oNewContents[i] = tools.RandomString("", 10) 67 createOpts := objects.CreateOpts{ 68 Content: strings.NewReader(oNewContents[i]), 69 } 70 _, err := objects.Create(client, cName, oNames[i], createOpts).Extract() 71 th.AssertNoErr(t, err) 72 } 73 // Delete the objects after testing two times. 74 defer func() { 75 // disable object versioning 76 opts := containers.UpdateOpts{ 77 VersionsEnabled: new(bool), 78 } 79 header, err := containers.Update(client, cName, opts).Extract() 80 th.AssertNoErr(t, err) 81 82 t.Logf("Update container headers: %+v\n", header) 83 84 // ensure versioning is disabled 85 get, err := containers.Get(client, cName, nil).Extract() 86 th.AssertNoErr(t, err) 87 t.Logf("Get container headers: %+v\n", get) 88 th.AssertEquals(t, false, get.VersionsEnabled) 89 90 // delete all object versions before deleting the container 91 currentVersionIDs := make([]string, numObjects) 92 for i := 0; i < numObjects; i++ { 93 opts := objects.DeleteOpts{ 94 ObjectVersionID: oContentVersionIDs[i], 95 } 96 obj, err := objects.Delete(client, cName, oNames[i], opts).Extract() 97 th.AssertNoErr(t, err) 98 currentVersionIDs[i] = obj.ObjectCurrentVersionID 99 } 100 for i := 0; i < numObjects; i++ { 101 opts := objects.DeleteOpts{ 102 ObjectVersionID: currentVersionIDs[i], 103 } 104 res := objects.Delete(client, cName, oNames[i], opts) 105 th.AssertNoErr(t, res.Err) 106 } 107 }() 108 109 // List created objects 110 listOpts := objects.ListOpts{ 111 Full: true, 112 Prefix: "test-object-", 113 } 114 115 allPages, err := objects.List(client, cName, listOpts).AllPages() 116 if err != nil { 117 t.Fatalf("Unable to list objects: %v", err) 118 } 119 120 ons, err := objects.ExtractNames(allPages) 121 if err != nil { 122 t.Fatalf("Unable to extract objects: %v", err) 123 } 124 th.AssertEquals(t, len(ons), len(oNames)) 125 126 ois, err := objects.ExtractInfo(allPages) 127 if err != nil { 128 t.Fatalf("Unable to extract object info: %v", err) 129 } 130 th.AssertEquals(t, len(ois), len(oNames)) 131 132 // List all created objects 133 listOpts = objects.ListOpts{ 134 Full: true, 135 Prefix: "test-object-", 136 Versions: true, 137 } 138 139 allPages, err = objects.List(client, cName, listOpts).AllPages() 140 if err != nil { 141 t.Fatalf("Unable to list objects: %v", err) 142 } 143 144 ons, err = objects.ExtractNames(allPages) 145 if err != nil { 146 t.Fatalf("Unable to extract objects: %v", err) 147 } 148 th.AssertEquals(t, len(ons), 2*len(oNames)) 149 150 ois, err = objects.ExtractInfo(allPages) 151 if err != nil { 152 t.Fatalf("Unable to extract object info: %v", err) 153 } 154 th.AssertEquals(t, len(ois), 2*len(oNames)) 155 156 // ensure proper versioning attributes are set 157 for i, obj := range ois { 158 if i%2 == 0 { 159 th.AssertEquals(t, true, obj.IsLatest) 160 } else { 161 th.AssertEquals(t, false, obj.IsLatest) 162 } 163 if obj.VersionID == "" { 164 t.Fatalf("Unexpected empty version_id for the %s object", obj.Name) 165 } 166 } 167 168 // Download one of the objects that was created above. 169 downloadres := objects.Download(client, cName, oNames[0], nil) 170 th.AssertNoErr(t, downloadres.Err) 171 172 o1Content, err := downloadres.ExtractContent() 173 th.AssertNoErr(t, err) 174 175 // Compare the two object's contents to test that the copy worked. 176 th.AssertEquals(t, oNewContents[0], string(o1Content)) 177 178 // Download the another object that was create above. 179 downloadOpts := objects.DownloadOpts{ 180 Newest: true, 181 } 182 downloadres = objects.Download(client, cName, oNames[1], downloadOpts) 183 th.AssertNoErr(t, downloadres.Err) 184 o2Content, err := downloadres.ExtractContent() 185 th.AssertNoErr(t, err) 186 187 // Compare the two object's contents to test that the copy worked. 188 th.AssertEquals(t, oNewContents[1], string(o2Content)) 189 }