Skip to content

Commit 9bcfd2a

Browse files
committed
[State] Feat: write current and desired state
1 parent 8170c60 commit 9bcfd2a

File tree

9 files changed

+106
-43
lines changed

9 files changed

+106
-43
lines changed

README.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,28 @@ cp config/config.example.yaml config/config.yaml
3131
# One time run
3232
go run main.go --config ../config/config.yaml
3333

34-
# Web Dashboard
34+
# TODO Web Dashboard
3535
go run main.go web --config ../config/config.yaml
3636
```
3737

38-
using [air](https://github.com/cosmtrek/air) with autoreload UI features
38+
## Installation
39+
### Using go
3940
```bash
40-
air -c .air.toml
41+
go get -u github.com/mensaah/reka
42+
```
43+
44+
## Usage
45+
46+
Reka loads default config from $HOME/.reka.yaml if --config param is not passed.
47+
Copy `config/config.example.yaml` to `config/config.yaml` and make all necessary changes
48+
49+
```bash
50+
cp config/config.example.yaml config/config.yaml
51+
# Run reka using configuration. Stops stoppable resources, resume resumable resources and terminate
52+
# resources dues for termination
53+
reka --config ../config/config.yaml
54+
55+
# KABOOOOOM
56+
# everything gone
57+
reka nuke --config ../config/config.yaml
4158
```

cmd/root.go

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ package cmd
1717

1818
import (
1919
"fmt"
20-
"log"
2120
"os"
2221
"unsafe"
2322

2423
"github.com/spf13/cobra"
2524

2625
homedir "github.com/mitchellh/go-homedir"
26+
log "github.com/sirupsen/logrus"
2727
"github.com/spf13/viper"
2828

2929
"github.com/mensaah/reka/config"
@@ -40,7 +40,7 @@ var (
4040
cfg *config.Config
4141
providers []*provider.Provider
4242
backend state.Backender
43-
currentState state.State
43+
currentState *state.State
4444
)
4545

4646
// rootCmd represents the base command when called without any subcommands
@@ -91,7 +91,7 @@ func initConfig() {
9191

9292
// If a config file is found, read it in.
9393
if err := viper.ReadInConfig(); err == nil {
94-
fmt.Println("Using config file:", viper.ConfigFileUsed())
94+
log.Info("Using config file:", viper.ConfigFileUsed())
9595
}
9696

9797
// Load Config and Defaults
@@ -108,10 +108,8 @@ func initConfig() {
108108
// Initialize Provider objects
109109
providers = initProviders()
110110
backend = state.InitBackend()
111-
currentState = make(state.State)
112111
}
113112

114-
// TODO Add logger to Providers during configuration
115113
func initProviders() []*provider.Provider {
116114
var providers []*provider.Provider
117115
for _, p := range config.GetProviders() {
@@ -135,25 +133,43 @@ func initProviders() []*provider.Provider {
135133
}
136134

137135
// Refresh current status of resources from Providers
136+
// TODO Reconcile state so that new resources are added to desired states and former resources removed
138137
func refreshResources(providers []*provider.Provider) {
138+
// currentState is the state stored in backend
139+
currentState = backend.GetState()
140+
141+
currentState.Current = make(state.ProvidersState)
139142
for _, provider := range providers {
140143
allResources := provider.GetAllResources()
141-
currentState[provider.Name] = allResources
142-
143-
// stoppableResources := provider.GetStoppableResources(allResources)
144-
// fmt.Println("Stoppable Resources: ", stoppableResources)
145-
// errs := provider.StopResources(stoppableResources)
146-
// fmt.Println("Errors Stopping Resources: ", errs)
147-
148-
// resumableResources := provider.GetResumableResources(allResources)
149-
// fmt.Println("Resumable Resources: ", resumableResources)
150-
// errs = provider.ResumeResources(resumableResources)
151-
// fmt.Println("Errors Resuming Resources: ", errs)
152-
153-
destroyableResources := provider.GetDestroyableResources(allResources)
154-
fmt.Println("Destroyable Resources: ", destroyableResources)
155-
// errs = provider.DestroyResources(destroyableResources)
156-
// fmt.Println("Errors Destroying Resources: ", errs)
144+
currentState.Current[provider.Name] = allResources
145+
}
146+
147+
// Add new resources to desired state if they don't already exists
148+
for k, v := range currentState.Current {
149+
if m, ok := currentState.Desired[k]; ok || currentState.Desired[k] == nil {
150+
log.Error(m)
151+
// TODO Return difference between two Resources object
152+
continue
153+
}
154+
currentState.Desired[k] = v
157155
}
158-
backend.WriteState(&currentState)
156+
157+
backend.WriteState(currentState)
158+
}
159+
160+
func reapResources() {
161+
// stoppableResources := provider.GetStoppableResources(allResources)
162+
// fmt.Println("Stoppable Resources: ", stoppableResources)
163+
// errs := provider.StopResources(stoppableResources)
164+
// fmt.Println("Errors Stopping Resources: ", errs)
165+
166+
// resumableResources := provider.GetResumableResources(allResources)
167+
// fmt.Println("Resumable Resources: ", resumableResources)
168+
// errs = provider.ResumeResources(resumableResources)
169+
// fmt.Println("Errors Resuming Resources: ", errs)
170+
171+
// destroyableResources := provider.GetDestroyableResources(allResources)
172+
// fmt.Println("Destroyable Resources: ", destroyableResources)
173+
// errs = provider.DestroyResources(destroyableResources)
174+
// fmt.Println("Errors Destroying Resources: ", errs)
159175
}

provider/aws/ec2_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var ec2Manager resource.Manager
1414

1515
const (
1616
// Name of resource
17-
ec2Name = "EC2"
17+
ec2Name = "ec2"
1818
// LongName descriptive name for resource
1919
ec2LongName = "Elastic Compute Cloud"
2020
)

provider/aws/eip_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var eipManager resource.Manager
1212

1313
const (
1414
// Name of resource
15-
eipName = "EIP"
15+
eipName = "eip"
1616
// LongName descriptive name for resource
1717
eipLongName = "Elastic IP"
1818
)

provider/aws/eks_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var eksManager resource.Manager
1414

1515
const (
1616
// Name of resource
17-
eksName = "EKS"
17+
eksName = "eks"
1818
// LongName descriptive name for resource
1919
eksLongName = "Elastic Compute Cloud"
2020

provider/aws/s3_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
const (
1111
// Name of resource
12-
s3Name = "S3"
12+
s3Name = "s3"
1313
// LongName descriptive name for resource
1414
s3LongName = "Simple Storage Service"
1515
)

state/backend.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type Backender interface {
1515

1616
// Reader is the interface for state types that can return state resources
1717
type Reader interface {
18-
Get() *State
18+
GetState() *State
1919
}
2020

2121
// Writer is the interface for state types that can write to state files
@@ -31,8 +31,10 @@ func InitBackend() Backender {
3131
switch cfg.StateBackend.Type {
3232
default:
3333
log.Debugf("using Local State at %s", cfg.StateBackend.Path)
34+
s := NewEmptyState()
3435
backend = LocalBackend{
35-
Path: cfg.StateBackend.Path,
36+
Path: cfg.StateBackend.Path,
37+
state: &s,
3638
}
3739
}
3840
return backend

state/local.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ type LocalBackend struct {
1616
Path string
1717
}
1818

19-
// Get returns state from local source
20-
func (s LocalBackend) Get() *State {
21-
if s.state.empty() {
19+
// GetState returns state from local source
20+
func (s LocalBackend) GetState() *State {
21+
if s.state.Empty() {
2222
if _, err := os.Stat(s.Path); os.IsNotExist(err) {
23-
s.state = &State{}
23+
log.Debugf("State file not found, using empty state")
2424
return s.state
2525
}
2626
stateFile, err := os.Open(s.Path)

state/state.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,49 @@ import (
88
var backend Backender
99
var cfg *config.Config
1010

11-
// State object: Represents a reka state consisting of resources
12-
// aws: {
11+
// ProvidersState represents state for providers
12+
// {
13+
// aws: {
1314
// s3: [ Resource1, Resource2 ]
15+
// }
16+
// }
17+
type ProvidersState map[string]provider.Resources
18+
19+
// State object: Represents a reka state consisting of current and desired state
20+
// Desired state is used for resumption of resources. It stores the attributes of the resource to resume to
21+
// for resources that need extra info like size of node pool to resize to
22+
// current: {
23+
// aws: {
24+
// s3: [ Resource1, Resource2 ]
25+
// }
26+
// }
27+
// desired: {
28+
// aws: {
29+
// s3: [ Resource1, Resource2 ]
30+
// }
1431
// }
15-
type State map[string]provider.Resources
32+
// State object stores state for both current and desired states
33+
// of resources
34+
type State struct {
35+
Current ProvidersState
36+
Desired ProvidersState
37+
}
1638

17-
func (s *State) diff(st *State) State {
18-
return Diff(s, st)
39+
func (s *State) diff() State {
40+
return Diff(s.Desired, s.Current)
1941
}
2042

21-
func (s State) empty() bool {
22-
return len(s) == 0
43+
// Empty checks if state is empty
44+
func (s State) Empty() bool {
45+
return len(s.Current) == 0 && len(s.Desired) == 0
2346
}
2447

2548
// Diff returns the difference in between two states
26-
func Diff(previous, current *State) State {
49+
func Diff(previous, current ProvidersState) State {
2750
return State{}
2851
}
52+
53+
// NewEmptyState gets a new empty state
54+
func NewEmptyState() State {
55+
return State{Desired: make(ProvidersState), Current: make(ProvidersState)}
56+
}

0 commit comments

Comments
 (0)