Skip to content

Commit

Permalink
test: confirm tokens are stored after configuration setup is complete (
Browse files Browse the repository at this point in the history
  • Loading branch information
zimeg authored Sep 5, 2024
1 parent eae5463 commit e4a8599
Show file tree
Hide file tree
Showing 29 changed files with 933 additions and 623 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Built binaries
etime
/etime
dist/*

# Development leftovers
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ to [Semantic Versioning][semver].
- Set the `go` version to a fixed `1.22.6` for the toolchain
- Update token authentication to use the latest Cognito SDK
- Test coverage as a metric to at least consider with changes
- Separate token exchanges into a cognito package for testing

## [1.1.0] - 2024-08-03

Expand Down
51 changes: 0 additions & 51 deletions cmd/etime.go

This file was deleted.

45 changes: 45 additions & 0 deletions cmd/etime/etime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package etime

import (
"fmt"
"os/exec"

"github.com/zimeg/emporia-time/pkg/config"
"github.com/zimeg/emporia-time/pkg/energy"
"github.com/zimeg/emporia-time/pkg/times"
)

// CommandResult holds information from the run command
type CommandResult struct {
energy.EnergyResult
times.TimeMeasurement
ExitCode int
}

// Run executes the command and returns the usage statistics
func Run(cmd []string, cfg config.Configure) (results CommandResult, err error) {
available, err := cfg.API().Status()
if err != nil {
return CommandResult{}, err
} else if !available {
return CommandResult{}, fmt.Errorf("Error: Cannot measure energy during Emporia maintenance")
}
measurements, err := times.TimeExec(cmd)
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
results.ExitCode = exitError.ExitCode()
} else {
return CommandResult{}, err
}
results.TimeMeasurement = measurements
} else {
results.TimeMeasurement = measurements
}
usage, err := cfg.API().GetChartUsage(results.TimeMeasurement)
if err != nil {
return results, err
} else {
results.EnergyResult = usage
}
return results, nil
}
53 changes: 53 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cmd

import (
"context"
"fmt"
"os"

"github.com/spf13/afero"
"github.com/zimeg/emporia-time/cmd/etime"
"github.com/zimeg/emporia-time/internal/display/templates"
"github.com/zimeg/emporia-time/pkg/api"
"github.com/zimeg/emporia-time/pkg/cognito"
"github.com/zimeg/emporia-time/pkg/config"
)

// Root facilitates the setup and execution of the command
func Root(
ctx context.Context,
cog cognito.Cognitoir,
fs afero.Fs,
req api.Emporiac,
args []string,
version string,
) (
etime.CommandResult,
error,
) {
cmd, flags, err := config.ParseFlags(args)
if err != nil {
return etime.CommandResult{}, err
} else if flags.Version {
fmt.Printf("%s\n", version)
return etime.CommandResult{}, nil
} else if flags.Help {
templates.PrintHelpMessage()
return etime.CommandResult{}, nil
}
cfg, err := config.Load(ctx, cog, fs, req, flags)
if err != nil {
return etime.CommandResult{}, err
}
results, err := etime.Run(cmd, &cfg)
if err != nil {
return etime.CommandResult{}, err
}
stats, err := templates.FormatUsage(results, flags.Portable)
if err != nil {
return results, err
} else {
fmt.Fprintf(os.Stderr, "%s\n", stats)
}
return results, nil
}
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/aws/aws-sdk-go-v2/config v1.27.31
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.43.3
github.com/spf13/afero v1.11.0
github.com/stretchr/testify v1.9.0
)

Expand All @@ -28,8 +29,9 @@ require (
github.com/mattn/go-isatty v0.0.8 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.5.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 8 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
Expand All @@ -66,8 +70,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
Expand All @@ -76,8 +80,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
Expand Down
39 changes: 16 additions & 23 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
package main

import (
"fmt"
"context"
"log"
"os"

etime "github.com/zimeg/emporia-time/cmd"
"github.com/zimeg/emporia-time/internal/display/templates"
"github.com/zimeg/emporia-time/pkg/emporia"
"github.com/spf13/afero"
"github.com/zimeg/emporia-time/cmd"
"github.com/zimeg/emporia-time/pkg/api"
"github.com/zimeg/emporia-time/pkg/cognito"
)

// version is the title of this current build
var version = "development"

const (
clientID string = "4qte47jbstod8apnfic0bunmrq" // Emporia AWS Cognito client ID
region string = "us-east-2" // Emporia AWS region
)

// main manages the lifecycle of this program
func main() {
command, client, err := etime.Setup(os.Args)
ctx := context.Background()
fs := afero.NewOsFs()
req := api.New()
cog, err := cognito.NewClient(ctx, clientID, region)
if err != nil {
log.Fatalf("Error: %s", err)
} else if command.Flags.Version {
fmt.Printf("%s\n", version)
os.Exit(0)
} else if command.Flags.Help {
templates.PrintHelpMessage()
os.Exit(0)
}
if available, err := emporia.EmporiaStatus(); err != nil {
log.Fatalf("Error: %s", err)
} else if !available {
log.Fatalf("Error: Cannot measure energy during Emporia maintenance\n")
}
results, err := etime.Run(command, client)
result, err := cmd.Root(ctx, cog, fs, req, os.Args, version)
if err != nil {
log.Fatalf("Error: %s", err)
}
if stats, err := templates.FormatUsage(results, command.Flags.Portable); err != nil {
log.Fatalf("Error: %s", err)
} else {
fmt.Fprintf(os.Stderr, "%s\n", stats)
}
os.Exit(results.ExitCode)
os.Exit(result.ExitCode)
}
71 changes: 71 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package api

import (
"encoding/json"
"io"
"net/http"

"github.com/zimeg/emporia-time/pkg/energy"
"github.com/zimeg/emporia-time/pkg/times"
)

// Emporiac communicates with the Emporia API
type Emporiac interface {
GetChartUsage(times times.TimeMeasurement) (results energy.EnergyResult, err error)
GetCustomerDevices() (devices []Device, err error)
Status() (available bool, err error)

SetDevice(deviceID string)
SetToken(token string)
}

// Emporia holds information for and from the Emporia API
type Emporia struct {
client interface {
// Do does the HTTP request and is often implmented using net/http
Do(req *http.Request) (*http.Response, error)
}
deviceID string
token string
}

// RequestURL is the base URL of the API
const RequestURL string = "https://api.emporiaenergy.com"

// New creates a new client to interact with Emporia HTTP APIs
func New() *Emporia {
return &Emporia{
client: &http.Client{},
}
}

// SetToken sets the token for the client
func (emp *Emporia) SetToken(token string) {
emp.token = token
}

// SetDevice sets the device ID for the client
func (emp *Emporia) SetDevice(deviceID string) {
emp.deviceID = deviceID
}

// get makes an authenticated GET request to URL and saves the response to data
func (emp *Emporia) get(url string, data any) error {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
if emp.token != "" {
req.Header.Add("authToken", emp.token)
}
resp, err := emp.client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
return json.Unmarshal(body, &data)
}
17 changes: 17 additions & 0 deletions pkg/api/api_mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package api

import (
"github.com/stretchr/testify/mock"
)

type EmporiaMock struct {
mock.Mock
}

func (em *EmporiaMock) SetDevice(deviceID string) {
em.Called(deviceID)
}

func (em *EmporiaMock) SetToken(token string) {
em.Called(token)
}
Loading

0 comments on commit e4a8599

Please sign in to comment.