Skip to content

Commit

Permalink
Release candidate v0.10.4-rc1 (#478)
Browse files Browse the repository at this point in the history
* rename terraform resources. add terraform import lines. add diff supression for deploy.content field. add import system test

* remove crash.log

* remove comment

* update docs, fix unit tests

* Terraform: improve handling of sigterm  (#301)

* rename terraform resources. add terraform import lines. add diff supression for deploy.content field. add import system test

* remove crash.log

* remove comment

* update docs, fix unit tests

* add Layer0Client for meta object

* use waitWithContext helper functions. Remove partial state from service resource

* remove wait

* fix merge

* check error codes for <Entity>DoesNotExist in terraform module

* return <Entity>DoesNotExist error codes from backend layer

* use 's' for receiver

* Return '404 Not Found' errors when resource not found instead of '500 Server Error' errors.

* split out system and stress tests

* Add leftover tags janitor and handle resolving leftover tags in CLI. (#305)

* API: Added Tag Janitor.
CLI: Check ecs task exists before attempting to retrieve information on it.

* tag janitor review feedback

* Updated expiredTasks test

* Merge master back into develop (#309)

* Create CNAME

* rename terraform resources. add terraform import lines. add diff supression for deploy.content field. add import system test

* remove crash.log

* remove comment

* update docs, fix unit tests

* Terraform: improve handling of sigterm  (#301)

* rename terraform resources. add terraform import lines. add diff supression for deploy.content field. add import system test

* remove crash.log

* remove comment

* update docs, fix unit tests

* add Layer0Client for meta object

* use waitWithContext helper functions. Remove partial state from service resource

* remove wait

* fix merge

* check error codes for <Entity>DoesNotExist in terraform module

* return <Entity>DoesNotExist error codes from backend layer

* use 's' for receiver

* Return '404 Not Found' errors when resource not found instead of '500 Server Error' errors.

* split out system and stress tests

* Add leftover tags janitor and handle resolving leftover tags in CLI. (#305)

* API: Added Tag Janitor.
CLI: Check ecs task exists before attempting to retrieve information on it.

* tag janitor review feedback

* Updated expiredTasks test

* update docs for 10.3

* l0-setup upgrade: Breadcrumb message when current version is not SemVer compliant (#310)

If the current version of a user's layer0 (as defined in ~/.layer0/<instance>/main.tf.json)
is not semver compliant, this change will notify the user that they can use the --force
flag to override the message.

* Preserving previous error message, tidying up formatting and line length

* 'Tester' iface; prototyping env stress tests with benchmarking

* 232: dep init cleanup, benchmark stress test on multiple dimensions

- The vendor/ dir cleanup is due to running go-dep's `dep init`
- Ignoring Gopkg* and _vendor*
- Benchmark tests are put into its own _test.go file. The pattern is
such that the number of environments, deploys and services are
parameterized when invoking benchmarkStress()

* 232: forcing constraint on github.com/cenkalti/backoff

Unit tests were failing because of very old semver version of this package
Forced it to constrain to the master branch of the project

* 232: dep manifest and lock should probably be included

* 232: Stress tests split into tf modules, folding some changes from 232-tlake

I created three tf modules, environment, service and deploy. The outputs
of environment and deploy are picked up by service. Services are distributed
using element() amongst available environments and deploys.

* 232: Removing defer Terraform.Destroy() and instead explicitly calling Destroy() at end of for loop

* 232: Cleaning up modules, parameterizing Dockerrun.aws.json command

Benchmark tests are no longer in table testing pattern
Dockerrun.aws.json now correctly interpolates the command passed to it by the test
Directory cleanup and organizing of the tf modules

* 232: Minor formatting change

* 232: Modifying the benchmark tests to be more modest in scope

* Add service limits warning

* Update for 'make test'

* Add ListTasks and ListJobs to benchmarks

* 232: Adding Load Balancer parameterization in benchmark stress tests

The benchmark tests now allow creating an arbitrary number of load balancers in a given test
Also made some adjustments to the dimensions of the benchmark tests themselves

* 232: More benchmark stress test cases

* 232: Added a more 'realistic' benchmark test, tested with changes from 232-tlake

* 232: More benchmark tests, terraform fmt adjustments

* 232: Adding comment in README recommending the usage of flow. Makefile timeout set to 2h.

* 232: Actually modifying the README

* 232: 232-stress-tests will not include dep changes, that will be handled by another named branch

* 232: syncing vendor dir state from develop into 232-stress-tests

* 232: Adding specifics of limits in tests/README.md, cutting down the number of benchmark tests

* Update to align with changes in `tftest` package (#332)

* Update to work with changes in tftest

* Remove earlier iteration stress test file

* Use 'testing.B' properly to avoid panic

* split out 'test' and 'benchmark' targets

* Strip out 'StressTest' struct

* Strip out 'StressTest' struct; Simplify function names and arguments

* Add compatibility with 'tftest.Logger'

* Update to use new 'StandardLogger.Logger'

* Add benchmark target to top-level Makefile

* Base of refactoring stress tests to use one terraform config

* DRY out benchmarking code

* Use a single Terraform config for stress tests

* Test entity Get functions in addition to List

* Refactor 'random_shuffle' resources out in favor of 'element()' with inherent modulus

* Transfer test cases into updated pattern

* Remove outdated multi-file terraform configuration

* Remove parametrization of deploy command

* Move 'Tester' iface into 'testutils' package

* Remove 'deploy_command' var

* Refactor task stress test into benchmark pattern

* Add top-of-test checks for entity dependencies

* Strip out go func args

* Don't wait for tasks to finish

* Strip out overcomplicated Task creation logic

* Overhaul test cases to use min/med/max params

* Vendoring update

* Reduce test matrix for Families+Deploys

* Added terraform init to l0-setup init

* Delete terraform

* use cluster names in ListEnvironments

* enable ecs metrics via IAM policy

* [v0.10.4] scaler patch (#472)

* Remove instance.AgentConnected check when gathering resource providers.

* Update test to reflect that agent status is not taken into account

* Log a disconnected agent as info, but do nothing about it

* update terraform module to use region, ami data sources (#471)

* enables terraform AMI, region lookup

* apply terraform fmt

* [v0.10.4] 466: Implement retry and delay logic against AWS API (#468)

* 466: Implement retry and delay logic against AWS API

Recognizes the environment variables LAYER0_AWS_TIME_BETWEEN_REQUESTS
and LAYER0_AWS_MAX_RETRIES.

LAYER0_AWS_TIME_BETWEEN_REQUESTS is a time duration for the min amount
of time allowed between AWS requests

LAYER0_AWS_MAX_RETRIES is a numerical value representing the max
number of times a request will be retried for failures

* MAINT: Review fixes

* MAINT: Undo changes to dynamo db tests

* MAINT: Make common aws config helper function

* 466: Make new helper function to handle session push back

* 466: Change session delay helper function name

* [v0.10.4] 475: Remove AWS Region default and require region for API operation (#476)

* 475: Remove AWS Region default and require region for API operation

* 475: Inclue region as l0-setup endpoint -d output

The AWS Region specified when creating a layer0 instance is now output
when running the command l0-setup endpoint -d.

Fixes an AMI ID for the API module in the us-east-1 region

* 475: Use develop version of setup/module/api/variables.tf

* 475: Use develop version of setup/module/api/variables.tf

* MAINT: Remove default AWS region from config

* [v0.10.4] Decrease ECS API Calls (#474)

* use cluster names in ListEnvironments

* add task environment id resolving

* fix get task

* fix delete and create task

* update task logs

* update list services api call

* update get environment

* chagne scheduler to run once an hour

* Fix api calls on service list for scaling

* use DescribeEnvironmentTasks for scaler

* remove copies from task create

* re-add copies param to task create in cli

* use 'layer0_version' instead of version for tf variable
  • Loading branch information
jparsons04 authored Jan 8, 2018
1 parent 8a26d6f commit ef09161
Show file tree
Hide file tree
Showing 143 changed files with 4,035 additions and 2,420 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ terraform-provider-layer0
*terraform.tfstate*
.vscode/
crash.log
_vendor*
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ smoketest:
$(MAKE) -C tests/smoke test

systemtest:
$(MAKE) -C tests/system test
$(MAKE) -C tests/system test

benchmark:
$(MAKE) -C tests/stress benchmark

install-smoketest:
$(MAKE) -C cli install-smoketest
Expand All @@ -44,4 +47,4 @@ apply-smoketest:
destroy-smoketest:
$(MAKE) -C setup destroy-smoketest

.PHONY: release unittest smoketest install-smoketest apply-smoketest destroy-smoketest systemtest
.PHONY: release unittest smoketest install-smoketest apply-smoketest destroy-smoketest systemtest benchmark
19 changes: 6 additions & 13 deletions api/backend/ecs/environment_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,18 @@ func NewECSEnvironmentManager(
}
}

func (e *ECSEnvironmentManager) ListEnvironments() ([]*models.Environment, error) {
clusters, err := e.ECS.Helper_DescribeClusters()
func (e *ECSEnvironmentManager) ListEnvironments() ([]id.ECSEnvironmentID, error) {
clusterNames, err := e.ECS.ListClusterNames(id.PREFIX)
if err != nil {
return nil, err
}

environments := []*models.Environment{}
for _, cluster := range clusters {
if strings.HasPrefix(*cluster.ClusterName, id.PREFIX) {
ecsEnvironmentID := id.ECSEnvironmentID(*cluster.ClusterName)
environment := &models.Environment{
EnvironmentID: ecsEnvironmentID.L0EnvironmentID(),
}

environments = append(environments, environment)
}
ecsEnvironmentIDs := make([]id.ECSEnvironmentID, len(clusterNames))
for i, clusterName := range clusterNames {
ecsEnvironmentIDs[i] = id.ECSEnvironmentID(clusterName)
}

return environments, nil
return ecsEnvironmentIDs, nil
}

func (e *ECSEnvironmentManager) GetEnvironment(environmentID string) (*models.Environment, error) {
Expand Down
61 changes: 19 additions & 42 deletions api/backend/ecs/environment_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/quintilesims/layer0/common/config"
"github.com/quintilesims/layer0/common/models"
"github.com/quintilesims/layer0/common/testutils"
"github.com/stretchr/testify/assert"
)

type MockECSEnvironmentManager struct {
Expand Down Expand Up @@ -146,55 +147,31 @@ func TestGetEnvironment(t *testing.T) {
}

func TestListEnvironments(t *testing.T) {
testCases := []testutils.TestCase{
{
Name: "Should return layer0-formatted environment ids and use proper params in aws calls",
Setup: func(reporter *testutils.Reporter, ctrl *gomock.Controller) interface{} {
mockEnvironment := NewMockECSEnvironmentManager(ctrl)

ecsEnvironmentID := id.L0EnvironmentID("envid").ECSEnvironmentID()
clusterName := ecsEnvironmentID.String()

mockEnvironment.ECS.EXPECT().
Helper_DescribeClusters().
Return([]*ecs.Cluster{ecs.NewCluster(clusterName)}, nil)
ctrl := gomock.NewController(t)
defer ctrl.Finish()

return mockEnvironment.Environment()
},
Run: func(reporter *testutils.Reporter, target interface{}) {
manager := target.(*ECSEnvironmentManager)
mockEnvironment := NewMockECSEnvironmentManager(ctrl)

environments, err := manager.ListEnvironments()
if err != nil {
reporter.Fatal(err)
}

reporter.AssertEqual(len(environments), 1)
reporter.AssertEqual(environments[0].EnvironmentID, "envid")
},
},
{
Name: "Should propagate ecs.Helper_DescribeClusters error",
Setup: func(reporter *testutils.Reporter, ctrl *gomock.Controller) interface{} {
mockEnvironment := NewMockECSEnvironmentManager(ctrl)
clusterNames := []string{
"env_id1",
"env_id2",
}

mockEnvironment.ECS.EXPECT().
Helper_DescribeClusters().
Return(nil, fmt.Errorf("some_error"))
mockEnvironment.ECS.EXPECT().
ListClusterNames(id.PREFIX).
Return(clusterNames, nil)

return mockEnvironment.Environment()
},
Run: func(reporter *testutils.Reporter, target interface{}) {
manager := target.(*ECSEnvironmentManager)
result, err := mockEnvironment.Environment().ListEnvironments()
if err != nil {
t.Fatal(err)
}

if _, err := manager.ListEnvironments(); err == nil {
reporter.Errorf("Error was nil!")
}
},
},
expected := []id.ECSEnvironmentID{
id.ECSEnvironmentID("env_id1"),
id.ECSEnvironmentID("env_id2"),
}

testutils.RunTests(t, testCases)
assert.Equal(t, result, expected)
}

func TestDeleteEnvironment(t *testing.T) {
Expand Down
5 changes: 2 additions & 3 deletions api/backend/ecs/resource_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func NewECSResourceManager(e ecs.Provider, a autoscaling.Provider) *ECSResourceM
return &ECSResourceManager{
ECS: e,
Autoscaling: a,
logger: logutils.NewStandardLogger("ECS Resource Manager"),
logger: logutils.NewStandardLogger("ECS Resource Manager").Logger,
}
}

Expand Down Expand Up @@ -62,8 +62,7 @@ func (r *ECSResourceManager) getResourceProvider(ecsEnvironmentID id.ECSEnvironm
}

if !pbool(instance.AgentConnected) {
r.logger.Errorf("Instance %s agent is disconnected", instanceID)
return nil, false
r.logger.Infof("Instance %s agent is disconnected", instanceID)
}

// this is non-intuitive, but the ports being used by tasks are kept in
Expand Down
2 changes: 1 addition & 1 deletion api/backend/ecs/resource_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestResourceManager_GetProviders(t *testing.T) {
{
&awsecs.ContainerInstance{
Status: stringp("ACTIVE"),
AgentConnected: boolp(true),
AgentConnected: boolp(false),
RunningTasksCount: int64p(0),
PendingTasksCount: int64p(0),
RemainingResources: []*awsecs.Resource{
Expand Down
42 changes: 31 additions & 11 deletions api/backend/ecs/service_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

log "github.com/Sirupsen/logrus"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/quintilesims/layer0/api/backend"
"github.com/quintilesims/layer0/api/backend/ecs/id"
"github.com/quintilesims/layer0/common/aws/cloudwatchlogs"
Expand Down Expand Up @@ -40,21 +41,25 @@ func NewECSServiceManager(
}
}

func (this *ECSServiceManager) ListServices() ([]*models.Service, error) {
serviceARNs, err := this.ECS.Helper_ListServices(id.PREFIX)
func (this *ECSServiceManager) ListServices() ([]id.ECSServiceID, error) {
clusterNames, err := this.Backend.ListEnvironments()
if err != nil {
return nil, err
}

services := make([]*models.Service, len(serviceARNs))
for i, arn := range serviceARNs {
ecsServiceID := id.ServiceARNToECSServiceID(*arn)
services[i] = &models.Service{
ServiceID: ecsServiceID.L0ServiceID(),
serviceIDs := []id.ECSServiceID{}
for _, clusterName := range clusterNames {
clusterServiceIDs, err := this.ECS.ListClusterServiceNames(clusterName.String(), id.PREFIX)
if err != nil {
return nil, err
}

for _, serviceID := range clusterServiceIDs {
serviceIDs = append(serviceIDs, id.ECSServiceID(serviceID))
}
}

return services, nil
return serviceIDs, nil
}

func (this *ECSServiceManager) GetService(environmentID, serviceID string) (*models.Service, error) {
Expand All @@ -63,9 +68,8 @@ func (this *ECSServiceManager) GetService(environmentID, serviceID string) (*mod

description, err := this.ECS.DescribeService(ecsEnvironmentID.String(), ecsServiceID.String())
if err != nil {
if ContainsErrMsg(err, "Service Not Found") {
err := fmt.Errorf("Service with id '%s' does not exist", serviceID)
return nil, errors.New(errors.ServiceDoesNotExist, err)
if err, ok := err.(awserr.Error); ok && err.Code() == "ServiceNotFoundException" {
return nil, errors.Newf(errors.ServiceDoesNotExist, "Service '%s' does not exist", serviceID)
}

return nil, err
Expand All @@ -74,6 +78,22 @@ func (this *ECSServiceManager) GetService(environmentID, serviceID string) (*mod
return this.populateModel(description), nil
}

func (this *ECSServiceManager) GetEnvironmentServices(environmentID string) ([]*models.Service, error) {
clusterName := id.L0EnvironmentID(environmentID).ECSEnvironmentID()

serviceDescriptions, err := this.ECS.DescribeClusterServices(clusterName.String(), id.PREFIX)
if err != nil {
return nil, err
}

services := make([]*models.Service, len(serviceDescriptions))
for i, description := range serviceDescriptions {
services[i] = this.populateModel(description)
}

return services, nil
}

func (this *ECSServiceManager) UpdateService(
environmentID string,
serviceID string,
Expand Down
85 changes: 25 additions & 60 deletions api/backend/ecs/service_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/quintilesims/layer0/common/aws/ecs/mock_ecs"
"github.com/quintilesims/layer0/common/models"
"github.com/quintilesims/layer0/common/testutils"
"github.com/stretchr/testify/assert"
)

type MockECSServiceManager struct {
Expand Down Expand Up @@ -111,74 +112,38 @@ func TestGetService(t *testing.T) {
}

func TestListServices(t *testing.T) {
testCases := []testutils.TestCase{
{
Name: "Should call ecs.Helper_ListServices with proper params",
Setup: func(reporter *testutils.Reporter, ctrl *gomock.Controller) interface{} {
mockService := NewMockECSServiceManager(ctrl)
ctrl := gomock.NewController(t)
defer ctrl.Finish()

serviceID := id.L0ServiceID("svcid").ECSServiceID()
serviceARN := fmt.Sprintf("arn:aws:ecs:region:aws_account_id:service/%s", serviceID.String())

mockService.ECS.EXPECT().
Helper_ListServices(id.PREFIX).
Return([]*string{&serviceARN}, nil)

return mockService.Service()
},
Run: func(reporter *testutils.Reporter, target interface{}) {
manager := target.(*ECSServiceManager)
manager.ListServices()
},
},
{
Name: "Should return layer0-formatted ids",
Setup: func(reporter *testutils.Reporter, ctrl *gomock.Controller) interface{} {
mockService := NewMockECSServiceManager(ctrl)

serviceID := id.L0ServiceID("svcid").ECSServiceID()
serviceARN := fmt.Sprintf("arn:aws:ecs:region:aws_account_id:service/%s", serviceID.String())

mockService.ECS.EXPECT().
Helper_ListServices(id.PREFIX).
Return([]*string{&serviceARN}, nil)

return mockService.Service()
},
Run: func(reporter *testutils.Reporter, target interface{}) {
manager := target.(*ECSServiceManager)
ecsEnvironmentIDs := []id.ECSEnvironmentID{
id.ECSEnvironmentID("env_id1"),
id.ECSEnvironmentID("env_id2"),
}

services, err := manager.ListServices()
if err != nil {
reporter.Fatal(err)
}
mockService := NewMockECSServiceManager(ctrl)
mockService.Backend.EXPECT().
ListEnvironments().
Return(ecsEnvironmentIDs, nil)

reporter.AssertEqual(len(services), 1)
reporter.AssertEqual(services[0].ServiceID, "svcid")
},
},
{
Name: "Should propagate ecs.Helper_ListServices error",
Setup: func(reporter *testutils.Reporter, ctrl *gomock.Controller) interface{} {
mockService := NewMockECSServiceManager(ctrl)
for i, ecsEnvironmentID := range ecsEnvironmentIDs {
name := fmt.Sprintf("name_%d", i)

mockService.ECS.EXPECT().
Helper_ListServices(gomock.Any()).
Return(nil, fmt.Errorf("some error"))
mockService.ECS.EXPECT().
ListClusterServiceNames(ecsEnvironmentID.String(), id.PREFIX).
Return([]string{name}, nil)
}

return mockService.Service()
},
Run: func(reporter *testutils.Reporter, target interface{}) {
manager := target.(*ECSServiceManager)
result, err := mockService.Service().ListServices()
if err != nil {
t.Fatal(err)
}

if _, err := manager.ListServices(); err == nil {
reporter.Fatalf("Error was nil!")
}
},
},
expected := []id.ECSServiceID{
id.ECSServiceID("name_0"),
id.ECSServiceID("name_1"),
}

testutils.RunTests(t, testCases)
assert.Equal(t, expected, result)
}

func TestDeleteService(t *testing.T) {
Expand Down
Loading

0 comments on commit ef09161

Please sign in to comment.