Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
iloveicedgreentea committed Oct 1, 2021
0 parents commit 677c872
Show file tree
Hide file tree
Showing 43 changed files with 3,667 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode
.DS_*
terraform/terraform.*tfvars
terraform/.terraform
terraform/terraform.tfstate*
terraform/.terraform.tfstate.lock*
17 changes: 17 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

Copyright 2021 ScaleSec

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
SHELL := /bin/bash
.PHONY: docs build init apply

docs:
@cd terraform && terraform-docs markdown table --output-file README.md --output-mode inject .

test:
@cd cloudfunctions && ./test.sh

apply:
@cd terraform && terraform apply

init:
@cd terraform && terraform init

plan:
@cd terraform && terraform plan

start:
@./start_server.sh
3 changes: 3 additions & 0 deletions cloudfunctions/backup/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BACKUP_FILE_NAME - The basename of the backup file. Assumes zip. Don't include file extension.
BUCKET_NAME - the destination backup bucket
BUCKET_NAME_DR - secondary bucket to write to for DR. The valheim SA should not have access to this
170 changes: 170 additions & 0 deletions cloudfunctions/backup/backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package backup

import (
"context"
"fmt"

"io/ioutil"

"os"
"time"

log "github.com/sirupsen/logrus"

"cloud.google.com/go/storage"
"google.golang.org/api/iterator"
)

var (
bucketName, bucketNamePresent = os.LookupEnv("BUCKET_NAME")
// secondary bucket for DR
bucketNameDr, drBucketPresent = os.LookupEnv("BUCKET_NAME_DR")
backupName, backupNamePresent = os.LookupEnv("BACKUP_FILE_NAME")
t = time.Now()
)

// get objects in bucket and checks if older than 7
func checkObjectAge(bucket *storage.BucketHandle) error {
// create a timeout
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

iter := bucket.Objects(ctx, nil)

for {
attrs, err := iter.Next()

if err == iterator.Done {
break
}

if err != nil {
return fmt.Errorf("%v", err)
}

createdStamp := attrs.Created
objectName := attrs.Name

// if the object is 7 days old, delete
if t.After(createdStamp.Add(168 * time.Hour)) {
fmt.Printf("%s is over 7 days old\n", objectName)
if err = deleteObject(ctx, bucket, objectName); err != nil {
return err
}
}
}

return nil
}

// deletes an object
func deleteObject(ctx context.Context, bucket *storage.BucketHandle, objectName string) error {

// just in case
if objectName == "scaleheim.zip" {
fmt.Println("Skipping scaleheim.zip, refusing to delete")
}

fmt.Printf("Deleting %s\n", objectName)

obj := bucket.Object(objectName)
if err := obj.Delete(ctx); err != nil {
return err
}

return nil
}

// read the backup zip from gcs into an object
func readObject(ctx context.Context, bucket *storage.BucketHandle) (data []byte) {
obj := bucket.Object(fmt.Sprintf("%s.zip", backupName))
reader, err := obj.NewReader(ctx)

if err != nil {
log.Fatal("Could not read backup zip file from bucket")
}

data, err = ioutil.ReadAll(reader)
reader.Close()

if err != nil {
log.Fatal("Failed to read the bucket data with ioutil")
}

return data
}

// write the object to a copy in the bucket
func writeObject(ctx context.Context, bucket *storage.BucketHandle, date string, data []byte, bucketOutput string) {
// make a new object name
obj := bucket.Object(fmt.Sprintf("%s-%s.zip", backupName, date))

// make a writer
log.Println("Creating new writer")
w := obj.NewWriter(ctx)

// write the data into new object. This is asynchronous so error may not be known until close
log.Printf("Writing file to %s", bucketOutput)
if _, err := w.Write(data); err != nil {
log.Error("Failed to write data to new object. Probably exists already")
}

err := w.Close()
if err != nil {
log.Error("Failed to write data to new object. Probably exists already")
}

log.Info("Finished writing")
}

// Main runs the logic
func Backup(ctx context.Context, e interface{}) error {
// check that vars are present
if !backupNamePresent {
log.Fatal("BACKUP_FILE_NAME is unset")
}

if !bucketNamePresent {
log.Fatal("BUCKET_NAME is unset")
}

// init the client
client, err := storage.NewClient(ctx)
defer client.Close()
if err != nil {
log.Fatal("Could not initialize storage client")
}

// init bucket objects
bucket := client.Bucket(bucketName)
bucketDr := client.Bucket(bucketNameDr)

log.Info("Starting backup")

// get the current date
date := t.Format("01-02-2006")
log.Infof("Date is %s\n", date)

// get the data to write
log.Info("Reading main backup file")
data := readObject(ctx, bucket)

// write daily backup file
log.Info("Writing daily backup")
writeObject(ctx, bucket, date, data, bucketName)

if drBucketPresent {
log.Println("Backing up to secondary bucket")
// write a copy to a DR bucket
writeObject(ctx, bucketDr, date, data, bucketNameDr)
}

// delete objects older than 7 days
log.Info("Checking object ages")
err = checkObjectAge(bucket)
if err != nil {
log.Error(err)
}

return err
}
29 changes: 29 additions & 0 deletions cloudfunctions/backup/backup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package backup

import (
"context"
"testing"

"cloud.google.com/go/storage"
)

func initClient(t *testing.T) (bucket *storage.BucketHandle) {
ctx := context.Background()
client, err := storage.NewClient(ctx)
if err != nil {
t.Fatalf("error initializing client")
}

bucket = client.Bucket(bucketName)

return bucket
}

func TestCheckObjectAge(t *testing.T) {
bucket := initClient(t)

err := checkObjectAge(bucket)
if err != nil {
t.Fatalf("error listing buckets client")
}
}
23 changes: 23 additions & 0 deletions cloudfunctions/backup/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module github.com/iloveicedgreentea/valheim-gke-server/backup

go 1.17

require (
cloud.google.com/go v0.94.1 // indirect
cloud.google.com/go/storage v1.16.1 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/googleapis/gax-go/v2 v2.1.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365 // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/api v0.57.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 // indirect
google.golang.org/grpc v1.40.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
Loading

0 comments on commit 677c872

Please sign in to comment.