From eca87c81a45be56636144d1e4f48f1da8498bcb9 Mon Sep 17 00:00:00 2001 From: Marcela Bonell Date: Thu, 23 Feb 2017 18:33:51 -0600 Subject: [PATCH] MyFirstApp: Durability section for gophercloud Adding the code for interact with the object storage service with go. Change-Id: I4f994b6f8ccfca0ab858a062c9243c3a66197ddd --- firstapp/samples/gophercloud/durability.go | 158 +++++++++++++++++++++ firstapp/source/durability.rst | 66 +++++++++ 2 files changed, 224 insertions(+) create mode 100644 firstapp/samples/gophercloud/durability.go diff --git a/firstapp/samples/gophercloud/durability.go b/firstapp/samples/gophercloud/durability.go new file mode 100644 index 000000000..5061a33d9 --- /dev/null +++ b/firstapp/samples/gophercloud/durability.go @@ -0,0 +1,158 @@ +package main + +import ( + "bufio" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack" + "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" + "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects" + "github.com/gophercloud/gophercloud/pagination" +) + +func main() { + + // step-1 + authOpts, err := openstack.AuthOptionsFromEnv() + if err != nil { + fmt.Println(err) + return + } + + provider, err := openstack.AuthenticatedClient(authOpts) + if err != nil { + fmt.Println(err) + return + } + + var regionName = os.Getenv("OS_REGION_NAME") + objectClient, err := openstack.NewObjectStorageV1(provider, gophercloud.EndpointOpts{ + Region: regionName, + }) + if err != nil { + fmt.Println(err) + return + } + + // step-2 + containerName := "fractals" + containers.Create(objectClient, containerName, nil) + + // step-3 + containers.List(objectClient, &containers.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + containerList, _ := containers.ExtractNames(page) + for _, name := range containerList { + fmt.Printf("Container name [%s] \n", name) + } + return true, nil + }) + + // step-4 + filePath := "goat.jpg" + objectName := "an amazing goat" + + f, _ := os.Open(filePath) + defer f.Close() + reader := bufio.NewReader(f) + + options := objects.CreateOpts{ + Content: reader, + } + + objects.Create(objectClient, containerName, objectName, options) + + // step-5 + objects.List(objectClient, containerName, &objects.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + objectList, _ := objects.ExtractNames(page) + for _, name := range objectList { + fmt.Printf("Object name [%s] \n", name) + } + return true, nil + }) + + // step-6 + + // step-7 + + // step-8 + objects.Delete(objectClient, containerName, objectName, nil) + + // step-9 + + // step-10 + containerName = "fractals" + containers.Create(objectClient, containerName, nil) + + // step-11 + endpoint := "http://IP_API_1" + + resp, _ := http.Get(endpoint + "/v1/fractal") + defer resp.Body.Close() + body, _ := ioutil.ReadAll(resp.Body) + + type Fractal struct { + UUID string `json:"uuid"` + } + + type Data struct { + Results int `json:"num_results"` + Objects []Fractal `json:"objects"` + Page int `json:"page"` + TotalPages int `json:"total_pages"` + } + + var data Data + json.Unmarshal([]byte(body), &data) + + for _, fractal := range data.Objects { + r, _ := http.Get(endpoint + "/fractal/" + fractal.UUID) + defer r.Body.Close() + image := fractal.UUID + ".png" + out, _ := os.Create(image) + defer out.Close() + io.Copy(out, r.Body) + + f, _ := os.Open(image) + defer f.Close() + reader := bufio.NewReader(f) + + options := objects.CreateOpts{ + Content: reader, + } + + objectName = fractal.UUID + fmt.Printf("Uploading object [%s] in container [%s]... \n", objectName, containerName) + objects.Create(objectClient, containerName, objectName, options) + } + + objects.List(objectClient, containerName, &objects.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + objectList, _ := objects.ExtractNames(page) + for _, name := range objectList { + fmt.Printf("Object [%s] in container [%s] \n", name, containerName) + } + return true, nil + }) + + // step-12 + objects.List(objectClient, containerName, &objects.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + objectList, _ := objects.ExtractNames(page) + for _, name := range objectList { + fmt.Printf("Deleting object [%s] in container [%s]... \n", name, containerName) + objects.Delete(objectClient, containerName, name, nil) + } + return true, nil + }) + fmt.Printf("Deleting container [%s] \n", containerName) + containers.Delete(objectClient, containerName) + + // step-13 + objects.Update(objectClient, containerName, objectName, &objects.UpdateOpts{Metadata: map[string]string{"foo": "bar"}}) + + // step-14 +} diff --git a/firstapp/source/durability.rst b/firstapp/source/durability.rst index b904a7090..3e57c2e7e 100644 --- a/firstapp/source/durability.rst +++ b/firstapp/source/durability.rst @@ -123,6 +123,13 @@ First, learn how to connect to the Object Storage endpoint: :start-after: step-1 :end-before: step-2 +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-1 + :end-before: step-2 + To begin to store objects, we must first make a container. Call yours :code:`fractals`: @@ -173,6 +180,12 @@ Call yours :code:`fractals`: u'txc6262b9c2bc1445b9dfe3-00574277ff', u'date': u'Mon, 23 May 2016 03:24:47 GMT', u'content-type': u'text/plain; charset=utf-8'}) +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-2 + :end-before: step-3 You should now be able to see this container appear in a listing of all containers in your account: @@ -219,6 +232,13 @@ all containers in your account: [Munch({u'count': 0, u'bytes': 0, u'name': u'fractals'}), Munch({u'count': 0, u'bytes': 0, u'name': u'fractals_segments'})] + .. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-3 + :end-before: step-4 + The next logical step is to upload an object. Find a photo of a goat online, name it :code:`goat.jpg`, and upload it to your :code:`fractals` container: @@ -248,6 +268,13 @@ online, name it :code:`goat.jpg`, and upload it to your :start-after: step-4 :end-before: step-5 +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-4 + :end-before: step-5 + List objects in your :code:`fractals` container to see if the upload was successful. Then, download the file to verify that the md5sum is the same: @@ -364,6 +391,13 @@ the same: d1408b5bf6510426db6e2bafc2f90854 +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-5 + :end-before: step-6 + Finally, clean up by deleting the test object: .. only:: fog @@ -421,6 +455,12 @@ Finally, clean up by deleting the test object: [] +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-8 + :end-before: step-9 Back up the Fractals from the database on the Object Storage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -455,6 +495,13 @@ Place the images in the :code:`fractals` container: :start-after: step-10 :end-before: step-11 +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-10 + :end-before: step-11 + Next, back up all existing fractals from the database to the swift container. A simple loop takes care of that: @@ -502,6 +549,12 @@ A simple loop takes care of that: Before you try to run the previous script, make sure that it is installed on your system. +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-11 + :end-before: step-12 Configure the Fractals app to use Object Storage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -544,6 +597,13 @@ Otherwise, the delete operation fails: :start-after: step-12 :end-before: step-13 +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-12 + :end-before: step-13 + .. warning:: It is not possible to restore deleted objects. Be careful. Add metadata to objects @@ -598,6 +658,12 @@ your SDK. :start-after: step-13 :end-before: step-14 +.. only:: gophercloud + + .. literalinclude:: ../samples/gophercloud/durability.go + :language: go + :start-after: step-13 + :end-before: step-14 Large objects ~~~~~~~~~~~~~