Skip to content

Commit 2d45020

Browse files
author
Foivos Filippopoulos
committed
Change app to read configuration and support both labels and descriptions in json format
1 parent 0066348 commit 2d45020

File tree

7 files changed

+220
-128
lines changed

7 files changed

+220
-128
lines changed

README.md

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,45 @@ Snapshots (only the ones created by the service) are deleted when they become ol
66
## Usage
77
```
88
Usage of /gcp-disk-snapshotter:
9-
-interval_secs int
10-
Interval between snapshots in seconds. Defaults to 43200s = 12h (default 43200)
11-
-labels string
12-
(Required) Comma separated list of disk labels in format <name>:<value>
9+
-conf_file string
10+
(Required) Path of the configuration file tha contains the targets based on label or description
1311
-log_level string
1412
Log Level, defaults to INFO (default "info")
1513
-project string
1614
(Required) GCP Project to use
17-
-retention_hours int
18-
Retention Duration in hours. Defaults to 720h = 1 month (default 720)
1915
-snap_prefix string
2016
Prefix for created snapshots
2117
-watch_interval int
2218
Interval between watch cycles in seconds. Defaults to 60s (default 60)
2319
-zones string
2420
(Required) Comma separated list of zones where projects disks may live
2521
```
22+
23+
#Configuration File
24+
25+
Example Configuration File:
26+
27+
```
28+
{
29+
"Descriptions": [
30+
{
31+
"retentionPeriodHours" : 2,
32+
"intervalSeconds" : 100,
33+
"description": {
34+
"key": "kubernetes.io/created-for/pvc/name",
35+
"value": "some-app-pd-pvc"
36+
}
37+
}
38+
],
39+
"Labels": [
40+
{
41+
"retentionPeriodHours" : 2,
42+
"intervalSeconds" : 100,
43+
"label": {
44+
"key": "name",
45+
"value": "some-app-name"
46+
}
47+
}
48+
]
49+
}
50+
```

main.go

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package main
22

