sqs-browse: remove assumption regarding table keys

Table keys are now retrieved from describe
This commit is contained in:
Leon Mika 2022-03-25 08:17:52 +11:00
parent 3428bd2a8a
commit 5a69e6c954
47 changed files with 150 additions and 98 deletions

View file

@ -4,6 +4,8 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"os"
"github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
@ -15,7 +17,6 @@ import (
"github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/internal/dynamo-browse/services/tables"
"github.com/lmika/awstools/internal/dynamo-browse/ui" "github.com/lmika/awstools/internal/dynamo-browse/ui"
"github.com/lmika/gopkgs/cli" "github.com/lmika/gopkgs/cli"
"os"
) )
func main() { func main() {
@ -49,8 +50,8 @@ func main() {
commandController := commandctrl.NewCommandController(map[string]uimodels.Operation{ commandController := commandctrl.NewCommandController(map[string]uimodels.Operation{
"scan": tableReadController.Scan(), "scan": tableReadController.Scan(),
"rw": tableWriteController.ToggleReadWrite(), "rw": tableWriteController.ToggleReadWrite(),
"dup": tableWriteController.Duplicate(), "dup": tableWriteController.Duplicate(),
}) })
uiModel := ui.NewModel(uiDispatcher, commandController, tableReadController, tableWriteController) uiModel := ui.NewModel(uiDispatcher, commandController, tableReadController, tableWriteController)
@ -77,4 +78,3 @@ type msgLoopback struct {
func (m *msgLoopback) Send(msg tea.Msg) { func (m *msgLoopback) Send(msg tea.Msg) {
m.program.Send(msg) m.program.Send(msg)
} }

View file

@ -4,6 +4,9 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"log"
"os"
"github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/aws/aws-sdk-go-v2/service/sqs"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
@ -17,8 +20,6 @@ import (
"github.com/lmika/awstools/internal/sqs-browse/ui" "github.com/lmika/awstools/internal/sqs-browse/ui"
"github.com/lmika/events" "github.com/lmika/events"
"github.com/lmika/gopkgs/cli" "github.com/lmika/gopkgs/cli"
"log"
"os"
) )
func main() { func main() {
@ -39,7 +40,7 @@ func main() {
if err != nil { if err != nil {
cli.Fatalf("cannot create workspace file: %v", err) cli.Fatalf("cannot create workspace file: %v", err)
} }
workspaceFile.Close() // We just need the filename workspaceFile.Close() // We just need the filename
msgStore, err := stormstore.NewStore(workspaceFile.Name()) msgStore, err := stormstore.NewStore(workspaceFile.Name())
if err != nil { if err != nil {

View file

@ -3,15 +3,16 @@ package main
import ( import (
"context" "context"
"flag" "flag"
"log"
"os"
"path/filepath"
"time"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/aws/aws-sdk-go-v2/service/sqs"
"github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/aws/aws-sdk-go-v2/service/sqs/types"
"github.com/pkg/errors" "github.com/pkg/errors"
"log"
"os"
"path/filepath"
"time"
"github.com/lmika/gopkgs/cli" "github.com/lmika/gopkgs/cli"
) )
@ -44,9 +45,9 @@ func main() {
msgCount := 0 msgCount := 0
for { for {
out, err := client.ReceiveMessage(ctx, &sqs.ReceiveMessageInput{ out, err := client.ReceiveMessage(ctx, &sqs.ReceiveMessageInput{
QueueUrl: aws.String(*flagQueue), QueueUrl: aws.String(*flagQueue),
MaxNumberOfMessages: 10, MaxNumberOfMessages: 10,
WaitTimeSeconds: 1, WaitTimeSeconds: 1,
}) })
if err != nil { if err != nil {
log.Fatalf("error receiving messages: %v", err) log.Fatalf("error receiving messages: %v", err)
@ -59,7 +60,7 @@ func main() {
for _, msg := range out.Messages { for _, msg := range out.Messages {
if err := handleMessage(ctx, outDir, msg); err == nil { if err := handleMessage(ctx, outDir, msg); err == nil {
messagesToDelete = append(messagesToDelete, types.DeleteMessageBatchRequestEntry{ messagesToDelete = append(messagesToDelete, types.DeleteMessageBatchRequestEntry{
Id: msg.MessageId, Id: msg.MessageId,
ReceiptHandle: msg.ReceiptHandle, ReceiptHandle: msg.ReceiptHandle,
}) })
msgCount += 1 msgCount += 1
@ -74,7 +75,7 @@ func main() {
if _, err := client.DeleteMessageBatch(ctx, &sqs.DeleteMessageBatchInput{ if _, err := client.DeleteMessageBatch(ctx, &sqs.DeleteMessageBatchInput{
QueueUrl: aws.String(*flagQueue), QueueUrl: aws.String(*flagQueue),
Entries: messagesToDelete, Entries: messagesToDelete,
}); err != nil { }); err != nil {
log.Printf("error deleting messages from queue: %v", err) log.Printf("error deleting messages from queue: %v", err)
break break
@ -85,7 +86,7 @@ func main() {
} }
func handleMessage(ctx context.Context, outDir string, msg types.Message) error { func handleMessage(ctx context.Context, outDir string, msg types.Message) error {
outFile := filepath.Join(outDir, aws.ToString(msg.MessageId) + ".json") outFile := filepath.Join(outDir, aws.ToString(msg.MessageId)+".json")
msgBody := aws.ToString(msg.Body) msgBody := aws.ToString(msg.Body)
log.Printf("%v -> %v", aws.ToString(msg.MessageId), outFile) log.Printf("%v -> %v", aws.ToString(msg.MessageId), outFile)

View file

@ -2,11 +2,12 @@ package commandctrl
import ( import (
"context" "context"
"strings"
"github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/common/ui/events"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/shellwords" "github.com/lmika/shellwords"
"github.com/pkg/errors" "github.com/pkg/errors"
"strings"
) )
type CommandController struct { type CommandController struct {
@ -45,4 +46,4 @@ func (c *CommandController) Execute() uimodels.Operation {
return command.Execute(WithCommandArgs(ctx, tokens[1:])) return command.Execute(WithCommandArgs(ctx, tokens[1:]))
}) })
} }

View file

@ -2,11 +2,12 @@ package commandctrl_test
import ( import (
"context" "context"
"testing"
"github.com/lmika/awstools/internal/common/ui/commandctrl" "github.com/lmika/awstools/internal/common/ui/commandctrl"
"github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/common/ui/events"
"github.com/lmika/awstools/test/testuictx" "github.com/lmika/awstools/test/testuictx"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestCommandController_Prompt(t *testing.T) { func TestCommandController_Prompt(t *testing.T) {

View file

@ -2,7 +2,8 @@ package commandctrl
import "context" import "context"
type commandArgContextKeyType struct {} type commandArgContextKeyType struct{}
var commandArgContextKey = commandArgContextKeyType{} var commandArgContextKey = commandArgContextKeyType{}
func WithCommandArgs(ctx context.Context, args []string) context.Context { func WithCommandArgs(ctx context.Context, args []string) context.Context {
@ -12,4 +13,4 @@ func WithCommandArgs(ctx context.Context, args []string) context.Context {
func CommandArgs(ctx context.Context) []string { func CommandArgs(ctx context.Context) []string {
args, _ := ctx.Value(commandArgContextKey).([]string) args, _ := ctx.Value(commandArgContextKey).([]string)
return args return args
} }

View file

@ -2,6 +2,7 @@ package dispatcher
import ( import (
"fmt" "fmt"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/common/ui/events"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"

View file

@ -2,10 +2,11 @@ package dispatcher
import ( import (
"context" "context"
"sync"
"github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/common/ui/events"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/pkg/errors" "github.com/pkg/errors"
"sync"
) )
type Dispatcher struct { type Dispatcher struct {
@ -14,7 +15,6 @@ type Dispatcher struct {
publisher MessagePublisher publisher MessagePublisher
} }
func NewDispatcher(publisher MessagePublisher) *Dispatcher { func NewDispatcher(publisher MessagePublisher) *Dispatcher {
return &Dispatcher{ return &Dispatcher{
mutex: new(sync.Mutex), mutex: new(sync.Mutex),
@ -44,6 +44,3 @@ func (d *Dispatcher) Start(ctx context.Context, operation uimodels.Operation) {
d.runningOp = nil d.runningOp = nil
}() }()
} }

View file

@ -4,4 +4,4 @@ import tea "github.com/charmbracelet/bubbletea"
type MessagePublisher interface { type MessagePublisher interface {
Send(msg tea.Msg) Send(msg tea.Msg)
} }

View file

@ -14,4 +14,4 @@ type Message string
type PromptForInput struct { type PromptForInput struct {
Prompt string Prompt string
OnDone uimodels.Operation OnDone uimodels.Operation
} }

View file

@ -2,7 +2,8 @@ package uimodels
import "context" import "context"
type uiContextKeyType struct {} type uiContextKeyType struct{}
var uiContextKey = uiContextKeyType{} var uiContextKey = uiContextKeyType{}
func Ctx(ctx context.Context) UIContext { func Ctx(ctx context.Context) UIContext {

View file

@ -11,4 +11,3 @@ type OperationFn func(ctx context.Context) error
func (f OperationFn) Execute(ctx context.Context) error { func (f OperationFn) Execute(ctx context.Context) error {
return f(ctx) return f(ctx)
} }

View file

@ -2,7 +2,8 @@ package uimodels
import "context" import "context"
type promptValueKeyType struct {} type promptValueKeyType struct{}
var promptValueKey = promptValueKeyType{} var promptValueKey = promptValueKeyType{}
func PromptValue(ctx context.Context) string { func PromptValue(ctx context.Context) string {

View file

@ -8,4 +8,4 @@ type NewResultSet struct {
type SetReadWrite struct { type SetReadWrite struct {
NewValue bool NewValue bool
} }

View file

@ -2,6 +2,7 @@ package controllers
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
) )

View file

@ -2,6 +2,7 @@ package controllers
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
"github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/internal/dynamo-browse/services/tables"

View file

@ -2,6 +2,7 @@ package controllers
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/awstools/internal/dynamo-browse/models/modexpr" "github.com/lmika/awstools/internal/dynamo-browse/models/modexpr"
"github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/internal/dynamo-browse/services/tables"
@ -9,16 +10,16 @@ import (
) )
type TableWriteController struct { type TableWriteController struct {
tableService *tables.Service tableService *tables.Service
tableReadControllers *TableReadController tableReadControllers *TableReadController
tableName string tableName string
} }
func NewTableWriteController(tableService *tables.Service, tableReadControllers *TableReadController, tableName string) *TableWriteController { func NewTableWriteController(tableService *tables.Service, tableReadControllers *TableReadController, tableName string) *TableWriteController {
return &TableWriteController{ return &TableWriteController{
tableService: tableService, tableService: tableService,
tableReadControllers: tableReadControllers, tableReadControllers: tableReadControllers,
tableName: tableName, tableName: tableName,
} }
} }

View file

@ -2,6 +2,8 @@ package controllers_test
import ( import (
"context" "context"
"testing"
"github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/common/ui/events"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/awstools/internal/dynamo-browse/controllers" "github.com/lmika/awstools/internal/dynamo-browse/controllers"
@ -10,7 +12,6 @@ import (
"github.com/lmika/awstools/test/testdynamo" "github.com/lmika/awstools/test/testdynamo"
"github.com/lmika/awstools/test/testuictx" "github.com/lmika/awstools/test/testuictx"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestTableWriteController_ToggleReadWrite(t *testing.T) { func TestTableWriteController_ToggleReadWrite(t *testing.T) {
@ -47,7 +48,10 @@ func TestTableWriteController_Delete(t *testing.T) {
twc, ctrls, closeFn := setupController(t) twc, ctrls, closeFn := setupController(t)
t.Cleanup(closeFn) t.Cleanup(closeFn)
resultSet, err := ctrls.tableService.Scan(context.Background(), ctrls.tableName) ti, err := ctrls.tableService.Describe(context.Background(), ctrls.tableName)
assert.NoError(t, err)
resultSet, err := ctrls.tableService.Scan(context.Background(), ti)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, resultSet.Items, 3) assert.Len(t, resultSet.Items, 3)
@ -71,7 +75,7 @@ func TestTableWriteController_Delete(t *testing.T) {
err = promptRequest.OnDone.Execute(uimodels.WithPromptValue(ctx, "y")) err = promptRequest.OnDone.Execute(uimodels.WithPromptValue(ctx, "y"))
assert.NoError(t, err) assert.NoError(t, err)
afterResultSet, err := ctrls.tableService.Scan(context.Background(), ctrls.tableName) afterResultSet, err := ctrls.tableService.Scan(context.Background(), ti)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, afterResultSet.Items, 2) assert.Len(t, afterResultSet.Items, 2)
assert.Contains(t, afterResultSet.Items, resultSet.Items[0]) assert.Contains(t, afterResultSet.Items, resultSet.Items[0])
@ -83,7 +87,10 @@ func TestTableWriteController_Delete(t *testing.T) {
twc, ctrls, closeFn := setupController(t) twc, ctrls, closeFn := setupController(t)
t.Cleanup(closeFn) t.Cleanup(closeFn)
resultSet, err := ctrls.tableService.Scan(context.Background(), ctrls.tableName) ti, err := ctrls.tableService.Describe(context.Background(), ctrls.tableName)
assert.NoError(t, err)
resultSet, err := ctrls.tableService.Scan(context.Background(), ti)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, resultSet.Items, 3) assert.Len(t, resultSet.Items, 3)
@ -107,7 +114,7 @@ func TestTableWriteController_Delete(t *testing.T) {
err = promptRequest.OnDone.Execute(uimodels.WithPromptValue(ctx, "n")) err = promptRequest.OnDone.Execute(uimodels.WithPromptValue(ctx, "n"))
assert.Error(t, err) assert.Error(t, err)
afterResultSet, err := ctrls.tableService.Scan(context.Background(), ctrls.tableName) afterResultSet, err := ctrls.tableService.Scan(context.Background(), ti)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, afterResultSet.Items, 3) assert.Len(t, afterResultSet.Items, 3)
assert.Contains(t, afterResultSet.Items, resultSet.Items[0]) assert.Contains(t, afterResultSet.Items, resultSet.Items[0])
@ -119,7 +126,10 @@ func TestTableWriteController_Delete(t *testing.T) {
tableWriteController, ctrls, closeFn := setupController(t) tableWriteController, ctrls, closeFn := setupController(t)
t.Cleanup(closeFn) t.Cleanup(closeFn)
resultSet, err := ctrls.tableService.Scan(context.Background(), ctrls.tableName) ti, err := ctrls.tableService.Describe(context.Background(), ctrls.tableName)
assert.NoError(t, err)
resultSet, err := ctrls.tableService.Scan(context.Background(), ti)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, resultSet.Items, 3) assert.Len(t, resultSet.Items, 3)
@ -174,4 +184,4 @@ var testData = testdynamo.TestData{
"beta": 2468, "beta": 2468,
"gamma": "foobar", "gamma": "foobar",
}, },
} }

View file

@ -1,8 +1,9 @@
package models package models
import ( import (
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"math/big" "math/big"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
) )
func compareScalarAttributes(x, y types.AttributeValue) (int, bool) { func compareScalarAttributes(x, y types.AttributeValue) (int, bool) {

View file

@ -29,4 +29,4 @@ func (i Item) KeyValue(info *TableInfo) map[string]types.AttributeValue {
itemKey[info.Keys.SortKey] = i[info.Keys.SortKey] itemKey[info.Keys.SortKey] = i[info.Keys.SortKey]
} }
return itemKey return itemKey
} }

View file

@ -32,4 +32,4 @@ func Parse(expr string) (*ModExpr, error) {
} }
return &ModExpr{ast: &ast}, nil return &ModExpr{ast: &ast}, nil
} }

View file

@ -1,11 +1,12 @@
package modexpr_test package modexpr_test
import ( import (
"testing"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
"github.com/lmika/awstools/internal/dynamo-browse/models/modexpr" "github.com/lmika/awstools/internal/dynamo-browse/models/modexpr"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestModExpr_Patch(t *testing.T) { func TestModExpr_Patch(t *testing.T) {
@ -26,7 +27,7 @@ func TestModExpr_Patch(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
oldItem := models.Item{ oldItem := models.Item{
"old": &types.AttributeValueMemberS{Value: "before"}, "old": &types.AttributeValueMemberS{Value: "before"},
"beta": &types.AttributeValueMemberS{Value: "before beta"}, "beta": &types.AttributeValueMemberS{Value: "before beta"},
} }
newItem, err := modExpr.Patch(oldItem) newItem, err := modExpr.Patch(oldItem)
@ -42,7 +43,7 @@ func TestModExpr_Patch(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
oldItem := models.Item{ oldItem := models.Item{
"old": &types.AttributeValueMemberS{Value: "before"}, "old": &types.AttributeValueMemberS{Value: "before"},
"beta": &types.AttributeValueMemberS{Value: "before beta"}, "beta": &types.AttributeValueMemberS{Value: "before beta"},
} }
newItem, err := modExpr.Patch(oldItem) newItem, err := modExpr.Patch(oldItem)

View file

@ -10,8 +10,8 @@ type patchMod interface {
} }
type setAttributeMod struct { type setAttributeMod struct {
key string key string
to types.AttributeValue to types.AttributeValue
} }
func (sa setAttributeMod) Apply(item models.Item) { func (sa setAttributeMod) Apply(item models.Item) {

View file

@ -1,9 +1,10 @@
package modexpr package modexpr
import ( import (
"strconv"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/pkg/errors" "github.com/pkg/errors"
"strconv"
) )
func (a *astLiteralValue) dynamoValue() (types.AttributeValue, error) { func (a *astLiteralValue) dynamoValue() (types.AttributeValue, error) {

View file

@ -1,18 +1,21 @@
package models_test package models_test
import ( import (
"testing"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestSort(t *testing.T) { func TestSort(t *testing.T) {
t.Run("pk and sk are both strings", func(t *testing.T) { t.Run("pk and sk are both strings", func(t *testing.T) {
tableInfo := &models.TableInfo{Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"}}
items := make([]models.Item, len(testStringData)) items := make([]models.Item, len(testStringData))
copy(items, testStringData) copy(items, testStringData)
models.Sort(items, "pk", "sk") models.Sort(items, tableInfo)
assert.Equal(t, items[0], testStringData[1]) assert.Equal(t, items[0], testStringData[1])
assert.Equal(t, items[1], testStringData[2]) assert.Equal(t, items[1], testStringData[2])
@ -20,10 +23,12 @@ func TestSort(t *testing.T) {
}) })
t.Run("pk and sk are both numbers", func(t *testing.T) { t.Run("pk and sk are both numbers", func(t *testing.T) {
tableInfo := &models.TableInfo{Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"}}
items := make([]models.Item, len(testNumberData)) items := make([]models.Item, len(testNumberData))
copy(items, testNumberData) copy(items, testNumberData)
models.Sort(items, "pk", "sk") models.Sort(items, tableInfo)
assert.Equal(t, items[0], testNumberData[2]) assert.Equal(t, items[0], testNumberData[2])
assert.Equal(t, items[1], testNumberData[1]) assert.Equal(t, items[1], testNumberData[1])
@ -31,10 +36,12 @@ func TestSort(t *testing.T) {
}) })
t.Run("pk and sk are both bools", func(t *testing.T) { t.Run("pk and sk are both bools", func(t *testing.T) {
tableInfo := &models.TableInfo{Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"}}
items := make([]models.Item, len(testBoolData)) items := make([]models.Item, len(testBoolData))
copy(items, testBoolData) copy(items, testBoolData)
models.Sort(items, "pk", "sk") models.Sort(items, tableInfo)
assert.Equal(t, items[0], testBoolData[2]) assert.Equal(t, items[0], testBoolData[2])
assert.Equal(t, items[1], testBoolData[1]) assert.Equal(t, items[1], testBoolData[1])

View file

@ -2,6 +2,7 @@ package dynamo
import ( import (
"context" "context"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
@ -42,7 +43,7 @@ func (p *Provider) DescribeTable(ctx context.Context, tableName string) (*models
func (p *Provider) PutItem(ctx context.Context, name string, item models.Item) error { func (p *Provider) PutItem(ctx context.Context, name string, item models.Item) error {
_, err := p.client.PutItem(ctx, &dynamodb.PutItemInput{ _, err := p.client.PutItem(ctx, &dynamodb.PutItemInput{
TableName: aws.String(name), TableName: aws.String(name),
Item: item, Item: item,
}) })
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot execute put on table %v", name) return errors.Wrapf(err, "cannot execute put on table %v", name)
@ -73,7 +74,7 @@ func (p *Provider) ScanItems(ctx context.Context, tableName string) ([]models.It
func (p *Provider) DeleteItem(ctx context.Context, tableName string, key map[string]types.AttributeValue) error { func (p *Provider) DeleteItem(ctx context.Context, tableName string, key map[string]types.AttributeValue) error {
_, err := p.client.DeleteItem(ctx, &dynamodb.DeleteItemInput{ _, err := p.client.DeleteItem(ctx, &dynamodb.DeleteItemInput{
TableName: aws.String(tableName), TableName: aws.String(tableName),
Key: key, Key: key,
}) })
return errors.Wrap(err, "could not delete item") return errors.Wrap(err, "could not delete item")
} }

View file

@ -2,11 +2,12 @@ package dynamo_test
import ( import (
"context" "context"
"testing"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" "github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo"
"github.com/lmika/awstools/test/testdynamo" "github.com/lmika/awstools/test/testdynamo"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestProvider_ScanItems(t *testing.T) { func TestProvider_ScanItems(t *testing.T) {

View file

@ -2,6 +2,7 @@ package tables
import ( import (
"context" "context"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
) )

View file

@ -2,9 +2,10 @@ package tables
import ( import (
"context" "context"
"sort"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
"github.com/pkg/errors" "github.com/pkg/errors"
"sort"
) )
type Service struct { type Service struct {
@ -63,9 +64,9 @@ func (s *Service) Scan(ctx context.Context, tableInfo *models.TableInfo) (*model
models.Sort(results, tableInfo) models.Sort(results, tableInfo)
return &models.ResultSet{ return &models.ResultSet{
TableInfo: tableInfo, TableInfo: tableInfo,
Columns: columns, Columns: columns,
Items: results, Items: results,
}, nil }, nil
} }

View file

@ -2,11 +2,12 @@ package tables_test
import ( import (
"context" "context"
"testing"
"github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" "github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo"
"github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/internal/dynamo-browse/services/tables"
"github.com/lmika/awstools/test/testdynamo" "github.com/lmika/awstools/test/testdynamo"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestService_Describe(t *testing.T) { func TestService_Describe(t *testing.T) {

View file

@ -3,6 +3,9 @@ package ui
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"text/tabwriter"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
table "github.com/calyptia/go-bubble-table" table "github.com/calyptia/go-bubble-table"
"github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/textinput"
@ -14,8 +17,6 @@ import (
"github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/common/ui/events"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/awstools/internal/dynamo-browse/controllers" "github.com/lmika/awstools/internal/dynamo-browse/controllers"
"strings"
"text/tabwriter"
) )
var ( var (
@ -156,7 +157,7 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// Tea events // Tea events
case tea.WindowSizeMsg: case tea.WindowSizeMsg:
fixedViewsHeight := lipgloss.Height(m.headerView()) + lipgloss.Height(m.splitterView()) + lipgloss.Height(m.footerView()) fixedViewsHeight := lipgloss.Height(m.headerView()) + lipgloss.Height(m.splitterView()) + lipgloss.Height(m.footerView())
viewportHeight := msg.Height / 2 // TODO: make this dynamic viewportHeight := msg.Height / 2 // TODO: make this dynamic
if viewportHeight > 15 { if viewportHeight > 15 {
viewportHeight = 15 viewportHeight = 15
} }

View file

@ -2,11 +2,12 @@ package ui
import ( import (
"fmt" "fmt"
"io"
"strings"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
table "github.com/calyptia/go-bubble-table" table "github.com/calyptia/go-bubble-table"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
"io"
"strings"
) )
type itemTableRow struct { type itemTableRow struct {

View file

@ -2,6 +2,7 @@ package controllers
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
"github.com/lmika/awstools/internal/sqs-browse/services/messages" "github.com/lmika/awstools/internal/sqs-browse/services/messages"

View file

@ -3,9 +3,9 @@ package models
import "time" import "time"
type Message struct { type Message struct {
ID uint64 `storm:"id,increment"` ID uint64 `storm:"id,increment"`
ExtID string `storm:"unique"` ExtID string `storm:"unique"`
Queue string `storm:"index"` Queue string `storm:"index"`
Received time.Time Received time.Time
Data string Data string
} }

View file

@ -2,13 +2,14 @@ package sqs
import ( import (
"context" "context"
"log"
"time"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/aws/aws-sdk-go-v2/service/sqs"
"github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/aws/aws-sdk-go-v2/service/sqs/types"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
"github.com/pkg/errors" "github.com/pkg/errors"
"log"
"time"
) )
type Provider struct { type Provider struct {
@ -23,7 +24,7 @@ func (p *Provider) SendMessage(ctx context.Context, msg models.Message, queue st
// TEMP :: queue URL // TEMP :: queue URL
out, err := p.client.SendMessage(ctx, &sqs.SendMessageInput{ out, err := p.client.SendMessage(ctx, &sqs.SendMessageInput{
QueueUrl: aws.String(queue), QueueUrl: aws.String(queue),
MessageBody: aws.String(msg.Data), MessageBody: aws.String(msg.Data),
}) })
if err != nil { if err != nil {

View file

@ -2,6 +2,7 @@ package stormstore
import ( import (
"context" "context"
"github.com/asdine/storm" "github.com/asdine/storm"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
"github.com/pkg/errors" "github.com/pkg/errors"

View file

@ -2,9 +2,10 @@ package messages
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
) )
type MessageSender interface { type MessageSender interface {
SendMessage(ctx context.Context, msg models.Message, queue string) (string, error) SendMessage(ctx context.Context, msg models.Message, queue string) (string, error)
} }

View file

@ -2,6 +2,7 @@ package messages
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
"github.com/pkg/errors" "github.com/pkg/errors"
) )

View file

@ -2,6 +2,7 @@ package pollmessage
import ( import (
"context" "context"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
) )
@ -11,4 +12,4 @@ type MessageStore interface {
type MessagePoller interface { type MessagePoller interface {
PollForNewMessages(ctx context.Context, queue string) ([]*models.Message, error) PollForNewMessages(ctx context.Context, queue string) ([]*models.Message, error)
} }

View file

@ -2,9 +2,10 @@ package pollmessage
import ( import (
"context" "context"
"log"
"github.com/lmika/events" "github.com/lmika/events"
"github.com/pkg/errors" "github.com/pkg/errors"
"log"
) )
type Service struct { type Service struct {

View file

@ -2,4 +2,4 @@ package ui
import "github.com/lmika/awstools/internal/sqs-browse/models" import "github.com/lmika/awstools/internal/sqs-browse/models"
type NewMessagesEvent []*models.Message type NewMessagesEvent []*models.Message

View file

@ -4,6 +4,9 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"log"
"strings"
table "github.com/calyptia/go-bubble-table" table "github.com/calyptia/go-bubble-table"
"github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/textinput"
"github.com/charmbracelet/bubbles/viewport" "github.com/charmbracelet/bubbles/viewport"
@ -14,19 +17,17 @@ import (
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"
"github.com/lmika/awstools/internal/sqs-browse/controllers" "github.com/lmika/awstools/internal/sqs-browse/controllers"
"github.com/lmika/awstools/internal/sqs-browse/models" "github.com/lmika/awstools/internal/sqs-browse/models"
"log"
"strings"
) )
var ( var (
activeHeaderStyle = lipgloss.NewStyle(). activeHeaderStyle = lipgloss.NewStyle().
Bold(true). Bold(true).
Foreground(lipgloss.Color("#ffffff")). Foreground(lipgloss.Color("#ffffff")).
Background(lipgloss.Color("#eac610")) Background(lipgloss.Color("#eac610"))
inactiveHeaderStyle = lipgloss.NewStyle(). inactiveHeaderStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#000000")). Foreground(lipgloss.Color("#000000")).
Background(lipgloss.Color("#d1d1d1")) Background(lipgloss.Color("#d1d1d1"))
) )
type uiModel struct { type uiModel struct {
@ -52,12 +53,12 @@ func NewModel(dispatcher *dispatcher.Dispatcher, msgSendingHandlers *controllers
textInput := textinput.New() textInput := textinput.New()
model := uiModel{ model := uiModel{
table: tbl, table: tbl,
tableRows: rows, tableRows: rows,
message: "", message: "",
textInput: textInput, textInput: textInput,
msgSendingHandlers: msgSendingHandlers, msgSendingHandlers: msgSendingHandlers,
dispatcher: dispatcher, dispatcher: dispatcher,
} }
return model return model

View file

@ -2,10 +2,11 @@ package ui
import ( import (
"fmt" "fmt"
"github.com/lmika/awstools/internal/sqs-browse/models"
table "github.com/calyptia/go-bubble-table"
"io" "io"
"strings" "strings"
table "github.com/calyptia/go-bubble-table"
"github.com/lmika/awstools/internal/sqs-browse/models"
) )
type messageTableRow models.Message type messageTableRow models.Message

View file

@ -2,6 +2,8 @@ package main
import ( import (
"context" "context"
"log"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb"
@ -12,7 +14,6 @@ import (
"github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" "github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo"
"github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/internal/dynamo-browse/services/tables"
"github.com/lmika/gopkgs/cli" "github.com/lmika/gopkgs/cli"
"log"
) )
func main() { func main() {
@ -52,12 +53,17 @@ func main() {
log.Fatalf("warn: cannot create table: %v", tableName) log.Fatalf("warn: cannot create table: %v", tableName)
} }
tableInfo := &models.TableInfo{
Name: tableName,
Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"},
}
dynamoProvider := dynamo.NewProvider(dynamoClient) dynamoProvider := dynamo.NewProvider(dynamoClient)
tableService := tables.NewService(dynamoProvider) tableService := tables.NewService(dynamoProvider)
for i := 0; i < totalItems; i++ { for i := 0; i < totalItems; i++ {
key := uuid.New().String() key := uuid.New().String()
if err := tableService.Put(ctx, tableName, models.Item{ if err := tableService.Put(ctx, tableInfo, models.Item{
"pk": &types.AttributeValueMemberS{Value: key}, "pk": &types.AttributeValueMemberS{Value: key},
"sk": &types.AttributeValueMemberS{Value: key}, "sk": &types.AttributeValueMemberS{Value: key},
"name": &types.AttributeValueMemberS{Value: gofakeit.Name()}, "name": &types.AttributeValueMemberS{Value: gofakeit.Name()},

View file

@ -2,6 +2,8 @@ package testdynamo
import ( import (
"context" "context"
"testing"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/credentials"
@ -9,7 +11,6 @@ import (
"github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
type TestData []map[string]interface{} type TestData []map[string]interface{}

View file

@ -1,10 +1,11 @@
package testdynamo package testdynamo
import ( import (
"testing"
"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue" "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
"github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/models"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestRecordAsItem(t *testing.T, item map[string]interface{}) models.Item { func TestRecordAsItem(t *testing.T, item map[string]interface{}) models.Item {

View file

@ -2,6 +2,7 @@ package testuictx
import ( import (
"context" "context"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/lmika/awstools/internal/common/ui/dispatcher" "github.com/lmika/awstools/internal/common/ui/dispatcher"
"github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/common/ui/uimodels"