How to use Vultr Object Storage in Go
Introduction
Vultr Object Storage is a highly scalable, S3-Compatible cloud object storage solution for storing files or objects. This guide explains how to use Vultr Object Storage in Go with GoVultr v2, and how to manage Buckets inside Object Storage with AWS SDK for Go.
Prerequisites
You will need:
- A computer workstation running on Linux, Windows, or macOS
- The latest version of Go installed on your computer workstation
These examples use the Linux $
prompt, but the commands also work on Mac and Windows.
Manage Vultr Object Storage with Go
Generate an API key from your API Settings by enabling your API.
Warning: Keep your API key secured. Your API key has access to your entire Vultr account, and publicly exposing your API key may compromise your account.
Create a new project folder.
$ mkdir ObjectStorage
Change the directory to the new folder.
$ cd ObjectStorage
Initialize the module.
$ go mod init ObjectStorage
Install GoVultr v2.
$ go get -u github.com/vultr/govultr/v2
Install oAuth2 for Go.
$ go get golang.org/x/oauth2
Set your API key as an environment variable. Replace
YOUR-API-KEY-HERE
with your API Key found on your API Settings.Linux and macOS workstations run:
$ export VULTR_API_KEY=YOUR-API-KEY-HERE
Windows workstations run:
C:\> setx VULTR_API_KEY "YOUR-API-KEY-HERE"
Use your preferred plain text editor to create and edit
main.go
. Linux users may usenano
, while Mac and Windows users might chooseTextEdit
orNotepad
.$ nano main.go
Paste the following code into
main.go
, which sets up themain
package and imports all the required packages.package main import ( "bufio" "context" "fmt" "log" "os" "strings" "time" "github.com/vultr/govultr/v2" "golang.org/x/oauth2" )
Paste the following code into
main.go
, which declares the global variables.var ( apiKey = os.Getenv("VULTR_API_KEY") vc *govultr.Client ctx = context.Background() input int input2 string loop string objStorageID string )
Paste the following code into
main.go
, which initializes oAuth2 config, TokenSource, and the Vultr Client.func init() { config := &oauth2.Config{} ts := config.TokenSource(ctx, &oauth2.Token{AccessToken: apiKey}) vc = govultr.NewClient(oauth2.NewClient(ctx, ts)) }
Object Storage Management with GoVultr
Populate your main.go
file with each of these functions. Each function is for a specific object storage operation.
Function: listClusters()
This function lists all object storage clusters. It stops the program if there are errors when listing clusters or if no clusters are found.
func listClusters() {
clusterList, meta, err := vc.ObjectStorage.ListCluster(ctx, nil)
if err != nil {
log.Panicf("Error listing clusters: %s", err)
}
if meta.Total <= 0 {
log.Panic("There are no clusters found to create an Object Storage.")
}
log.Printf("List of All Clusters: %+v", clusterList)
}
Function: createObjStorage()
This function creates an object storage in your selected cluster, then prints its complete information once it becomes active. It stops the program if there are any errors when creating an object storage.
This guide uses ClusterID 2
, which is Vultr's New Jersey Object Storage location, ewr1.vultrobjects.com
.
func createObjStorage() {
var objStorageName string
clusterID := 2
fmt.Print("Enter Your Desired Object Storage Name: ")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
objStorageName = scanner.Text()
fmt.Print()
if objStorageName != "" {
break
}
}
objStorageNew, errn := vc.ObjectStorage.Create(ctx, clusterID, objStorageName)
if errn != nil {
log.Panicf("Error creating storage: %s", errn)
} else {
log.Printf("Succesfully created an Object Storage with ID: %s", objStorageNew.ID)
}
for {
objStorageNewInfo, erri := vc.ObjectStorage.Get(ctx, objStorageNew.ID)
if erri != nil {
log.Panicf("Error getting Object Storage Information: %s", erri)
}
if objStorageNewInfo.Status == "active" {
log.Print("Your Object Storage is now Active.")
log.Printf("Object Storage Information: %+v", objStorageNewInfo)
log.Println("S3 Credentials: ")
log.Printf("Hostname: %s | Access Key: %s | Secret Key: %s", objStorageNewInfo.S3Hostname, objStorageNewInfo.S3AccessKey, objStorageNewInfo.S3SecretKey)
break
}
log.Printf("The Object Storage is currently %s. Waiting another ten seconds until it becomes active.", objStorageNewInfo.Status)
time.Sleep(time.Second * 10)
}
}
The function requires one user input: The user's desired name for the object storage. It then creates new object storage and checks the status of the newly created object storage every ten seconds until it becomes active. After the object storage's status becomes active, it displays its complete information.
Functions: listObjStorage1() and listObjStorage2()
These functions list all object storage in your account. There are two ways to display your object storage information.
First: list all object storage one by one, then display the data in JSON format.
func listObjStorage1() {
objStorageList, meta, err := vc.ObjectStorage.List(ctx, nil)
log.Printf("The Total Number of Object Storage: %d", meta.Total)
for x := 0; x != len(objStorageList); x++ {
log.Printf("Object Storage #%d:", x+1)
log.Printf("List of Object Storage: %+v", objStorageList[x])
log.Println()
}
if err != nil {
log.Panicf("Error listing Object Storage: %s", err)
}
}
This function displays the total number of active object storage in your account and their complete information in JSON format.
Second: list all object storage one by one, then display the data of each object storage by key-value pairs.
func listObjStorage2() {
objStorageList, meta, err := vc.ObjectStorage.List(ctx, nil)
log.Printf("The Total Number of Object Storage: %d", meta.Total)
for x := 0; x != len(objStorageList); x++ {
log.Printf("Object Storage #%d:", x+1)
log.Printf("Date Created: %s", objStorageList[x].DateCreated)
log.Printf("Object Storage ID: %s", objStorageList[x].ID)
log.Printf("Object Storage Label: %s", objStorageList[x].Label)
log.Printf("Object Storage Location: %s", objStorageList[x].Location)
log.Printf("Object Storage Region: %s", objStorageList[x].Region)
log.Printf("Object Storage Hostname: %s", objStorageList[x].S3Hostname)
log.Printf("Object Storage Access Key: %s", objStorageList[x].S3AccessKey)
log.Printf("Object Storage Secret Key: %s", objStorageList[x].S3SecretKey)
log.Printf("Object Storage Status: %s", objStorageList[x].Status)
log.Printf("Object Storage Cluster ID: %d", objStorageList[x].ObjectStoreClusterID)
log.Println()
}
if err != nil {
log.Panicf("Error listing Object Storage: %s", err)
}
}
This function displays the total number of active object storage in your account and their complete information. The Object Storage's ID is required when you want to manipulate Object Storage.
Function: getObjStorage()
This function displays the complete information of a specific object storage or stops the program if there is an error in getting your object storage's information.
func getObjStorage() {
fmt.Println("To Get your Object Storage's ID, List all of your Object Storage.")
fmt.Print("Enter Your Object Storage's ID to get its Full Information (e.g. cb676a46-66fd-4dfb-b839-443f2e6c0b60): ")
fmt.Scan(&objStorageID)
objStorageGet, err := vc.ObjectStorage.Get(ctx, objStorageID)
log.Printf("Full information of Object Storage with an ID \"%s\".", objStorageID)
log.Printf("Object Storage ID: %s", objStorageGet.ID)
log.Printf("Date Created: %s", objStorageGet.DateCreated)
log.Printf("Label: %s", objStorageGet.Label)
log.Printf("Location: %s", objStorageGet.Location)
log.Printf("Region: %s", objStorageGet.Region)
log.Printf("S3 Hostname: %s", objStorageGet.S3Hostname)
log.Printf("S3 Access Key: %s", objStorageGet.S3AccessKey)
log.Printf("S3 Secret Key: %s", objStorageGet.S3SecretKey)
log.Printf("Status: %s", objStorageGet.Status)
log.Printf("Cluster ID: %d", objStorageGet.ObjectStoreClusterID)
log.Println()
if err != nil {
log.Panicf("Error Getting Object Storage that has an ID %s: %s", objStorageID, err)
}
}
This function requires one user input: Your object storage's ID, which you can find when you list all your object storage.
Function: delObjStorage()
This function deletes a specific object storage.
func delObjStorage() {
fmt.Println("To Get your Object Storage's ID, List all of your Object Storage.")
fmt.Print("Enter the ID of the Object Storage that you want to Delete (e.g. cb676a46-66fd-4dfb-b839-443f2e6c0b60): ")
fmt.Scan(&objStorageID)
objStorageDel := vc.ObjectStorage.Delete(ctx, objStorageID)
if objStorageDel == nil {
log.Printf("Successfully deleted object storage with an ID \"%s\"", objStorageID)
}
}
This function requires one user input: The ID of the object storage that you want to delete.
Function: updateObjectStorage()
This function updates or changes the label of a specific object storage.
func updateObjectStorage() {
var newLabel string
fmt.Println("To Get your Object Storage's ID, List all of your Object Storage.")
fmt.Print("Enter the ID of the Object Storage that you want to Update the Label (e.g. cb676a46-66fd-4dfb-b839-443f2e6c0b60): ")
fmt.Scan(&objStorageID)
fmt.Print("Enter Your Desired New Object Storage Label: ")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
newLabel = scanner.Text()
fmt.Print()
if newLabel != "" {
break
}
}
objStorageUpdate := vc.ObjectStorage.Update(ctx, objStorageID, newLabel)
if objStorageUpdate == nil {
log.Printf("Succesfully updated the label of the object storage with an ID of: \"%s\"", objStorageID)
}
fmt.Print()
}
This function requires two user inputs: Your object storage's ID, which you can find when you list all your object storage, and your preferred new object storage label.
Function regenKeys()
This function will regenerate a new Access Key and Secret Key of a specific object storage.
func regenKeys() {
fmt.Println("To Get your Object Storage's ID, List all of your Object Storage.")
fmt.Print("Enter the ID of the Object Storage that you want to Regenerate Keys (e.g. cb676a46-66fd-4dfb-b839-443f2e6c0b60): ")
fmt.Scan(&objStorageID)
objStorageNewKeys, err := vc.ObjectStorage.RegenerateKeys(ctx, objStorageID)
log.Print("Successfully Regenerated new S3 Credentials.")
log.Printf("Your Object Storage's New S3 Credentials are: %v", objStorageNewKeys)
log.Printf("S3 Hostname: %s", objStorageNewKeys.S3Hostname)
log.Printf("S3 Access Key: %s", objStorageNewKeys.S3AccessKey)
log.Printf("S3 Secret Key: %s", objStorageNewKeys.S3SecretKey)
if err != nil {
log.Panicf("Error Regenerating New S3 Credentials: %v", err)
}
}
This function requires one user input: the ID of the object storage that you want to regenerate the keys.
Main Function
This function asks the user what object storage operation they would like to perform, then calls a specific function based on the user input.
func main() {
for {
fmt.Println("Input '1' to List All Object Storage Clusters.")
fmt.Println("Input '2' to Create an Object Storage.")
fmt.Println("Input '3' to List All Object Storage (Less Organized).")
fmt.Println("Input '4' to List All Object Storage (More Organized).")
fmt.Println("Input '5' to Get the Full Information of your Object Storage.")
fmt.Println("Input '6' to Delete an Object Storage.")
fmt.Println("Input '7' to Update an Object Storage's Label.")
fmt.Println("Input '8' to Regenerate Access Key and Secret Key of your Object Storage.")
fmt.Print("Your Input: ")
fmt.Scan(&input)
switch input {
case 1:
listClusters()
case 2:
createObjStorage()
case 3:
listObjStorage1()
case 4:
listObjStorage2()
case 5:
getObjStorage()
case 6:
delObjStorage()
case 7:
updateObjectStorage()
case 8:
regenKeys()
default:
fmt.Println("Invalid Input! Please try again.")
continue
}
fmt.Print("Do you want to rerun the program? (y/n): ")
fmt.Scan(&input2)
loop = strings.ToLower(input2)
if loop == "n" {
fmt.Println("Closing the Program...")
time.Sleep(2 * time.Second)
break
} else if loop == "y" {
continue
} else {
log.Fatal("Invalid Input! Closing the Program.")
time.Sleep(2 * time.Second)
}
}
}
Build the Object Storage Project
After you have populated the main.go
file with the example code, save and close the file. Then, compile the code into a binary executable file.
$ go build
Run the executable file, then select which object storage operation you like to perform.
$ ./ObjectStorage
Bucket Operations
To manage your Buckets, use the AWS SDK for Go.
Set up the Bucket Project Environment
Create a new project folder.
$ mkdir Bucket
Change the directory to the new folder.
$ cd Bucket
Initialize the module.
$ go mod init Bucket
Install AWS SDK for Go.
$ go get github.com/aws/aws-sdk-go
Install mimetype. This package is for setting the Content-Type of each file to be uploaded.
$ go get github.com/gabriel-vasile/mimetype
Get your Object Storage's Access key and Secret Key from Vultr's website, or list all your object storage using the
ObjectStorage
program above.Set your Object Storage's Access key and Secret key as environment variables. Replace
YOUR-ACCESS-KEY-HERE
andYOUR-SECRET-KEY-HERE
with your object storage's Access key and Secret key.Linux and macOS workstations run:
$ export ACCESS_KEY=YOUR-ACCESS-KEY-HERE $ export SECRET_KEY=YOUR-SECRET-KEY-HERE
Windows workstations run:
C:\> setx ACCESS_KEY "YOUR-ACCESS-KEY-HERE" C:\> setx SECRET_KEY "YOUR-SECRET-KEY-HERE"
Use your preferred plain text editor to create and edit
main.go
. Linux users may usenano
, while Mac and Windows users might chooseTextEdit
orNotepad
.$ nano main.go
Paste the following code into
main.go
, which sets up themain
package and imports all the required packages.package main import ( "fmt" "io/ioutil" "log" "os" "path" "regexp" "strings" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/gabriel-vasile/mimetype" )
Paste the following code into
main.go
, which declares the global variables.var ( s3Vultr *s3.S3 accessKey = os.Getenv("ACCESS_KEY") secretKey = os.Getenv("SECRET_KEY") bucketName string directory string filename string input int input2 string loop string )
Paste the following code into
main.go
, which initializes the Vultr S3 session.func init() { s3Vultr = s3.New(session.Must(session.NewSession(&aws.Config{ Region: aws.String("ewr"), Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""), Endpoint: aws.String("https://ewr1.vultrobjects.com/"), }))) }
Bucket Operations using AWS SDK for Go
Populate your main.go
file with each of these functions. Each function is for a specific bucket operation.
Function: listAllBuckets()
This function lists all the buckets in your object storage.
func listAllBuckets() (ret *s3.ListBucketsOutput) {
ret, err := s3Vultr.ListBuckets(&s3.ListBucketsInput{})
if err != nil {
panic(err)
}
return ret
}
Function: createBucket()
This function has two helper functions, nameCheck()
and newBucket()
. It creates a bucket in your object storage or stops the program if the bucket name already exists. It requires one user input: Your preferred name for your bucket. If your input bucket name does not meet the criteria for naming a bucket, it will ask you to reinput another bucket name.
func nameCheck(str string) bool {
checker := regexp.MustCompile(`^[a-z0-9-]*$`).MatchString(str)
alphanumeric := "abcdefghijklmnopqrstuvwxyz1234567890"
if checker && strings.Contains(alphanumeric, string(str[0])) && len(str) >= 3 && len(str) <= 63 {
return true
} else {
return false
}
}
func newBucket() (ret *s3.CreateBucketOutput) {
_, err := s3Vultr.CreateBucket(&s3.CreateBucketInput{
Bucket: aws.String(bucketName),
CreateBucketConfiguration: &s3.CreateBucketConfiguration{
LocationConstraint: aws.String(""),
},
})
if awsError, ok := err.(awserr.Error); ok {
if awsError.Code() == s3.ErrCodeBucketAlreadyExists {
log.Fatalf("Bucket %q already exists. Error: %v", bucketName, awsError.Code())
}
} else {
log.Printf("Successfully created bucket %q", bucketName)
}
return ret
}
func createBucket() (ret *s3.CreateBucketOutput) {
for {
fmt.Println("Bucket names are unique to their location and must meet the following criteria:")
fmt.Println("Only lowercase and starts with a letter or number. No spaces.")
fmt.Println("Bucket name may contain dashes")
fmt.Println("Must be between 3 and 63 characters long.")
fmt.Print("Enter your preferred Name for the Bucket: ")
fmt.Scan(&bucketName)
if nameCheck(bucketName) {
break
} else {
fmt.Printf("%q does not meet the criteria above. Please try again.", bucketName)
fmt.Print("\n\n")
continue
}
}
bucketList := listAllBuckets()
if len(bucketList.Buckets) != 0 {
for _, bucket := range bucketList.Buckets {
if bucketName == *bucket.Name {
log.Fatalf("Bucket %q already exists and is owned by you.", bucketName)
} else {
newBucket()
break
}
}
} else {
newBucket()
}
return ret
}
The createBucket()
function checks if your input bucket name already exists and is owned by you, then it calls the nameCheck()
function and the newBucket()
function.
The nameCheck()
function checks the user's input bucket name to see if it meets the criteria for naming a bucket and asks again if it does not. It uses the regexp
package to check if the input only contains lowercase letters, numbers, and dashes. To check if the input starts with a letter or a number, it uses the strings
package's strings.Contains()
. It also checks if the input length is between 3 and 63 characters long.
The newBucket()
function tries to create a new bucket if the input bucket name does not exist and returns an error otherwise.
Function: uploadObject()
This function uploads a file or an object to a specific bucket. It requires three user inputs: The bucket name where you want to store the file, the path or directory where you want to put the files in the bucket, and last is the path of the file that you want to upload.
func uploadObject() (ret *s3.PutObjectOutput) {
fmt.Print("Enter the name of the bucket where you want to upload the File/Object: ")
fmt.Scan(&bucketName)
fmt.Print("Enter the Path or Directory where you want to upload the File/Object in the bucket: (e.g., assets/css/): ")
fmt.Scan(&directory)
fmt.Print("Enter the Path to the file that you want to upload (e.g., css/styles.css): ")
fmt.Scan(&filename)
f, err := os.Open(filename)
if err != nil {
panic(err)
}
var mtype2 string
if strings.Contains(filename, ".css") {
mtype2 = "text/css"
} else {
mtype, errmime := mimetype.DetectFile(filename)
if errmime != nil {
log.Fatalf("Error getting Content-Type: %v", errmime)
}
mtype2 = mtype.String()
}
log.Println("Uploading Object:", filename)
ret, err = s3Vultr.PutObject(&s3.PutObjectInput{
Body: f,
Bucket: aws.String(bucketName),
Key: aws.String(path.Join(directory, strings.Split(filename, "/")[strings.Count(filename, "/")])),
ACL: aws.String("public-read"),
ContentType: aws.String(mtype2),
})
if err != nil {
panic(err)
} else {
log.Printf("File %q was Uploaded Successfully.", filename)
}
return ret
}
Your file's Canned Access Control List (ACL) is set to private by default, which means no one except you has access to it. To serve your files appropriately, you must Grant Public Read Access and set your file's content type correctly. The field ACL
with the value public-read
grants all users a READ access and the owner a FULL CONTROL. When you upload files to your bucket, the default Content Type is usually application/octet-stream
. To automatically set your file's content type, the program used the mimetype package to detect each file's MIME type or content type. See this list of supported MIME types for your reference. Notice that CSS is not in the list of supported MIME types, so it is set using strings.Contains()
. If the filename has a .css
extension, it sets the content type to text/css
.
Function: listObjects()
This function lists all files or objects in a bucket. It requires one user input: the bucket's name to list its files.
func listObjects() (ret *s3.ListObjectsV2Output) {
fmt.Print("Enter the name of the bucket to list its file/s: ")
fmt.Scan(&bucketName)
ret, err := s3Vultr.ListObjectsV2(&s3.ListObjectsV2Input{
Bucket: aws.String(bucketName),
})
if err != nil {
panic(err)
}
return ret
}
Function: getObject()
This function downloads a file or an object from a bucket into the same directory where your main.go
or binary executable file is. It requires three user inputs: The bucket name, the directory or path of the file, and the name of the file you want to download.
func getObject() {
fmt.Print("Enter the name of the bucket that contains the file that you want to download: ")
fmt.Scan(&bucketName)
fmt.Print("Enter the Path or Directory of the file (e.g. assets/css/): ")
fmt.Scan(&directory)
fmt.Print("Enter the name of the file that you want to download(e.g., styles.css): ")
fmt.Scan(&filename)
log.Println("Downloading: ", filename)
ret, err := s3Vultr.GetObject(&s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(path.Join(directory, strings.Split(filename, "/")[strings.Count(filename, "/")])),
})
if err != nil {
panic(err)
}
body, _ := ioutil.ReadAll(ret.Body)
err = ioutil.WriteFile(filename, body, 0644)
if err != nil {
panic(err)
}
log.Println("File Downloaded Successfully.")
}
This function reads the file inside a bucket using ioutil.ReadAll()
, then writes the returned data using ioutil.WriteFile()
. It saves the file as filename
, with a 644
permission which means the owner has Read and Write access, while the group and others only have Read access.
Function: deleteObject()
This function deletes a file or an object from a bucket. It requires three user inputs: the name of the bucket that contains the file you want to delete, the path or directory of the file in the bucket, and the name of the file you want to delete.
func deleteObject() (ret *s3.DeleteObjectOutput) {
fmt.Print("Enter the name of the bucket that contains the file that you want to delete: ")
fmt.Scan(&bucketName)
fmt.Print("Enter the Path or Directory of the file in the bucket (e.g., assets/css/): ")
fmt.Scan(&directory)
fmt.Print("Enter the name of the file that you want to delete (e.g., styles.css): ")
fmt.Scan(&filename)
log.Println("Deleting: ", filename)
ret, err := s3Vultr.DeleteObject(&s3.DeleteObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(path.Join(directory, strings.Split(filename, "/")[strings.Count(filename, "/")])),
})
if err != nil {
panic(err)
} else {
log.Printf("%q deleted Successfully", filename)
}
return ret
}
Function: deleteAllObjects()
This function deletes all files or objects in a bucket. It requires one user input: The Name of the Bucket that you want to empty. This function can be useful when you want to delete a bucket since you must delete all of its contents before you can delete it.
func deleteAllObjects() {
fmt.Scan(&bucketName)
objectList, errList := s3Vultr.ListObjectsV2(&s3.ListObjectsV2Input{
Bucket: aws.String(bucketName),
})
if errList != nil {
log.Fatalf("Error Listing objects: %v", errList)
}
for _, object := range objectList.Contents {
log.Printf("Deleting %v", *object.Key)
_, err := s3Vultr.DeleteObject(&s3.DeleteObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(*object.Key),
})
log.Printf("%v Deleted Successfully", *object.Key)
if err != nil {
log.Fatalf("Error Deleteing Objects.")
}
}
log.Println("All Files deleted successfully.")
}
This function lists all the bucket's contents first, and then it gets the Key of each object to be used to delete each file.
Function: deleteBucket()
This function deletes a bucket from your object storage. It requires one user input: the name of the bucket you want to delete.
func deleteBucket() (ret *s3.DeleteBucketOutput) {
deleteAllObjects()
ret, err := s3Vultr.DeleteBucket(&s3.DeleteBucketInput{
Bucket: aws.String(bucketName),
})
if err != nil {
if awsError, ok := err.(awserr.Error); ok {
switch awsError.Code() {
case s3.ErrCodeNoSuchBucket:
log.Fatalf("No Bucket exists with the name '%s'", bucketName)
log.Println()
default:
panic(err)
}
}
}
log.Printf("Bucket %q deleted Successfully.", bucketName)
return ret
}
This function calls the deleteAllObjects()
first to delete all of its contents because you must empty the bucket before you can delete it.
Bucket Main Function
The main()
function asks the user what bucket operation they would like to perform, then calls a specific function based on the user input.
func main() {
for {
fmt.Println("Input '1' to List All Buckets in your Object Storage.")
fmt.Println("Input '2' to Create a new Bucket.")
fmt.Println("Input '3' to Delete a Bucket.")
fmt.Println("Input '4' to Upload a File/Object.")
fmt.Println("Input '5' to List All Files/Objects inside a Bucket.")
fmt.Println("Input '6' to Download a File/Object from a Bucket.")
fmt.Println("Input '7' to Delete a File/Object from a Bucket.")
fmt.Println("Input '8' to Delete All Files/Objects from a Bucket.")
fmt.Print("Your Input: ")
fmt.Scan(&input)
switch input {
case 1:
log.Println(listAllBuckets())
case 2:
createBucket()
case 3:
fmt.Print("Enter the Name of the Bucket that you want to Delete: ")
deleteBucket()
case 4:
uploadObject()
case 5:
log.Println(listObjects())
case 6:
getObject()
case 7:
deleteObject()
case 8:
fmt.Print("Enter the Name of the Bucket that you want to Empty: ")
deleteAllObjects()
default:
log.Println("Invalid Input! Please try again.")
continue
}
fmt.Print("Do you want to rerun the program? (y/n): ")
fmt.Scan(&input2)
loop = strings.ToLower(input2)
if loop == "n" {
fmt.Println("Closing the Program...")
time.Sleep(2 * time.Second)
break
} else if loop == "y" {
continue
} else {
log.Fatalln("Invalid Input! Closing the Program.")
time.Sleep(2 * time.Second)
}
}
}
Build the Bucket Project
After you have populated the main.go
file with the example code, save and close the file. Then, compile the code into a binary executable file.
$ go build
Run the executable file, then select which bucket operation you like to perform.
$ ./Bucket
Serving Static Files with Vultr Object Storage
You must do two important things to serve static files with Vultr Object Storage. First, you have to Grant Public Read Access to all your static files. And second, you need to set the correct Content Type for each file, or else your files will be downloaded when you visit your static files' URL.
In this example, you will create a sample HTML and CSS static files and host them with Vultr Object Storage.
You will use the same project
Bucket
and the same executable fileBucket.exe
to create a bucket and upload files because its settings (Canned ACL and Content-Type) are set to Grant public read access and to set the content type automatically.$ cd Bucket
Create an HTML file named
index.html
.$ nano index.html
Paste this sample HTML Code to your
index.html
file, then save and exit the file.<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="css/style.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>This is a Sample Static File Hosted with Vultr Object Storage</title> </head> <body> <h1>This is a Heading 1</h1> <h2>This is a Heading 2</h2> <h3>This is a Heading 3</h3> <h4>This is a Heading 4</h4> <h5>This is a Heading 5</h5> <h6>This is a Heading 6</h6> <p>This is a Sample Static File Hosted with Vultr Object Storage.</p> </body> </html>
Create a folder named
css
.Create a CSS file named
style.css
inside thecss
folder.$ nano css/style.css
Paste this sample CSS Code to your
style.css
file, then save and exit the file.h1 {color: blue;} h2 {color: red;} h3 {color: green;} h4 {background-color: blue;} h5 {background-color: red;} h6 {background-color: green;}
Run the binary executable file
Bucket.exe
.$ ./Bucket
Create a New Bucket. Enter
2
to create a new Bucket, then name the bucket asmy-static-hosting
or any bucket name you prefer.Here is the sample execution:
Input '1' to List All Buckets in your Object Storage. Input '2' to Create a new Bucket. Input '3' to Delete a Bucket. Input '4' to Upload a File/Object. Input '5' to List All Files/Objects inside a Bucket. Input '6' to Download a File/Object from a Bucket. Input '7' to Delete a File/Object from a Bucket. Input '8' to Delete All Files/Objects from a Bucket. Your Input: 2 Bucket names are unique to their location and must meet the following criteria: Only lowercase and starts with a letter or number. No spaces. Bucket name may contain dashes Must be between 3 and 63 characters long. Enter your preferred name for the Bucket: my-static-hosting 2022/07/29 17:31:45 Successfully created bucket "my-static-hosting" Do you want to rerun the program? (y/n): n Closing the Program...
Upload your
index.html
file andstyle.css
file. RunBucket.exe
again, then enter4
to upload a file. Rerun the program when prompted because you have to upload two files.Here is the sample program execution:
$ ./Bucket Input '1' to List All Buckets in your Object Storage. Input '2' to Create a new Bucket. Input '3' to Delete a Bucket. Input '4' to Upload a File/Object. Input '5' to List All Files/Objects inside a Bucket. Input '6' to Download a File/Object from a Bucket. Input '7' to Delete a File/Object from a Bucket. Input '8' to Delete All Files/Objects from a Bucket. Your Input: 4 Enter the name of the bucket where you want to upload the File/Object: my-static-hosting Enter the Path or Directory where you want to upload the File/Object in the bucket: (e.g., assets/css/): / Enter the Path to the file that you want to upload (e.g., css/styles.css): index.html 2022/07/29 17:36:03 Uploading Object: index.html 2022/07/29 17:36:04 File "index.html" was Uploaded Successfully. Do you want to rerun the program? (y/n): y Input '1' to List All Buckets in your Object Storage. Input '2' to Create a new Bucket. Input '3' to Delete a Bucket. Input '4' to Upload a File/Object. Input '5' to List All Files/Objects inside a Bucket. Input '6' to Download a File/Object from a Bucket. Input '7' to Delete a File/Object from a Bucket. Input '8' to Delete All Files/Objects from a Bucket. Your Input: 4 Enter the name of the bucket where you want to upload the File/Object: my-static-hosting Enter the Path or Directory where you want to upload the File/Object in the bucket: (e.g., assets/css/): css/ Enter the Path to the file that you want to upload (e.g., css/styles.css): css/style.css 2022/07/29 17:36:16 Uploading Object: css/style.css 2022/07/29 17:36:17 File "css/style.css" was Uploaded Successfully. Do you want to rerun the program? (y/n): n Closing the Program...
In your web browser, navigate to
https://bucketname.ewr1.vultrobjects.com/filename
. For example,https://my-static-hosting.ewr1.vultrobjects.com/index.html
.Notice that your HTML static files are displayed and not downloaded when you visit the file's URL. The linked CSS stylesheet is applied as well.
You may upload other media types such as images, videos, and so on to further test serving static files with Vultr Object Storage.
More Information
To learn more about Vultr Object Storage, GoVultr V2, Vultr API v2, and AWS SDK for Go, please see these resources: