Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
youyo committed Aug 13, 2015
0 parents commit ec5fc52
Show file tree
Hide file tree
Showing 7 changed files with 333 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
recorder
*.swp
tmp/
*.zip
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## 0.1.0 (2015-08-13)

Initial release

### Added

- Add Fundamental features

### Deprecated

- Nothing

### Removed

- Nothing

### Fixed

- Nothing
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
169 changes: 169 additions & 0 deletions command/self.go
Original file line number Diff line number Diff line change
@@ -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:])
}
}
}
32 changes: 32 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
@@ -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)
}
23 changes: 23 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -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)
}
4 changes: 4 additions & 0 deletions version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package main

const Name string = "recorder"
const Version string = "0.1.0"

0 comments on commit ec5fc52

Please sign in to comment.