33
import (
4+
"encoding/json"
45
"flag"
6+
"io/ioutil"
57
"os"
68
"strings"
79

@@ -13,14 +15,12 @@ import (
1315

1416
var (
1517
// flags
16-
flagProject = flag.String("project", "", "(Required) GCP Project to use")
17-
flagZones = flag.String("zones", "", "(Required) Comma separated list of zones where projects disks may live")
18-
flagLabels = flag.String("labels", "", "(Required) Comma separated list of disk labels in format <name>:<value>")
19-
flagSnapPrefix = flag.String("snap_prefix", "", "Prefix for created snapshots")
20-
flagWatchInterval = flag.Int("watch_interval", 60, "Interval between watch cycles in seconds. Defaults to 60s")
21-
flagRetentionHours = flag.Int("retention_hours", 720, "Retention Duration in hours. Defaults to 720h = 1 month")
22-
flagIntervalSeconds = flag.Int("interval_secs", 43200, "Interval between snapshots in seconds. Defaults to 43200s = 12h")
23-
flagLogLevel = flag.String("log_level", "info", "Log Level, defaults to INFO")
18+
flagProject = flag.String("project", "", "(Required) GCP Project to use")
19+
flagZones = flag.String("zones", "", "(Required) Comma separated list of zones where projects disks may live")
20+
flagConfFile = flag.String("conf_file", "", "(Required) Path of the configuration file tha contains the targets based on label or description")
21+
flagSnapPrefix = flag.String("snap_prefix", "", "Prefix for created snapshots")
22+
flagWatchInterval = flag.Int("watch_interval", 60, "Interval between watch cycles in seconds. Defaults to 60s")
23+
flagLogLevel = flag.String("log_level", "info", "Log Level, defaults to INFO")
2424
)
2525

2626
func usage() {
@@ -55,41 +55,51 @@ func main() {
5555
}
5656
zones := strings.Split(*flagZones, ",")
5757

58-
if *flagLabels == "" {
58+
if *flagConfFile == "" {
5959
usage()
6060
}
6161

62-
labels := &models.LabelList{}
63-
64-
for _, label := range strings.Split(*flagLabels, ",") {
65-
66-
l := strings.Split(label, ":")
67-
if len(l) < 2 {
68-
usage()
69-
}
70-
71-
labels.AddLabel(l[0], l[1])
72-
}
73-
7462
snapPrefix := *flagSnapPrefix
7563
watchInterval := *flagWatchInterval
76-
retentionHours := *flagRetentionHours
77-
intervalSecs := *flagIntervalSeconds
7864
logLevel := *flagLogLevel
7965

8066
// Init logging
8167
initLogging(logLevel)
8268

69+
// Load config
70+
snapshotConfigs := loadSnapshotConfig(*flagConfFile)
71+
72+
log.Debug("Reading Configuration")
73+
for _, d := range snapshotConfigs.Descriptions {
74+
log.Debug("description: ", d.Description.Key, " ", d.Description.Value)
75+
}
76+
for _, l := range snapshotConfigs.Labels {
77+
log.Debug("label: ", l.Label.Key, " ", l.Label.Value)
78+
}
8379
// Create a snapshotter
84-
gsc := snapshot.CreateGCPSnapClient(project, snapPrefix, zones, *labels)
80+
gsc := snapshot.CreateGCPSnapClient(project, snapPrefix, zones)
8581

8682
// Start watching
8783
watcher := &watch.Watcher{
88-
GSC: gsc,
89-
WatchInterval: watchInterval,
90-
RetentionHours: retentionHours,
91-
IntervalSecs: intervalSecs,
84+
GSC: gsc,
85+
WatchInterval: watchInterval,
9286
}
93-
watcher.Watch()
87+
watcher.Watch(snapshotConfigs)
9488

9589
}
90+
91+
func loadSnapshotConfig(snapshotConfigFile string) *models.SnapshotConfigs {
92+
confFile, err := os.Open(snapshotConfigFile)
93+
if err != nil {
94+
log.Fatal("Error while opening volume snapshot config file: ", err)
95+
}
96+
fileContent, err := ioutil.ReadAll(confFile)
97+
if err != nil {
98+
log.Fatal("Error while reading volume snapshot config file: ", err)
99+
}
100+
snapshotConfigs := &models.SnapshotConfigs{}
101+
if err = json.Unmarshal(fileContent, snapshotConfigs); err != nil {
102+
log.Fatal("Error unmarshalling snapshots config file: ", err)
103+
}
104+
return snapshotConfigs
105+
}

models/labels.go

Lines changed: 0 additions & 22 deletions
This file was deleted.

models/types.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package models
2+
3+
type Label struct {
4+
Key string `json:"key"`
5+
Value string `json:"value"`
6+
}
7+
8+
type LabelSnapshotConfig struct {
9+
Label *Label `json:"label"`
10+
IntervalSeconds int64 `json:"intervalSeconds"`
11+
RetentionPeriodHours int64 `json:"retentionPeriodHours"`
12+
}
13+
14+
type Description struct {
15+
Key string `json:"key"`
16+
Value string `json:"value"`
17+
}
18+
19+
type DescriptionSnapshotConfig struct {
20+
Description *Description `json:"description"`
21+
IntervalSeconds int64 `json:"intervalSeconds"`
22+
RetentionPeriodHours int64 `json:"retentionPeriodHours"`
23+
}
24+
25+
type SnapshotConfigs struct {
26+
Descriptions []*DescriptionSnapshotConfig `json:"Descriptions"`
27+
Labels []*LabelSnapshotConfig `json:"Labels"`
28+
}

snapshot/client.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package snapshot
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
log "github.com/sirupsen/logrus"
78
"net/http"
@@ -25,13 +26,13 @@ var googleClient *http.Client
2526
type GCPSnapClient struct {
2627
Project string
2728
Zones []string
28-
Labels models.LabelList
2929
SnapPrefix string
3030
ComputeService compute.Service
3131
}
3232

3333
type GCPSnapClientInterface interface {
34-
GetDiskList() ([]compute.Disk, error)
34+
GetDisksFromLabel(label *models.Label) ([]compute.Disk, error)
35+
GetDisksFromDescription(label *models.Description) ([]compute.Disk, error)
3536
ListSnapshots(diskSelfLink string) ([]compute.Snapshot, error)
3637
ListClientCreatedSnapshots(diskSelfLink string) ([]compute.Snapshot, error)
3738
CreateSnapshot(diskName, zone string) (string, error)
@@ -41,7 +42,7 @@ type GCPSnapClientInterface interface {
4142
}
4243

4344
// Basic Init function for the snapshotter
44-
func CreateGCPSnapClient(project, snapPrefix string, zones []string, labels models.LabelList) *GCPSnapClient {
45+
func CreateGCPSnapClient(project, snapPrefix string, zones []string) *GCPSnapClient {
4546

4647
ctx := context.Background()
4748
googleClient, err := google.DefaultClient(ctx, compute.ComputeScope)
@@ -57,7 +58,6 @@ func CreateGCPSnapClient(project, snapPrefix string, zones []string, labels mode
5758
return &GCPSnapClient{
5859
Project: project,
5960
Zones: zones,
60-
Labels: labels,
6161
SnapPrefix: snapPrefix,
6262
ComputeService: *computeService,
6363
}
@@ -74,7 +74,7 @@ func formatLinkString(in string) string {
7474
}
7575

7676
// GetDiskList: Returns a list of disks that contain one of the given labels
77-
func (gsc *GCPSnapClient) GetDiskList() ([]compute.Disk, error) {
77+
func (gsc *GCPSnapClient) GetDisksFromLabel(label *models.Label) ([]compute.Disk, error) {
7878

7979
disks := []compute.Disk{}
8080

@@ -85,12 +85,36 @@ func (gsc *GCPSnapClient) GetDiskList() ([]compute.Disk, error) {
8585
}
8686

8787
for _, disk := range resp.Items {
88-
for _, label := range gsc.Labels.Items {
89-
if val, ok := disk.Labels[label.Name]; ok {
90-
if label.Value == val {
91-
disks = append(disks, *disk)
92-
break
93-
}
88+
if val, ok := disk.Labels[label.Key]; ok {
89+
if label.Value == val {
90+
disks = append(disks, *disk)
91+
}
92+
}
93+
}
94+
}
95+
96+
return disks, nil
97+
}
98+
99+
func (gsc *GCPSnapClient) GetDisksFromDescription(desc *models.Description) ([]compute.Disk, error) {
100+
101+
disks := []compute.Disk{}
102+
103+
for _, zone := range gsc.Zones {
104+
resp, err := gsc.ComputeService.Disks.List(gsc.Project, zone).Do()
105+
if err != nil {
106+
return disks, errors.Wrap(err, "error listing disks")
107+
}
108+
109+
for _, disk := range resp.Items {
110+
var dObj map[string]string
111+
if err = json.Unmarshal([]byte(disk.Description), &dObj); err != nil {
112+
log.Debug("Skipping: error unmarshalling disk description to map: ", err)
113+
continue
114+
}
115+
if val, ok := dObj[desc.Key]; ok {
116+
if desc.Value == val {
117+
disks = append(disks, *disk)
94118
}
95119
}
96120
}
@@ -163,7 +187,7 @@ func (gsc *GCPSnapClient) CreateSnapshot(diskName, zone string) (string, error)
163187
// Name must match regex '(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)'
164188
snapshot := &compute.Snapshot{
165189
Description: fmt.Sprintf("Snapshot of %s", diskName),
166-
Name: fmt.Sprintf("%s%s-snapshot-%s", gsc.SnapPrefix, diskName, time.Now().Format("20060102150405")),
190+
Name: fmt.Sprintf("%s%s-%s", gsc.SnapPrefix, diskName, time.Now().Format("20060102150405")),
167191
Labels: snapLabels,
168192
}
169193

snapshot/mock_client.go

Lines changed: 20 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)