]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/go-getter/get_gcs.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / go-getter / get_gcs.go
1 package getter
2
3 import (
4 "context"
5 "fmt"
6 "net/url"
7 "os"
8 "path/filepath"
9 "strings"
10
11 "cloud.google.com/go/storage"
12 "google.golang.org/api/iterator"
13 )
14
15 // GCSGetter is a Getter implementation that will download a module from
16 // a GCS bucket.
17 type GCSGetter struct {
18 getter
19 }
20
21 func (g *GCSGetter) ClientMode(u *url.URL) (ClientMode, error) {
22 ctx := g.Context()
23
24 // Parse URL
25 bucket, object, err := g.parseURL(u)
26 if err != nil {
27 return 0, err
28 }
29
30 client, err := storage.NewClient(ctx)
31 if err != nil {
32 return 0, err
33 }
34 iter := client.Bucket(bucket).Objects(ctx, &storage.Query{Prefix: object})
35 for {
36 obj, err := iter.Next()
37 if err != nil && err != iterator.Done {
38 return 0, err
39 }
40
41 if err == iterator.Done {
42 break
43 }
44 if strings.HasSuffix(obj.Name, "/") {
45 // A directory matched the prefix search, so this must be a directory
46 return ClientModeDir, nil
47 } else if obj.Name != object {
48 // A file matched the prefix search and doesn't have the same name
49 // as the query, so this must be a directory
50 return ClientModeDir, nil
51 }
52 }
53 // There are no directories or subdirectories, and if a match was returned,
54 // it was exactly equal to the prefix search. So return File mode
55 return ClientModeFile, nil
56 }
57
58 func (g *GCSGetter) Get(dst string, u *url.URL) error {
59 ctx := g.Context()
60
61 // Parse URL
62 bucket, object, err := g.parseURL(u)
63 if err != nil {
64 return err
65 }
66
67 // Remove destination if it already exists
68 _, err = os.Stat(dst)
69 if err != nil && !os.IsNotExist(err) {
70 return err
71 }
72 if err == nil {
73 // Remove the destination
74 if err := os.RemoveAll(dst); err != nil {
75 return err
76 }
77 }
78
79 // Create all the parent directories
80 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
81 return err
82 }
83
84 client, err := storage.NewClient(ctx)
85 if err != nil {
86 return err
87 }
88
89 // Iterate through all matching objects.
90 iter := client.Bucket(bucket).Objects(ctx, &storage.Query{Prefix: object})
91 for {
92 obj, err := iter.Next()
93 if err != nil && err != iterator.Done {
94 return err
95 }
96 if err == iterator.Done {
97 break
98 }
99
100 if !strings.HasSuffix(obj.Name, "/") {
101 // Get the object destination path
102 objDst, err := filepath.Rel(object, obj.Name)
103 if err != nil {
104 return err
105 }
106 objDst = filepath.Join(dst, objDst)
107 // Download the matching object.
108 err = g.getObject(ctx, client, objDst, bucket, obj.Name)
109 if err != nil {
110 return err
111 }
112 }
113 }
114 return nil
115 }
116
117 func (g *GCSGetter) GetFile(dst string, u *url.URL) error {
118 ctx := g.Context()
119
120 // Parse URL
121 bucket, object, err := g.parseURL(u)
122 if err != nil {
123 return err
124 }
125
126 client, err := storage.NewClient(ctx)
127 if err != nil {
128 return err
129 }
130 return g.getObject(ctx, client, dst, bucket, object)
131 }
132
133 func (g *GCSGetter) getObject(ctx context.Context, client *storage.Client, dst, bucket, object string) error {
134 rc, err := client.Bucket(bucket).Object(object).NewReader(ctx)
135 if err != nil {
136 return err
137 }
138 defer rc.Close()
139
140 // Create all the parent directories
141 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
142 return err
143 }
144
145 f, err := os.Create(dst)
146 if err != nil {
147 return err
148 }
149 defer f.Close()
150
151 _, err = Copy(ctx, f, rc)
152 return err
153 }
154
155 func (g *GCSGetter) parseURL(u *url.URL) (bucket, path string, err error) {
156 if strings.Contains(u.Host, "googleapis.com") {
157 hostParts := strings.Split(u.Host, ".")
158 if len(hostParts) != 3 {
159 err = fmt.Errorf("URL is not a valid GCS URL")
160 return
161 }
162
163 pathParts := strings.SplitN(u.Path, "/", 5)
164 if len(pathParts) != 5 {
165 err = fmt.Errorf("URL is not a valid GCS URL")
166 return
167 }
168 bucket = pathParts[3]
169 path = pathParts[4]
170 }
171 return
172 }