-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement cli for state-management
- Loading branch information
1 parent
e5d2e4a
commit b8afcf8
Showing
12 changed files
with
436 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"log" | ||
|
||
"github.com/aws/aws-sdk-go-v2/config" | ||
"github.com/mcastellin/aws-fail-az/awsapis" | ||
"github.com/mcastellin/aws-fail-az/state" | ||
) | ||
|
||
func getManager(namespace string) state.StateManager { | ||
cfg, err := config.LoadDefaultConfig(context.TODO()) | ||
if err != nil { | ||
log.Fatalf("Failed to load AWS configuration: %v", err) | ||
} | ||
|
||
provider := awsapis.NewProviderFromConfig(&cfg) | ||
|
||
return &state.StateManagerImpl{ | ||
Api: awsapis.NewDynamodbApi(&provider), | ||
Namespace: namespace, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/aws/aws-sdk-go-v2/config" | ||
"github.com/mcastellin/aws-fail-az/awsapis" | ||
"github.com/mcastellin/aws-fail-az/service/asg" | ||
"github.com/mcastellin/aws-fail-az/service/ecs" | ||
"github.com/mcastellin/aws-fail-az/state" | ||
) | ||
|
||
func RecoverCommand(namespace string) { | ||
cfg, err := config.LoadDefaultConfig(context.TODO()) | ||
if err != nil { | ||
log.Fatalf("Failed to load AWS configuration: %v", err) | ||
} | ||
provider := awsapis.NewProviderFromConfig(&cfg) | ||
|
||
stateManager := &state.StateManagerImpl{ | ||
Api: awsapis.NewDynamodbApi(&provider), | ||
Namespace: namespace, | ||
} | ||
|
||
stateManager.Initialize() | ||
|
||
states, err := stateManager.ReadStates(&state.QueryStatesInput{}) | ||
if err != nil { | ||
log.Panic(err) | ||
} | ||
for _, s := range states { | ||
if s.ResourceType == ecs.RESOURCE_TYPE { | ||
err = ecs.RestoreFromState(s.State, &provider) | ||
} else if s.ResourceType == asg.RESOURCE_TYPE { | ||
err = asg.RestoreFromState(s.State, &provider) | ||
} else { | ||
err = fmt.Errorf("Unknown resource of type %s found in state with key %s. Object will be ignored.\n", | ||
s.ResourceType, | ||
s.Key, | ||
) | ||
} | ||
|
||
if err != nil { | ||
log.Println(err) | ||
} else { | ||
stateManager.RemoveState(s) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"log" | ||
"os" | ||
|
||
"github.com/mcastellin/aws-fail-az/state" | ||
) | ||
|
||
type ReadStatesOutput struct { | ||
Namespace string `json:"namespace"` | ||
ResourceType string `json:"type"` | ||
ResourceKey string `json:"key"` | ||
State string `json:"state"` | ||
} | ||
|
||
func SaveState(namespace string, | ||
resourceType string, | ||
resourceKey string, | ||
readFromStdin bool, | ||
stateData string) { | ||
|
||
var statePayload []byte | ||
var err error | ||
if readFromStdin { | ||
statePayload, err = io.ReadAll(os.Stdin) | ||
if err != nil { | ||
log.Panic(err) | ||
} | ||
} else { | ||
statePayload = []byte(stateData) | ||
} | ||
|
||
if len(statePayload) == 0 { | ||
log.Fatal("No data was provided to store in state. Exiting.") | ||
} | ||
|
||
stateManager := getManager(namespace) | ||
stateManager.Initialize() | ||
|
||
err = stateManager.Save(resourceType, resourceKey, statePayload) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
func ReadStates(namespace string, resourceType string, resourceKey string) { | ||
|
||
// Discard logging to facilitate output parsing | ||
log.SetOutput(io.Discard) | ||
|
||
stateManager := getManager(namespace) | ||
stateManager.Initialize() | ||
|
||
states, err := stateManager.ReadStates(&state.QueryStatesInput{ | ||
ResourceType: resourceType, | ||
ResourceKey: resourceKey, | ||
}) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
stateData := []ReadStatesOutput{} | ||
for _, s := range states { | ||
stateData = append(stateData, | ||
ReadStatesOutput{ | ||
Namespace: s.Namespace, | ||
ResourceType: s.ResourceType, | ||
ResourceKey: s.ResourceKey, | ||
State: string(s.State), | ||
}) | ||
} | ||
|
||
if len(states) > 0 { | ||
stateJson, err := json.Marshal(stateData) | ||
if err != nil { | ||
fmt.Println("Error unmarshalling state object. Exiting.") | ||
} | ||
fmt.Println(string(stateJson)) | ||
} else { | ||
fmt.Println("[]") | ||
} | ||
} | ||
|
||
func DeleteState(namespace string, resourceType string, resourceKey string) { | ||
|
||
stateManager := getManager(namespace) | ||
stateManager.Initialize() | ||
|
||
result, err := stateManager.GetState(resourceType, resourceKey) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
err = stateManager.RemoveState(*result) | ||
if err != nil { | ||
log.Fatalf("Error removing state object with key %s", result.Key) | ||
} else { | ||
log.Printf("State with key %s removed successfully", result.Key) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package domain | ||
|
||
// An error type to signal the activity has failed and whether or not | ||
// it can be retried | ||
type ActivityFailedError struct { | ||
Wrap error | ||
Temporary bool | ||
} | ||
|
||
func (e ActivityFailedError) Error() string { | ||
return e.Wrap.Error() | ||
} | ||
|
||
func (e ActivityFailedError) IsTemporary() bool { | ||
return e.Temporary | ||
} | ||
|
||
// An error type to signal the current activity has failed and that the | ||
// program execution should be interrupted as soon as possible | ||
type InterruptExecutionError struct { | ||
Wrap error | ||
} | ||
|
||
func (e InterruptExecutionError) Error() string { | ||
return e.Wrap.Error() | ||
} |
Oops, something went wrong.