Skip to content

Commit

Permalink
Merge pull request #17 from olevchyk/master
Browse files Browse the repository at this point in the history
AlreadyExistsException check on stackcreation.
  • Loading branch information
szuecs authored Oct 3, 2018
2 parents 10ce645 + 334c8ab commit 66c0b93
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 37 deletions.
54 changes: 36 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import (
"os"
"os/signal"
"sort"
"strings"
"sync"
"syscall"
"time"

"github.com/cenkalti/backoff"

"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/szuecs/kube-static-egress-controller/kube"
provider "github.com/szuecs/kube-static-egress-controller/provider"
"github.com/szuecs/kube-static-egress-controller/provider"
"github.com/szuecs/kube-static-egress-controller/provider/aws"
"github.com/szuecs/kube-static-egress-controller/provider/noop"
kingpin "gopkg.in/alecthomas/kingpin.v2"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -64,6 +64,18 @@ func NewConfig() *Config {
return &Config{}
}

func newProvider(dry bool, name string, natCidrBlocks, availabilityZones []string, StackTerminationProtection bool) provider.Provider {
switch name {
case aws.ProviderName:
return aws.NewAwsProvider(dry, natCidrBlocks, availabilityZones, StackTerminationProtection)
case noop.ProviderName:
return noop.NewNoopProvider()
default:
log.Fatalf("Unkown provider: %s", name)
}
return nil
}

func allLogLevelsAsStrings() []string {
var levels []string
for _, level := range log.AllLevels {
Expand Down Expand Up @@ -125,7 +137,7 @@ func main() {
log.SetLevel(ll)
log.Debugf("config: %+v", cfg)

p := provider.NewProvider(cfg.DryRun, cfg.Provider, cfg.NatCidrBlocks, cfg.AvailabilityZones, cfg.StackTerminationProtection)
p := newProvider(cfg.DryRun, cfg.Provider, cfg.NatCidrBlocks, cfg.AvailabilityZones, cfg.StackTerminationProtection)
run(newKubeClient(), p)
}

Expand Down Expand Up @@ -270,8 +282,16 @@ func enterProvider(wg *sync.WaitGroup, p provider.Provider, mergerCH <-chan []st
bootstrap = false
continue
}

var err error
createNotify := func(err error, t time.Duration) {
switch errors.Cause(err).(type) {
case *provider.AlreadyExistsError:
err = p.Update(output)
if err != nil {
log.Error(err)
}
}
}
if len(input) == 0 { // not caused by faulty value in CIDR string
if !sameValues(resultCache, output) {
resultCache = output
Expand All @@ -287,27 +307,25 @@ func enterProvider(wg *sync.WaitGroup, p provider.Provider, mergerCH <-chan []st
createFunc := func() error {
return p.Create(output)
}
err = backoff.Retry(createFunc, retry)
err = backoff.RetryNotify(createFunc, retry, createNotify)
if err != nil {
log.Error(err)
}
} else {
err = p.Update(output)
// create if stack does not exist, but we have targets
if err != nil {
switch e := errors.Cause(err).(type) {
case awserr.Error:
log.Infof("%s | %s | %s", e.Code(), e.Message(), e.OrigErr())
if strings.Contains(e.Message(), "does not exist") {
err = p.Create(output)
createFunc := func() error {
return p.Create(output)
}
err = backoff.Retry(createFunc, retry)
if err != nil {
log.Error(err)
}
switch errors.Cause(err).(type) {
case *provider.DoesNotExistError:
createFunc := func() error {
return p.Create(output)
}
err = backoff.RetryNotify(createFunc, retry, createNotify)
if err != nil {
log.Error(err)
}
default:
log.Errorf("Failed to update stack: %v", err)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func Test_enterProvider(t *testing.T) {
{
name: "enterProvider noop quit test",
wg: sync.WaitGroup{},
p: provider.NewProvider(true, noop.ProviderName, []string{}, []string{}, false),
p: newProvider(true, noop.ProviderName, []string{}, []string{}, false),
mergerCH: make(chan []string),
quitCH: make(chan struct{}),
timeout: 3 * time.Second,
Expand Down
12 changes: 12 additions & 0 deletions provider/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudformation"
Expand All @@ -16,6 +17,7 @@ import (
"github.com/linki/instrumented_http"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/szuecs/kube-static-egress-controller/provider"
)

const (
Expand Down Expand Up @@ -304,6 +306,11 @@ func (p *AwsProvider) updateCFStack(nets []string, spec *stackSpec) (string, err

resp, err := p.cloudformation.UpdateStack(params)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "AlreadyExistsException" {
err = provider.NewAlreadyExistsError(fmt.Sprintf("%s AlreadyExists", stackName))
}
}
return spec.name, err
}
return aws.StringValue(resp.StackId), nil
Expand Down Expand Up @@ -335,6 +342,11 @@ func (p *AwsProvider) createCFStack(nets []string, spec *stackSpec) (string, err
resp, err := p.cloudformation.CreateStack(params)
log.Debugf("Stackoutput: %+v", resp)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if strings.Contains(awsErr.Message(), "does not exist") {
err = provider.NewDoesNotExistError(fmt.Sprintf("%s does not exist", stackName))
}
}
return spec.name, err
}
return aws.StringValue(resp.StackId), nil
Expand Down
25 changes: 25 additions & 0 deletions provider/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package provider

type AlreadyExistsError struct {
msg string
}

type DoesNotExistError struct {
msg string
}

func (error *AlreadyExistsError) Error() string {
return error.msg
}

func (error *DoesNotExistError) Error() string {
return error.msg
}

func NewAlreadyExistsError(msg string) error {
return &AlreadyExistsError{msg}
}

func NewDoesNotExistError(msg string) error {
return &DoesNotExistError{msg}
}
18 changes: 0 additions & 18 deletions provider/provider.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
package provider

import (
log "github.com/sirupsen/logrus"
"github.com/szuecs/kube-static-egress-controller/provider/aws"
"github.com/szuecs/kube-static-egress-controller/provider/noop"
)

type Provider interface {
Create([]string) error
Update([]string) error
Delete() error
String() string
}

func NewProvider(dry bool, name string, natCidrBlocks, availabilityZones []string, StackTerminationProtection bool) Provider {
switch name {
case aws.ProviderName:
return aws.NewAwsProvider(dry, natCidrBlocks, availabilityZones, StackTerminationProtection)
case noop.ProviderName:
return noop.NewNoopProvider()
default:
log.Fatalf("Unkown provider: %s", name)
}
return nil
}

0 comments on commit 66c0b93

Please sign in to comment.