Skip to content

Commit e9e69cd

Browse files
committed
first commit
1 parent 87f22dc commit e9e69cd

File tree

5 files changed

+162
-0
lines changed

5 files changed

+162
-0
lines changed

.env.dist

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
TIMEZONE=
2+
AWS_ACCESS_KEY_ID=
3+
AWS_SECRET_ACCESS_KEY=
4+
AWS_REGION=
5+
BUCKET=
6+
PATH_PREFIX=
7+
OLDER_THAN_MINUTES=
8+
SMALLER_THAN_MEGABYTES=

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env

Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FROM golang:onbuild

README.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Check last S3 file
2+
A useful script that search for last file in a s3 bucket and check size and last edit timestamp.
3+
We use this with a cron job for check that our backups are up to date.
4+
5+
Following environment variables are mandatory:
6+
```
7+
TIMEZONE= // ex. Europe/Rome
8+
AWS_ACCESS_KEY_ID=
9+
AWS_SECRET_ACCESS_KEY=
10+
AWS_REGION= // ex. eu-west-1
11+
BUCKET= // Only the bucket name ex. Backups
12+
PATH_PREFIX= // You can insert here subpath and the name prefix ex. /databases/my-database
13+
OLDER_THAN_MINUTES= // ex. 60 for 1 hour
14+
SMALLER_THAN_MEGABYTES= // ex. 100 for 100MB
15+
```
16+
17+
## Usage
18+
19+
`docker run --env-file .env leen15/check-last-s3-file`
20+
21+
And it responses with something like:
22+
23+
```
24+
Check last file in:
25+
Bucket: backups
26+
Prefix: databases/my-database
27+
Older than: 60 minutes
28+
Smaller than: 100 MB
29+
Files in bucket: 4
30+
31+
Most recent file is:
32+
Name: my-database.2019-11-22-00-10-09.native.dump.bz2
33+
modified at: 2019-11-22 01:10:11 +0100 CET
34+
Size: 50 MB
35+
36+
[ERROR] The file is older than max allowed. ( 13h57m23.59s ago )
37+
[ERROR] The file is smaller than min allowed. ( 50 vs 100 MB )
38+
```
39+
40+
## License
41+
42+
This project is released under the terms of the [MIT license](http://en.wikipedia.org/wiki/MIT_License).

main.go

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package main
2+
3+
import (
4+
"github.com/aws/aws-sdk-go/aws"
5+
"github.com/aws/aws-sdk-go/aws/credentials"
6+
"github.com/aws/aws-sdk-go/aws/session"
7+
"github.com/aws/aws-sdk-go/service/s3"
8+
"github.com/caarlos0/env"
9+
"fmt"
10+
"os"
11+
"time"
12+
"strings"
13+
)
14+
15+
type config struct {
16+
Bucket string `env:"BUCKET"`
17+
Prefix string `env:"PATH_PREFIX"`
18+
Timezone string `env:"TIMEZONE"`
19+
OlderThanMinutes int `env:"OLDER_THAN_MINUTES"`
20+
SmallerThanMegabytes int64 `env:"SMALLER_THAN_MEGABYTES"`
21+
AwsAccessKeyID string `env:"AWS_ACCESS_KEY_ID"`
22+
AwsSecretAccessKey string `env:"AWS_SECRET_ACCESS_KEY"`
23+
AwsRegion string `env:"AWS_REGION"`
24+
}
25+
26+
func main() {
27+
28+
cfg := config{}
29+
if err := env.Parse(&cfg); err != nil {
30+
exitErrorf("%+v\n", err)
31+
}
32+
33+
fmt.Println("Check last file in:")
34+
fmt.Println("Region: ", cfg.AwsRegion)
35+
fmt.Println("Bucket: ", cfg.Bucket)
36+
fmt.Println("Prefix: ", cfg.Prefix)
37+
fmt.Println("Older than: ", cfg.OlderThanMinutes, "minutes")
38+
fmt.Println("Smaller than: ", cfg.SmallerThanMegabytes, "MB")
39+
40+
// utc life
41+
loc, err := time.LoadLocation(cfg.Timezone)
42+
if err != nil {
43+
panic(err)
44+
}
45+
46+
sess, err := session.NewSession(&aws.Config{
47+
Region: aws.String(cfg.AwsRegion),
48+
Credentials: credentials.NewStaticCredentials(cfg.AwsAccessKeyID, cfg.AwsSecretAccessKey, ""),
49+
})
50+
51+
// Create S3 service client
52+
svc := s3.New(sess)
53+
54+
// Get the list of items
55+
resp, err := svc.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: aws.String(cfg.Bucket), Prefix: aws.String(cfg.Prefix)})
56+
if err != nil {
57+
exitErrorf("[ERROR] Unable to list items in bucket %q, %v", cfg.Bucket, err)
58+
}
59+
60+
if (len(resp.Contents) == 0) {
61+
fmt.Println("[ERROR] No files in bucket. ")
62+
os.Exit(1)
63+
}
64+
65+
mostRecentObj := *resp.Contents[0]
66+
for _, item := range resp.Contents {
67+
if (item.LastModified.After(*mostRecentObj.LastModified)) {
68+
mostRecentObj = *item
69+
}
70+
}
71+
72+
fmt.Println("Files in bucket:", len(resp.Contents))
73+
fmt.Println("")
74+
75+
keyArray := strings.Split(*mostRecentObj.Key, "/")
76+
mostRecentObjName := keyArray[len(keyArray)-1]
77+
mostRecentObjDate := (*mostRecentObj.LastModified).In(loc)
78+
mostRecentObjSize := *mostRecentObj.Size / 1024 / 1024
79+
80+
fmt.Println("Most recent file is: ")
81+
fmt.Println("Name: ", mostRecentObjName)
82+
fmt.Println("modified at: ", mostRecentObjDate)
83+
fmt.Println("Size: ", mostRecentObjSize , "MB")
84+
fmt.Println("")
85+
86+
minOlderTime := time.Now().In(loc).Add(time.Minute * time.Duration(-1 * cfg.OlderThanMinutes))
87+
diffTime := mostRecentObjDate.Sub(minOlderTime);
88+
89+
error := false
90+
if (diffTime.Minutes() < 0) {
91+
fmt.Println("[ERROR] The file is older than max allowed. (", diffTime * -1, "ago )" )
92+
error = true
93+
}
94+
95+
if (cfg.SmallerThanMegabytes > 0 && *mostRecentObj.Size / 1024 / 1024 < cfg.SmallerThanMegabytes) {
96+
fmt.Println("[ERROR] The file is smaller than min allowed. (", mostRecentObjSize, "MB vs", cfg.SmallerThanMegabytes, "MB )" )
97+
error = true
98+
}
99+
100+
if (error) {
101+
os.Exit(1)
102+
}
103+
104+
fmt.Println("[SUCCESS] The file is OK." )
105+
}
106+
107+
func exitErrorf(msg string, args ...interface{}) {
108+
fmt.Fprintf(os.Stderr, msg+"\n", args...)
109+
os.Exit(1)
110+
}

0 commit comments

Comments
 (0)