Skip to content

Commit

Permalink
Merge pull request #124 from stelligent/develop
Browse files Browse the repository at this point in the history
v0.10.0 final
  • Loading branch information
cplee authored Apr 10, 2017
2 parents 5461922 + d225283 commit 5528576
Show file tree
Hide file tree
Showing 42 changed files with 1,742 additions and 135 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ To address these challenges, this tool was created to simplify the declaration a

The `mu` tool uses CloudFormation stacks to manage all resources it creates. Additionally, `mu` will not create any databases or other AWS resources to support itself. It will only create resources (via CloudFormation) necessary to run your microservices. This means at any point you can stop using `mu` and continue to manage the AWS resources that it created via AWS tools such as the CLI or the console.

![Architecture Diagram](https://github.com/stelligent/mu/wiki/img/ms-architecture-3.png)
![Architecture Diagram](https://github.com/stelligent/mu/wiki/img/mu-architecture.gif)

# Demo
Watch the 90 second demo below to see mu in action!
Expand All @@ -19,7 +19,7 @@ Watch the 90 second demo below to see mu in action!
Install latest version to /usr/local/bin (or for additional options, see [wiki](https://github.com/stelligent/mu/wiki/Installation)):

```bash
curl -s https://raw.githubusercontent.com/stelligent/mu/master/install.sh | sh
curl -s http://getmu.io/install.sh | sh
```

Assuming your project already has a Dockerfile, you can initialize your mu.yml file with: `mu init`. More details available in the [quickstart](https://github.com/stelligent/mu/wiki/Quickstart).
Expand All @@ -28,6 +28,7 @@ Assuming your project already has a Dockerfile, you can initialize your mu.yml f
Check out the [examples](examples) to see snippets of `mu.yml` configuration files that you can use in your own project:

* **[Basic](examples/basic)** - Simple website with continuous delivery pipeline deploying to dev and prod environments
* **[Service Discovery](examples/consul)** - Service discovery via [Consul](https://www.consul.io/) and [Registrator](http://gliderlabs.com/registrator/latest/)
* **[Test Automation](examples/pipeline-newman)** - Automating end-to-end testing via [Newman](https://github.com/postmanlabs/newman)
* **[Env Variables](examples/service-env-vars)** - Defining environment variables for the service
* **[HTTPS](examples/elb-https)** - Enable HTTPS on the ALB for an environment
Expand All @@ -42,6 +43,7 @@ Refer to the wiki for complete details on the configuration of `mu.yml` and the
* **[Pipelines](https://github.com/stelligent/mu/wiki/Pipelines)** - managing continuous delivery pipelines
* **[CLI](https://github.com/stelligent/mu/wiki/CLI-Usage)** - details about using the CLI
* **[Custom CloudFormation](https://github.com/stelligent/mu/wiki/Custom-CloudFormation)** - details about customizing the CloudFormation that is generated by mu.
* **[Service Discovery](https://github.com/stelligent/mu/wiki/Service-Discovery)** - details about configuring and using service discovery

# Contributing

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.9
0.1.10
27 changes: 27 additions & 0 deletions cli/environments.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/stelligent/mu/workflows"
"github.com/urfave/cli"
"os"
"strings"
)

func newEnvironmentsCommand(ctx *common.Context) *cli.Command {
Expand All @@ -19,6 +20,7 @@ func newEnvironmentsCommand(ctx *common.Context) *cli.Command {
*newEnvironmentsShowCommand(ctx),
*newEnvironmentsUpsertCommand(ctx),
*newEnvironmentsTerminateCommand(ctx),
*newEnvironmentsLogsCommand(ctx),
},
}

Expand Down Expand Up @@ -104,3 +106,28 @@ func newEnvironmentsTerminateCommand(ctx *common.Context) *cli.Command {

return cmd
}
func newEnvironmentsLogsCommand(ctx *common.Context) *cli.Command {
cmd := &cli.Command{
Name: "logs",
Usage: "show environment logs",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "follow, f",
Usage: "follow logs for latest changes",
},
},
ArgsUsage: "<environment> [<filter>...]",
Action: func(c *cli.Context) error {
environmentName := c.Args().First()
if len(environmentName) == 0 {
cli.ShowCommandHelp(c, "logs")
return errors.New("environment must be provided")
}

workflow := workflows.NewEnvironmentLogViewer(ctx, c.Bool("follow"), environmentName, os.Stdout, strings.Join(c.Args().Tail(), " "))
return workflow()
},
}

return cmd
}
16 changes: 15 additions & 1 deletion cli/environments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestNewEnvironmentsCommand(t *testing.T) {
assert.Equal(1, len(command.Aliases), "Aliases len should match")
assert.Equal("env", command.Aliases[0], "Aliases should match")
assert.Equal("options for managing environments", command.Usage, "Usage should match")
assert.Equal(4, len(command.Subcommands), "Subcommands len should match")
assert.Equal(5, len(command.Subcommands), "Subcommands len should match")

args := []string{"environment", "help"}
err := runCommand(command, args)
Expand Down Expand Up @@ -89,6 +89,20 @@ func TestNewEnvironmentsTerminateCommand(t *testing.T) {
assert.Equal("<environment>", command.ArgsUsage, "ArgsUsage should match")
assert.NotNil(command.Action)
}
func TestNewEnvironmentsLogsCommand(t *testing.T) {
assert := assert.New(t)

ctx := common.NewContext()

command := newEnvironmentsLogsCommand(ctx)

assert.NotNil(command)
assert.Equal("logs", command.Name, "Name should match")
assert.Equal("<environment> [<filter>...]", command.ArgsUsage, "ArgsUsage should match")
assert.Equal(1, len(command.Flags), "Flags length")
assert.Equal("follow, f", command.Flags[0].GetName(), "Flags Name")
assert.NotNil(command.Action)
}

func runCommand(command *cli.Command, args []string) error {
app := cli.NewApp()
Expand Down
25 changes: 25 additions & 0 deletions cli/pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func newPipelinesCommand(ctx *common.Context) *cli.Command {
*newPipelinesListCommand(ctx),
*newPipelinesUpsertCommand(ctx),
*newPipelinesTerminateCommand(ctx),
*newPipelinesLogsCommand(ctx),
},
}

Expand Down Expand Up @@ -86,3 +87,27 @@ func newPipelinesUpsertCommand(ctx *common.Context) *cli.Command {

return cmd
}
func newPipelinesLogsCommand(ctx *common.Context) *cli.Command {
cmd := &cli.Command{
Name: "logs",
Usage: "show pipeline logs",
Flags: []cli.Flag{
cli.StringFlag{
Name: "service, s",
Usage: "service name to view logs for",
},
cli.BoolFlag{
Name: "follow, f",
Usage: "follow logs for latest changes",
},
},
ArgsUsage: "[<filter>...]",
Action: func(c *cli.Context) error {
serviceName := c.String("service")
workflow := workflows.NewPipelineLogViewer(ctx, c.Bool("follow"), serviceName, os.Stdout, strings.Join(c.Args(), " "))
return workflow()
},
}

return cmd
}
17 changes: 16 additions & 1 deletion cli/pipelines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestNewPipelinesCommand(t *testing.T) {
assert.NotNil(command)
assert.Equal("pipeline", command.Name, "Name should match")
assert.Equal("options for managing pipelines", command.Usage, "Usage should match")
assert.Equal(3, len(command.Subcommands), "Subcommands len should match")
assert.Equal(4, len(command.Subcommands), "Subcommands len should match")
}
func TestNewPipelinesListCommand(t *testing.T) {
assert := assert.New(t)
Expand Down Expand Up @@ -57,3 +57,18 @@ func TestNewPipelinesUpsertCommand(t *testing.T) {
assert.Equal("token, t", command.Flags[0].GetName(), "Flag should match")
assert.NotNil(command.Action)
}
func TestNewPipelinesLogsCommand(t *testing.T) {
assert := assert.New(t)

ctx := common.NewContext()

command := newPipelinesLogsCommand(ctx)

assert.NotNil(command)
assert.Equal("logs", command.Name, "Name should match")
assert.Equal("[<filter>...]", command.ArgsUsage, "ArgsUsage should match")
assert.Equal(2, len(command.Flags), "Flags length")
assert.Equal("service, s", command.Flags[0].GetName(), "Flags Name")
assert.Equal("follow, f", command.Flags[1].GetName(), "Flags Name")
assert.NotNil(command.Action)
}
33 changes: 33 additions & 0 deletions cli/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"github.com/stelligent/mu/common"
"github.com/stelligent/mu/workflows"
"github.com/urfave/cli"
"os"
"strings"
)

func newServicesCommand(ctx *common.Context) *cli.Command {
Expand All @@ -17,6 +19,7 @@ func newServicesCommand(ctx *common.Context) *cli.Command {
*newServicesPushCommand(ctx),
*newServicesDeployCommand(ctx),
*newServicesUndeployCommand(ctx),
*newServicesLogsCommand(ctx),
},
}

Expand Down Expand Up @@ -103,3 +106,33 @@ func newServicesUndeployCommand(ctx *common.Context) *cli.Command {

return cmd
}
func newServicesLogsCommand(ctx *common.Context) *cli.Command {
cmd := &cli.Command{
Name: "logs",
Usage: "show service logs",
Flags: []cli.Flag{
cli.StringFlag{
Name: "service, s",
Usage: "service name to view logs for",
},
cli.BoolFlag{
Name: "follow, f",
Usage: "follow logs for latest changes",
},
},
ArgsUsage: "<environment> [<filter>...]",
Action: func(c *cli.Context) error {
environmentName := c.Args().First()
if len(environmentName) == 0 {
cli.ShowCommandHelp(c, "logs")
return errors.New("environment must be provided")
}
serviceName := c.String("service")

workflow := workflows.NewServiceLogViewer(ctx, c.Bool("follow"), environmentName, serviceName, os.Stdout, strings.Join(c.Args().Tail(), " "))
return workflow()
},
}

return cmd
}
19 changes: 17 additions & 2 deletions cli/services_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestNewServicesCommand(t *testing.T) {
assert.Equal(1, len(command.Aliases), "Aliases len should match")
assert.Equal("svc", command.Aliases[0], "Aliases should match")
assert.Equal("options for managing services", command.Usage, "Usage should match")
assert.Equal(4, len(command.Subcommands), "Subcommands len should match")
assert.Equal(5, len(command.Subcommands), "Subcommands len should match")
}

func TestNewServicesShowCommand(t *testing.T) {
Expand Down Expand Up @@ -71,9 +71,24 @@ func TestNewUndeployCommand(t *testing.T) {

command := newServicesUndeployCommand(ctx)

assert.NotNil(command)
assert.Equal("undeploy", command.Name, "Name should match")
assert.Equal("<environment> [<service>]", command.ArgsUsage, "ArgsUsage should match")
assert.Equal(0, len(command.Flags), "Flags length")
assert.NotNil(command.Action)
}

func TestNewServicesLogsCommand(t *testing.T) {
assert := assert.New(t)

ctx := common.NewContext()

command := newServicesLogsCommand(ctx)

assert.NotNil(command)
assert.Equal("logs", command.Name, "Name should match")
assert.Equal("<environment> [<filter>...]", command.ArgsUsage, "ArgsUsage should match")
assert.Equal(2, len(command.Flags), "Flags length")
assert.Equal("service, s", command.Flags[0].GetName(), "Flags Name")
assert.Equal("follow, f", command.Flags[1].GetName(), "Flags Name")
assert.NotNil(command.Action)
}
33 changes: 31 additions & 2 deletions common/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"path"
"path/filepath"
"strings"
"time"
)

Expand Down Expand Up @@ -43,16 +44,38 @@ func (ctx *Context) InitializeConfigFromFile(muFile string) error {
log.Debugf("Setting basedir=%s", ctx.Config.Basedir)

ctx.Config.Repo.Name = path.Base(ctx.Config.Basedir)
log.Debugf("Setting repo name=%s", ctx.Config.Repo.Name)

ctx.Config.Repo.Revision = time.Now().Format("20060102150405")

// Get the git revision from the .git folder
gitRevision, err := findGitRevision(ctx.Config.Basedir)
if err == nil {
ctx.Config.Repo.Revision = gitRevision
} else {
log.Warningf("Unable to determine git revision: %s", err.Error())

// The .git folder does not exist, check to see if we are in CodeBuild
if os.Getenv("CODEBUILD_INITIATOR") != "" {
log.Warningf("Trying to determine git revision from CodeBuild initiator.")
initiator := os.Getenv("CODEBUILD_INITIATOR")
parts := strings.Split(initiator, "/")

// See if the build was initiated by CodePipeline
if parts[0] == "codepipeline" {
// Try retrieving the revision from the CodePipeline status
gitInfo, err := ctx.PipelineManager.GetGitInfo(parts[1])
if err != nil {
log.Warningf("Unable to determine git information from CodeBuild initiator: %s", initiator)
}

ctx.Config.Repo.Revision = string(gitInfo.revision[:7])
ctx.Config.Repo.Name = gitInfo.repoName
ctx.Config.Repo.OrgName = gitInfo.orgName
} else {
log.Warningf("Unable to process CodeBuild initiator: %s", initiator)
}
}
}
log.Debugf("Setting repo name=%s", ctx.Config.Repo.Name)
log.Debugf("Setting repo revision=%s", ctx.Config.Repo.Revision)

gitProvider, gitSlug, err := findGitSlug(ctx.Config.Basedir)
Expand Down Expand Up @@ -130,6 +153,12 @@ func (ctx *Context) InitializeContext(profile string, region string, dryrun bool
return err
}

// initialize CloudWatchLogs
ctx.LogsManager, err = newLogsManager(sess)
if err != nil {
return err
}

// initialize DockerManager
ctx.DockerManager, err = newClientDockerManager()
if err != nil {
Expand Down
Loading

0 comments on commit 5528576

Please sign in to comment.