From ec5fc527bcfdfc1477ce89797f411e2797ecdf2d Mon Sep 17 00:00:00 2001 From: youyo <1003ni2@gmail.com> Date: Thu, 13 Aug 2015 14:04:42 +0900 Subject: [PATCH] v0.1.0 --- .gitignore | 4 ++ CHANGELOG.md | 19 ++++++ README.md | 82 +++++++++++++++++++++++ command/self.go | 169 ++++++++++++++++++++++++++++++++++++++++++++++++ commands.go | 32 +++++++++ main.go | 23 +++++++ version.go | 4 ++ 7 files changed, 333 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 README.md create mode 100644 command/self.go create mode 100644 commands.go create mode 100644 main.go create mode 100644 version.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddac283 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +recorder +*.swp +tmp/ +*.zip diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..93f4d54 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ +## 0.1.0 (2015-08-13) + +Initial release + +### Added + +- Add Fundamental features + +### Deprecated + +- Nothing + +### Removed + +- Nothing + +### Fixed + +- Nothing diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca857f1 --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# recorder + +## Description + +Create a snapshot of the Amazon EC2. + +## Usage + +Set AWS configuration file. + +``` +cat ~/.aws/credentials +[default] +aws_access_key_id = XXXXXXXXXX +aws_secret_access_key = XXXXXXXXXXXXXXX +``` + +Run the `recorder self` + +``` +$ recorder self -h +NAME: + self - Snapshotting for own volume. + +USAGE: + command self [command options] [arguments...] + +OPTIONS: + --lifecycle, -l "5" Set the number of life cycle for snapshot. +``` + +``` +$ recorder -h +NAME: + recorder - Create a snapshot of the Amazon EC2. + +USAGE: + recorder [global options] command [command options] [arguments...] + +VERSION: + 0.1.0 + +AUTHOR(S): + youyo + +COMMANDS: + self Snapshotting for own volume. + help, h Shows a list of commands or help for one command + +GLOBAL OPTIONS: + --help, -h show help + --version, -v print the version +``` + + +## Install + +To install, use `go get`: + +```bash +$ go get -d github.com/heptagon-inc/recorder +$ cd $GOPATH/src/github.com/heptagon-inc/recorder +$ go build +``` + +## Warning! + +Test does not exist yet. + +## Contribution + +1. Fork ([https://github.com/heptagon-inc/recorder/fork](https://github.com/heptagon-inc/recorder/fork)) +1. Create a feature branch +1. Commit your changes +1. Rebase your local changes against the master branch +1. Run test suite with the `go test ./...` command and confirm that it passes +1. Run `gofmt -s` +1. Create a new Pull Request + +## Author + +[youyo](https://github.com/youyo) diff --git a/command/self.go b/command/self.go new file mode 100644 index 0000000..ede1dd2 --- /dev/null +++ b/command/self.go @@ -0,0 +1,169 @@ +package command + +import ( + "fmt" + "io/ioutil" + "net/http" + "sort" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/codegangsta/cli" +) + +type Snapshot struct { + snapshotId string + startTime int64 +} + +type Snapshots []Snapshot + +func (p Snapshots) Len() int { + return len(p) +} + +func (p Snapshots) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func (p Snapshots) Less(i, j int) bool { + return p[i].startTime < p[j].startTime +} + +func CmdSelf(c *cli.Context) { + // get region + r_url := "http://169.254.169.254/latest/meta-data/local-hostname" + r_res, _ := http.Get(r_url) + r_b, _ := ioutil.ReadAll(r_res.Body) + defer r_res.Body.Close() + region := strings.Split(string(r_b), ".")[1] + + // get instance-id + url := "http://169.254.169.254/latest/meta-data/instance-id" + res, _ := http.Get(url) + b, _ := ioutil.ReadAll(res.Body) + defer res.Body.Close() + instance_id := string(b) + + // Auth + svc := ec2.New(&aws.Config{Region: aws.String(region)}) + + // create instance-id-config + params := &ec2.DescribeInstancesInput{ + InstanceIDs: []*string{ + aws.String(instance_id), + }, + } + + // get instance-info + resp, err := svc.DescribeInstances(params) + if err != nil { + panic(err) + } + + // get all volume-id + var volume_ids []string = make([]string, 1) + for _, res := range resp.Reservations { + for _, res := range res.Instances { + for index, res := range res.BlockDeviceMappings { + if index == 0 { + volume_ids[0] = *res.EBS.VolumeID + } else { + volume_ids = append(volume_ids, *res.EBS.VolumeID) + } + } + } + } + + for _, volume_id := range volume_ids { + // Description + snapshotDescription := "Created by recorder from " + volume_id + " of " + instance_id + + // create-snapshot config + snapshotParams := &ec2.CreateSnapshotInput{ + VolumeID: aws.String(volume_id), + Description: aws.String(snapshotDescription), + } + + // create snapshot + snapshotResp, err := svc.CreateSnapshot(snapshotParams) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr()) + if reqErr, ok := err.(awserr.RequestFailure); ok { + fmt.Println(reqErr.Code(), reqErr.Message(), reqErr.StatusCode(), reqErr.RequestID()) + } + } else { + fmt.Println(err.Error()) + } + } + fmt.Println(awsutil.Prettify(snapshotResp)) + + // snapshot lifecycle + // describe-snapshot config + DescribeSnapshotParams := &ec2.DescribeSnapshotsInput{ + Filters: []*ec2.Filter{ + { + Name: aws.String("volume-id"), + Values: []*string{ + aws.String(volume_id), + }, + }, + }, + } + // get snapshots + describeResp, err := svc.DescribeSnapshots(DescribeSnapshotParams) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr()) + if reqErr, ok := err.(awserr.RequestFailure); ok { + fmt.Println(reqErr.Code(), reqErr.Message(), reqErr.StatusCode(), reqErr.RequestID()) + } + } else { + fmt.Println(err.Error()) + } + } + + // linkage of snapshot-id and the start-time + var snapshotId Snapshots = make([]Snapshot, 1) + for index, res := range describeResp.Snapshots { + if index == 0 { + snapshotId[0].snapshotId = *res.SnapshotID + snapshotId[0].startTime = res.StartTime.Unix() + } else { + snapshotId = append(snapshotId, Snapshot{*res.SnapshotID, res.StartTime.Unix()}) + } + } + // sort asc + sort.Sort(snapshotId) + // If the number of snapshot is life-cycle or more, Delete snapshot. + for len(snapshotId) > c.Int("lifecycle") { + for index, snapshots := range snapshotId { + if index == 0 { + // delete snapshot + deleteParam := &ec2.DeleteSnapshotInput{ + SnapshotID: aws.String(snapshots.snapshotId), + } + _, err := svc.DeleteSnapshot(deleteParam) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr()) + if reqErr, ok := err.(awserr.RequestFailure); ok { + fmt.Println(reqErr.Code(), reqErr.Message(), reqErr.StatusCode(), reqErr.RequestID()) + } + } else { + fmt.Println(err.Error()) + } + } + deleteMessage := "deleted: " + snapshots.snapshotId + fmt.Println(deleteMessage) + } + } + // delete snapshotID + snapshotId = append(snapshotId[1:]) + } + } +} diff --git a/commands.go b/commands.go new file mode 100644 index 0000000..d6ebad4 --- /dev/null +++ b/commands.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "os" + + "github.com/codegangsta/cli" + "github.com/heptagon-inc/recorder/command" +) + +var GlobalFlags = []cli.Flag{} + +var Commands = []cli.Command{ + + { + Name: "self", + Usage: "Snapshotting for own volume.", + Action: command.CmdSelf, + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "lifecycle, l", + Value: 5, + Usage: "Set the number of life cycle for snapshot.", + }, + }, + }, +} + +func CommandNotFound(c *cli.Context, command string) { + fmt.Fprintf(os.Stderr, "%s: '%s' is not a %s command. See '%s --help'.", c.App.Name, command, c.App.Name, c.App.Name) + os.Exit(2) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..8c45e2c --- /dev/null +++ b/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "os" + + "github.com/codegangsta/cli" +) + +func main() { + + app := cli.NewApp() + app.Name = Name + app.Version = Version + app.Author = "youyo" + app.Email = "" + app.Usage = "Create a snapshot of the Amazon EC2." + + app.Flags = GlobalFlags + app.Commands = Commands + app.CommandNotFound = CommandNotFound + + app.Run(os.Args) +} diff --git a/version.go b/version.go new file mode 100644 index 0000000..a871914 --- /dev/null +++ b/version.go @@ -0,0 +1,4 @@ +package main + +const Name string = "recorder" +const Version string = "0.1.0"