Skip to content

Instantly share code, notes, and snippets.

@moorage
Last active June 28, 2018 05:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moorage/a7300dee720e694aa89fd152b2b2c69d to your computer and use it in GitHub Desktop.
Save moorage/a7300dee720e694aa89fd152b2b2c69d to your computer and use it in GitHub Desktop.
Zip all the google cloud storage files with a prefix, and upload it back into the prefix.
var StorageBucket string // google storage bucket name
var PrefixToZip string // the prefix you want to zip
var ArchiveZipFilename string // the ultimate name of the zipfile, e.g. archive.zip
var GoogleCloudClientOption option.ClientOption // can load creds from a json file with this, e.g. GoogleCloudClientOption = option.WithCredentialsFile(jsonFile)
var LogContext string // additional logging string
// Download all files & zip (named ArchiveZipFilename) from gcloud prefix (PrefixToZip)
func main() {
ctx := &context.Background()
client, serr := storage.NewClient(ctx)
if GoogleCloudClientOption != nil {
client, serr = storage.NewClient(ctx, GoogleCloudClientOption)
}
if serr != nil {
reportError(serr)
os.Exit(1)
}
objects := []*storage.ObjectAttrs{}
it := client.Bucket(StorageBucket).Objects(*ctx,
&storage.Query{
Prefix: PrefixToZip, // no delim, to pickup sub folders
},
)
for {
objectAttrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
reportError(err)
os.Exit(1)
}
objects = append(objects, objectAttrs)
}
if len(objects) < 1 {
reportError(fmt.Errorf("No objects found in storage folder bucket(%s)/%v", StorageBucket, PrefixToZip))
os.Exit(1)
}
// create storage file for writing
zipFileURI := PrefixToZip + "/" + ArchiveZipFilename
storageWriter := client.Bucket(StorageBucket).Object(zipFileURI).NewWriter(*ctx)
storageWriter.ContentType = "application/zip"
defer storageWriter.Close()
// Create a new zip archive to memory buffer
zipWriter := zip.NewWriter(storageWriter)
// go through each file in the prefix
for _, obj := range objects {
log.Printf("Packing file %v of size %v to zip file", obj.Name, obj.Size)
storageReader, rerr := client.Bucket(StorageBucket).Object(obj.Name).NewReader(*ctx)
if rerr != nil {
reportError(fmt.Errorf("unable to open file from bucket %s, file %q: `%+v`", StorageBucket, obj.Name, rerr))
continue
}
// make all paths relative
relativeFilename, rerr := filepath.Rel("/"+PrefixToZip, "/"+obj.Name)
if rerr != nil {
reportError(rerr)
storageReader.Close()
continue
}
// add filename to zip
zipFile, zerr := zipWriter.Create(relativeFilename)
if zerr != nil {
reportError(zerr)
storageReader.Close()
continue
}
// copy from storage reader to zip writer
_, cerr := io.Copy(zipFile, storageReader)
if cerr != nil {
reportError(cerr)
storageReader.Close()
continue
}
storageReader.Close()
}
err := zipWriter.Close()
if err != nil {
reportError(fmt.Errorf("Packing failed to close zip file writer from bucket %q file %q : %v", StorageBucket, zipFileURI, err))
storageWriter.Close()
os.Exit(1)
}
storageWriter.Close() // we should be uploaded by here
}
func reportError(err error) { // I typically notify other services here, hence the convenience function...
errorMsg := fmt.Sprintf("{\"error\": \"%v\", \"trace\":\"%v\",\"context\":\"%s\"}", err, debug.Stack(), LogContext)
log.Printf("[ERROR] %+v\n", errorMsg)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment