sqs-browse: remove assumption regarding table keys
Table keys are now retrieved from describe
This commit is contained in:
		
							parent
							
								
									3428bd2a8a
								
							
						
					
					
						commit
						5a69e6c954
					
				|  | @ -4,6 +4,8 @@ import ( | |||
| 	"context" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/config" | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb" | ||||
| 	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/ui" | ||||
| 	"github.com/lmika/gopkgs/cli" | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
|  | @ -49,8 +50,8 @@ func main() { | |||
| 
 | ||||
| 	commandController := commandctrl.NewCommandController(map[string]uimodels.Operation{ | ||||
| 		"scan": tableReadController.Scan(), | ||||
| 		"rw": tableWriteController.ToggleReadWrite(), | ||||
| 		"dup": tableWriteController.Duplicate(), | ||||
| 		"rw":   tableWriteController.ToggleReadWrite(), | ||||
| 		"dup":  tableWriteController.Duplicate(), | ||||
| 	}) | ||||
| 
 | ||||
| 	uiModel := ui.NewModel(uiDispatcher, commandController, tableReadController, tableWriteController) | ||||
|  | @ -77,4 +78,3 @@ type msgLoopback struct { | |||
| func (m *msgLoopback) Send(msg tea.Msg) { | ||||
| 	m.program.Send(msg) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ import ( | |||
| 	"context" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/config" | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/sqs" | ||||
| 	tea "github.com/charmbracelet/bubbletea" | ||||
|  | @ -17,8 +20,6 @@ import ( | |||
| 	"github.com/lmika/awstools/internal/sqs-browse/ui" | ||||
| 	"github.com/lmika/events" | ||||
| 	"github.com/lmika/gopkgs/cli" | ||||
| 	"log" | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
|  | @ -39,7 +40,7 @@ func main() { | |||
| 	if err != nil { | ||||
| 		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()) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -3,15 +3,16 @@ package main | |||
| import ( | ||||
| 	"context" | ||||
| 	"flag" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/aws" | ||||
| 	"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/types" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/lmika/gopkgs/cli" | ||||
| ) | ||||
|  | @ -44,9 +45,9 @@ func main() { | |||
| 	msgCount := 0 | ||||
| 	for { | ||||
| 		out, err := client.ReceiveMessage(ctx, &sqs.ReceiveMessageInput{ | ||||
| 			QueueUrl: aws.String(*flagQueue), | ||||
| 			QueueUrl:            aws.String(*flagQueue), | ||||
| 			MaxNumberOfMessages: 10, | ||||
| 			WaitTimeSeconds: 1, | ||||
| 			WaitTimeSeconds:     1, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("error receiving messages: %v", err) | ||||
|  | @ -59,7 +60,7 @@ func main() { | |||
| 		for _, msg := range out.Messages { | ||||
| 			if err := handleMessage(ctx, outDir, msg); err == nil { | ||||
| 				messagesToDelete = append(messagesToDelete, types.DeleteMessageBatchRequestEntry{ | ||||
| 					Id: msg.MessageId, | ||||
| 					Id:            msg.MessageId, | ||||
| 					ReceiptHandle: msg.ReceiptHandle, | ||||
| 				}) | ||||
| 				msgCount += 1 | ||||
|  | @ -74,7 +75,7 @@ func main() { | |||
| 
 | ||||
| 		if _, err := client.DeleteMessageBatch(ctx, &sqs.DeleteMessageBatchInput{ | ||||
| 			QueueUrl: aws.String(*flagQueue), | ||||
| 			Entries: messagesToDelete, | ||||
| 			Entries:  messagesToDelete, | ||||
| 		}); err != nil { | ||||
| 			log.Printf("error deleting messages from queue: %v", err) | ||||
| 			break | ||||
|  | @ -85,7 +86,7 @@ func main() { | |||
| } | ||||
| 
 | ||||
| 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) | ||||
| 
 | ||||
| 	log.Printf("%v -> %v", aws.ToString(msg.MessageId), outFile) | ||||
|  |  | |||
|  | @ -2,11 +2,12 @@ package commandctrl | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/events" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/lmika/shellwords" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| type CommandController struct { | ||||
|  | @ -45,4 +46,4 @@ func (c *CommandController) Execute() uimodels.Operation { | |||
| 
 | ||||
| 		return command.Execute(WithCommandArgs(ctx, tokens[1:])) | ||||
| 	}) | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,11 +2,12 @@ package commandctrl_test | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/commandctrl" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/events" | ||||
| 	"github.com/lmika/awstools/test/testuictx" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestCommandController_Prompt(t *testing.T) { | ||||
|  |  | |||
|  | @ -2,7 +2,8 @@ package commandctrl | |||
| 
 | ||||
| import "context" | ||||
| 
 | ||||
| type commandArgContextKeyType struct {} | ||||
| type commandArgContextKeyType struct{} | ||||
| 
 | ||||
| var commandArgContextKey = commandArgContextKeyType{} | ||||
| 
 | ||||
| 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 { | ||||
| 	args, _ := ctx.Value(commandArgContextKey).([]string) | ||||
| 	return args | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package dispatcher | |||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	tea "github.com/charmbracelet/bubbletea" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/events" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
|  |  | |||
|  | @ -2,10 +2,11 @@ package dispatcher | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/events" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| type Dispatcher struct { | ||||
|  | @ -14,7 +15,6 @@ type Dispatcher struct { | |||
| 	publisher MessagePublisher | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| func NewDispatcher(publisher MessagePublisher) *Dispatcher { | ||||
| 	return &Dispatcher{ | ||||
| 		mutex:     new(sync.Mutex), | ||||
|  | @ -44,6 +44,3 @@ func (d *Dispatcher) Start(ctx context.Context, operation uimodels.Operation) { | |||
| 		d.runningOp = nil | ||||
| 	}() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,4 +4,4 @@ import tea "github.com/charmbracelet/bubbletea" | |||
| 
 | ||||
| type MessagePublisher interface { | ||||
| 	Send(msg tea.Msg) | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -14,4 +14,4 @@ type Message string | |||
| type PromptForInput struct { | ||||
| 	Prompt string | ||||
| 	OnDone uimodels.Operation | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,8 @@ package uimodels | |||
| 
 | ||||
| import "context" | ||||
| 
 | ||||
| type uiContextKeyType struct {} | ||||
| type uiContextKeyType struct{} | ||||
| 
 | ||||
| var uiContextKey = uiContextKeyType{} | ||||
| 
 | ||||
| func Ctx(ctx context.Context) UIContext { | ||||
|  |  | |||
|  | @ -11,4 +11,3 @@ type OperationFn func(ctx context.Context) error | |||
| func (f OperationFn) Execute(ctx context.Context) error { | ||||
| 	return f(ctx) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,7 +2,8 @@ package uimodels | |||
| 
 | ||||
| import "context" | ||||
| 
 | ||||
| type promptValueKeyType struct {} | ||||
| type promptValueKeyType struct{} | ||||
| 
 | ||||
| var promptValueKey = promptValueKeyType{} | ||||
| 
 | ||||
| func PromptValue(ctx context.Context) string { | ||||
|  |  | |||
|  | @ -8,4 +8,4 @@ type NewResultSet struct { | |||
| 
 | ||||
| type SetReadWrite struct { | ||||
| 	NewValue bool | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package controllers | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package controllers | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/services/tables" | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package controllers | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models/modexpr" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/services/tables" | ||||
|  | @ -9,16 +10,16 @@ import ( | |||
| ) | ||||
| 
 | ||||
| type TableWriteController struct { | ||||
| 	tableService *tables.Service | ||||
| 	tableService         *tables.Service | ||||
| 	tableReadControllers *TableReadController | ||||
| 	tableName string | ||||
| 	tableName            string | ||||
| } | ||||
| 
 | ||||
| func NewTableWriteController(tableService *tables.Service, tableReadControllers *TableReadController, tableName string) *TableWriteController { | ||||
| 	return &TableWriteController{ | ||||
| 		tableService: tableService, | ||||
| 		tableService:         tableService, | ||||
| 		tableReadControllers: tableReadControllers, | ||||
| 		tableName: tableName, | ||||
| 		tableName:            tableName, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ package controllers_test | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/events" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/controllers" | ||||
|  | @ -10,7 +12,6 @@ import ( | |||
| 	"github.com/lmika/awstools/test/testdynamo" | ||||
| 	"github.com/lmika/awstools/test/testuictx" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestTableWriteController_ToggleReadWrite(t *testing.T) { | ||||
|  | @ -47,7 +48,10 @@ func TestTableWriteController_Delete(t *testing.T) { | |||
| 		twc, ctrls, closeFn := setupController(t) | ||||
| 		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.Len(t, resultSet.Items, 3) | ||||
| 
 | ||||
|  | @ -71,7 +75,7 @@ func TestTableWriteController_Delete(t *testing.T) { | |||
| 		err = promptRequest.OnDone.Execute(uimodels.WithPromptValue(ctx, "y")) | ||||
| 		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.Len(t, afterResultSet.Items, 2) | ||||
| 		assert.Contains(t, afterResultSet.Items, resultSet.Items[0]) | ||||
|  | @ -83,7 +87,10 @@ func TestTableWriteController_Delete(t *testing.T) { | |||
| 		twc, ctrls, closeFn := setupController(t) | ||||
| 		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.Len(t, resultSet.Items, 3) | ||||
| 
 | ||||
|  | @ -107,7 +114,7 @@ func TestTableWriteController_Delete(t *testing.T) { | |||
| 		err = promptRequest.OnDone.Execute(uimodels.WithPromptValue(ctx, "n")) | ||||
| 		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.Len(t, afterResultSet.Items, 3) | ||||
| 		assert.Contains(t, afterResultSet.Items, resultSet.Items[0]) | ||||
|  | @ -119,7 +126,10 @@ func TestTableWriteController_Delete(t *testing.T) { | |||
| 		tableWriteController, ctrls, closeFn := setupController(t) | ||||
| 		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.Len(t, resultSet.Items, 3) | ||||
| 
 | ||||
|  | @ -174,4 +184,4 @@ var testData = testdynamo.TestData{ | |||
| 		"beta":  2468, | ||||
| 		"gamma": "foobar", | ||||
| 	}, | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| package models | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| ) | ||||
| 
 | ||||
| func compareScalarAttributes(x, y types.AttributeValue) (int, bool) { | ||||
|  |  | |||
|  | @ -29,4 +29,4 @@ func (i Item) KeyValue(info *TableInfo) map[string]types.AttributeValue { | |||
| 		itemKey[info.Keys.SortKey] = i[info.Keys.SortKey] | ||||
| 	} | ||||
| 	return itemKey | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -32,4 +32,4 @@ func Parse(expr string) (*ModExpr, error) { | |||
| 	} | ||||
| 
 | ||||
| 	return &ModExpr{ast: &ast}, nil | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| package modexpr_test | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"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/modexpr" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestModExpr_Patch(t *testing.T) { | ||||
|  | @ -26,7 +27,7 @@ func TestModExpr_Patch(t *testing.T) { | |||
| 		assert.NoError(t, err) | ||||
| 
 | ||||
| 		oldItem := models.Item{ | ||||
| 			"old": &types.AttributeValueMemberS{Value: "before"}, | ||||
| 			"old":  &types.AttributeValueMemberS{Value: "before"}, | ||||
| 			"beta": &types.AttributeValueMemberS{Value: "before beta"}, | ||||
| 		} | ||||
| 		newItem, err := modExpr.Patch(oldItem) | ||||
|  | @ -42,7 +43,7 @@ func TestModExpr_Patch(t *testing.T) { | |||
| 		assert.NoError(t, err) | ||||
| 
 | ||||
| 		oldItem := models.Item{ | ||||
| 			"old": &types.AttributeValueMemberS{Value: "before"}, | ||||
| 			"old":  &types.AttributeValueMemberS{Value: "before"}, | ||||
| 			"beta": &types.AttributeValueMemberS{Value: "before beta"}, | ||||
| 		} | ||||
| 		newItem, err := modExpr.Patch(oldItem) | ||||
|  |  | |||
|  | @ -10,8 +10,8 @@ type patchMod interface { | |||
| } | ||||
| 
 | ||||
| type setAttributeMod struct { | ||||
| 	key  string | ||||
| 	to   types.AttributeValue | ||||
| 	key string | ||||
| 	to  types.AttributeValue | ||||
| } | ||||
| 
 | ||||
| func (sa setAttributeMod) Apply(item models.Item) { | ||||
|  |  | |||
|  | @ -1,9 +1,10 @@ | |||
| package modexpr | ||||
| 
 | ||||
| import ( | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| func (a *astLiteralValue) dynamoValue() (types.AttributeValue, error) { | ||||
|  |  | |||
|  | @ -1,18 +1,21 @@ | |||
| package models_test | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestSort(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)) | ||||
| 		copy(items, testStringData) | ||||
| 
 | ||||
| 		models.Sort(items, "pk", "sk") | ||||
| 		models.Sort(items, tableInfo) | ||||
| 
 | ||||
| 		assert.Equal(t, items[0], testStringData[1]) | ||||
| 		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) { | ||||
| 		tableInfo := &models.TableInfo{Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"}} | ||||
| 
 | ||||
| 		items := make([]models.Item, len(testNumberData)) | ||||
| 		copy(items, testNumberData) | ||||
| 
 | ||||
| 		models.Sort(items, "pk", "sk") | ||||
| 		models.Sort(items, tableInfo) | ||||
| 
 | ||||
| 		assert.Equal(t, items[0], testNumberData[2]) | ||||
| 		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) { | ||||
| 		tableInfo := &models.TableInfo{Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"}} | ||||
| 
 | ||||
| 		items := make([]models.Item, len(testBoolData)) | ||||
| 		copy(items, testBoolData) | ||||
| 
 | ||||
| 		models.Sort(items, "pk", "sk") | ||||
| 		models.Sort(items, tableInfo) | ||||
| 
 | ||||
| 		assert.Equal(t, items[0], testBoolData[2]) | ||||
| 		assert.Equal(t, items[1], testBoolData[1]) | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package dynamo | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"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/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 { | ||||
| 	_, err := p.client.PutItem(ctx, &dynamodb.PutItemInput{ | ||||
| 		TableName: aws.String(name), | ||||
| 		Item: item, | ||||
| 		Item:      item, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		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 { | ||||
| 	_, err := p.client.DeleteItem(ctx, &dynamodb.DeleteItemInput{ | ||||
| 		TableName: aws.String(tableName), | ||||
| 		Key: key, | ||||
| 		Key:       key, | ||||
| 	}) | ||||
| 	return errors.Wrap(err, "could not delete item") | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,11 +2,12 @@ package dynamo_test | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" | ||||
| 	"github.com/lmika/awstools/test/testdynamo" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestProvider_ScanItems(t *testing.T) { | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package tables | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| ) | ||||
|  |  | |||
|  | @ -2,9 +2,10 @@ package tables | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sort" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"sort" | ||||
| ) | ||||
| 
 | ||||
| type Service struct { | ||||
|  | @ -63,9 +64,9 @@ func (s *Service) Scan(ctx context.Context, tableInfo *models.TableInfo) (*model | |||
| 	models.Sort(results, tableInfo) | ||||
| 
 | ||||
| 	return &models.ResultSet{ | ||||
| 		TableInfo:   tableInfo, | ||||
| 		Columns: columns, | ||||
| 		Items:   results, | ||||
| 		TableInfo: tableInfo, | ||||
| 		Columns:   columns, | ||||
| 		Items:     results, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,11 +2,12 @@ package tables_test | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/services/tables" | ||||
| 	"github.com/lmika/awstools/test/testdynamo" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestService_Describe(t *testing.T) { | ||||
|  |  | |||
|  | @ -3,6 +3,9 @@ package ui | |||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"text/tabwriter" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	table "github.com/calyptia/go-bubble-table" | ||||
| 	"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/uimodels" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/controllers" | ||||
| 	"strings" | ||||
| 	"text/tabwriter" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -156,7 +157,7 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |||
| 	// Tea events
 | ||||
| 	case tea.WindowSizeMsg: | ||||
| 		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 { | ||||
| 			viewportHeight = 15 | ||||
| 		} | ||||
|  |  | |||
|  | @ -2,11 +2,12 @@ package ui | |||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	table "github.com/calyptia/go-bubble-table" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| 	"io" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| type itemTableRow struct { | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package controllers | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/services/messages" | ||||
|  |  | |||
|  | @ -3,9 +3,9 @@ package models | |||
| import "time" | ||||
| 
 | ||||
| type Message struct { | ||||
| 	ID       uint64		`storm:"id,increment"` | ||||
| 	ExtID    string		`storm:"unique"` | ||||
| 	Queue    string		`storm:"index"` | ||||
| 	ID       uint64 `storm:"id,increment"` | ||||
| 	ExtID    string `storm:"unique"` | ||||
| 	Queue    string `storm:"index"` | ||||
| 	Received time.Time | ||||
| 	Data     string | ||||
| } | ||||
|  |  | |||
|  | @ -2,13 +2,14 @@ package sqs | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"log" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"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/types" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"log" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type Provider struct { | ||||
|  | @ -23,7 +24,7 @@ func (p *Provider) SendMessage(ctx context.Context, msg models.Message, queue st | |||
| 	// TEMP :: queue URL
 | ||||
| 
 | ||||
| 	out, err := p.client.SendMessage(ctx, &sqs.SendMessageInput{ | ||||
| 		QueueUrl: aws.String(queue), | ||||
| 		QueueUrl:    aws.String(queue), | ||||
| 		MessageBody: aws.String(msg.Data), | ||||
| 	}) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package stormstore | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/asdine/storm" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 	"github.com/pkg/errors" | ||||
|  |  | |||
|  | @ -2,9 +2,10 @@ package messages | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| ) | ||||
| 
 | ||||
| type MessageSender interface { | ||||
| 	SendMessage(ctx context.Context, msg models.Message, queue string) (string, error) | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package messages | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package pollmessage | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| ) | ||||
| 
 | ||||
|  | @ -11,4 +12,4 @@ type MessageStore interface { | |||
| 
 | ||||
| type MessagePoller interface { | ||||
| 	PollForNewMessages(ctx context.Context, queue string) ([]*models.Message, error) | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,9 +2,10 @@ package pollmessage | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"log" | ||||
| 
 | ||||
| 	"github.com/lmika/events" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"log" | ||||
| ) | ||||
| 
 | ||||
| type Service struct { | ||||
|  |  | |||
|  | @ -2,4 +2,4 @@ package ui | |||
| 
 | ||||
| import "github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 
 | ||||
| type NewMessagesEvent []*models.Message | ||||
| type NewMessagesEvent []*models.Message | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ import ( | |||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"log" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	table "github.com/calyptia/go-bubble-table" | ||||
| 	"github.com/charmbracelet/bubbles/textinput" | ||||
| 	"github.com/charmbracelet/bubbles/viewport" | ||||
|  | @ -14,19 +17,17 @@ import ( | |||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/controllers" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 	"log" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	activeHeaderStyle = lipgloss.NewStyle(). | ||||
| 		Bold(true). | ||||
| 		Foreground(lipgloss.Color("#ffffff")). | ||||
| 		Background(lipgloss.Color("#eac610")) | ||||
| 				Bold(true). | ||||
| 				Foreground(lipgloss.Color("#ffffff")). | ||||
| 				Background(lipgloss.Color("#eac610")) | ||||
| 
 | ||||
| 	inactiveHeaderStyle = lipgloss.NewStyle(). | ||||
| 		Foreground(lipgloss.Color("#000000")). | ||||
| 		Background(lipgloss.Color("#d1d1d1")) | ||||
| 				Foreground(lipgloss.Color("#000000")). | ||||
| 				Background(lipgloss.Color("#d1d1d1")) | ||||
| ) | ||||
| 
 | ||||
| type uiModel struct { | ||||
|  | @ -52,12 +53,12 @@ func NewModel(dispatcher *dispatcher.Dispatcher, msgSendingHandlers *controllers | |||
| 	textInput := textinput.New() | ||||
| 
 | ||||
| 	model := uiModel{ | ||||
| 		table:      tbl, | ||||
| 		tableRows:  rows, | ||||
| 		message:    "", | ||||
| 		textInput:  textInput, | ||||
| 		table:              tbl, | ||||
| 		tableRows:          rows, | ||||
| 		message:            "", | ||||
| 		textInput:          textInput, | ||||
| 		msgSendingHandlers: msgSendingHandlers, | ||||
| 		dispatcher: dispatcher, | ||||
| 		dispatcher:         dispatcher, | ||||
| 	} | ||||
| 
 | ||||
| 	return model | ||||
|  |  | |||
|  | @ -2,10 +2,11 @@ package ui | |||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| 	table "github.com/calyptia/go-bubble-table" | ||||
| 	"io" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	table "github.com/calyptia/go-bubble-table" | ||||
| 	"github.com/lmika/awstools/internal/sqs-browse/models" | ||||
| ) | ||||
| 
 | ||||
| type messageTableRow models.Message | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ package main | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"log" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/aws" | ||||
| 	"github.com/aws/aws-sdk-go-v2/config" | ||||
| 	"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/services/tables" | ||||
| 	"github.com/lmika/gopkgs/cli" | ||||
| 	"log" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
|  | @ -52,12 +53,17 @@ func main() { | |||
| 		log.Fatalf("warn: cannot create table: %v", tableName) | ||||
| 	} | ||||
| 
 | ||||
| 	tableInfo := &models.TableInfo{ | ||||
| 		Name: tableName, | ||||
| 		Keys: models.KeyAttribute{PartitionKey: "pk", SortKey: "sk"}, | ||||
| 	} | ||||
| 
 | ||||
| 	dynamoProvider := dynamo.NewProvider(dynamoClient) | ||||
| 	tableService := tables.NewService(dynamoProvider) | ||||
| 
 | ||||
| 	for i := 0; i < totalItems; i++ { | ||||
| 		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}, | ||||
| 			"sk":      &types.AttributeValueMemberS{Value: key}, | ||||
| 			"name":    &types.AttributeValueMemberS{Value: gofakeit.Name()}, | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ package testdynamo | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/aws" | ||||
| 	"github.com/aws/aws-sdk-go-v2/config" | ||||
| 	"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/types" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| type TestData []map[string]interface{} | ||||
|  |  | |||
|  | @ -1,10 +1,11 @@ | |||
| package testdynamo | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue" | ||||
| 	"github.com/lmika/awstools/internal/dynamo-browse/models" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestRecordAsItem(t *testing.T, item map[string]interface{}) models.Item { | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package testuictx | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	tea "github.com/charmbracelet/bubbletea" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/dispatcher" | ||||
| 	"github.com/lmika/awstools/internal/common/ui/uimodels" | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue