Skip to content

Commit 9f8a7ec

Browse files
committed
Logger interface to control stdio printing depending on which format
okta-aws-cli is outputting to. Closes #247
1 parent 9fac884 commit 9f8a7ec

File tree

11 files changed

+174
-74
lines changed

11 files changed

+174
-74
lines changed

cmd/root/debug/debug.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
package debug
1818

1919
import (
20-
"fmt"
21-
"os"
22-
2320
"github.com/spf13/cobra"
2421

2522
"github.com/okta/okta-aws-cli/internal/config"
@@ -37,7 +34,7 @@ func NewDebugCommand() *cobra.Command {
3734
}
3835
err = config.RunConfigChecks()
3936
// NOTE: still print out the done message, even if there was an error it will get printed as well
40-
fmt.Fprintf(os.Stderr, "debugging okta-aws-cli config $HOME/.okta/okta.yaml is complete\n")
37+
config.Logger.Warn("debugging okta-aws-cli config $HOME/.okta/okta.yaml is complete\n")
4138
if err != nil {
4239
return err
4340
}

cmd/root/profileslist/profiles-list.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
package profileslist
1818

1919
import (
20-
"fmt"
21-
2220
"github.com/spf13/cobra"
2321

2422
"github.com/okta/okta-aws-cli/internal/config"
@@ -35,15 +33,15 @@ func NewProfilesListCommand() *cobra.Command {
3533
return err
3634
}
3735

38-
fmt.Println("Profiles:")
36+
config.Logger.Info("Profiles:\n")
3937

4038
keys, err := config.ReadConfigProfileKeys()
4139
if err != nil {
4240
return err
4341
}
4442

4543
for _, key := range keys {
46-
fmt.Printf(" %s\n", key)
44+
config.Logger.Info(" %s\n", key)
4745
}
4846

4947
return nil

internal/config/config.go

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import (
2929

3030
"github.com/spf13/viper"
3131
"gopkg.in/yaml.v2"
32+
33+
"github.com/okta/okta-aws-cli/internal/logger"
3234
)
3335

3436
// longUserAgent the long user agent value
@@ -281,6 +283,7 @@ type Config struct {
281283
shortUserAgent bool
282284
writeAWSCredentials bool
283285
clock Clock
286+
Logger logger.Logger
284287
}
285288

286289
// ConfigAttributes attributes for config construction
@@ -324,7 +327,18 @@ func NewEvaluatedConfig() (*Config, error) {
324327
if err != nil {
325328
return nil, err
326329
}
327-
return NewConfig(&cfgAttrs)
330+
var config *Config
331+
if config, err = NewConfig(&cfgAttrs); err != nil {
332+
return nil, err
333+
}
334+
switch cfgAttrs.Format {
335+
case ProcessCredentialsFormat:
336+
config.Logger = &logger.TerseLogger{}
337+
default:
338+
config.Logger = &logger.FullLogger{}
339+
}
340+
341+
return config, nil
328342
}
329343

330344
// NewConfig create config from attributes
@@ -994,137 +1008,137 @@ awscli:
9941008
"arn:aws:iam::012345678901:role/admin": "Dev Admin"
9951009
"arn:aws:iam::012345678901:role/operator": "Dev Ops"
9961010
`
997-
fmt.Fprintf(os.Stderr, "Given this YAML as an example template of okta.yaml for reference:\n%s\n", exampleYaml)
1011+
c.Logger.Warn("Given this YAML as an example template of okta.yaml for reference:\n%s\n", exampleYaml)
9981012

9991013
homeDir, err := os.UserHomeDir()
10001014
if err != nil {
1001-
fmt.Fprintf(os.Stderr, "WARNING: can't find user home directory $HOME\n")
1002-
fmt.Fprintf(os.Stderr, " see https://pkg.go.dev/os#UserHomeDir\n")
1015+
c.Logger.Warn("WARNING: can't find user home directory $HOME\n")
1016+
c.Logger.Warn(" see https://pkg.go.dev/os#UserHomeDir\n")
10031017
return
10041018
}
1005-
fmt.Fprintf(os.Stderr, "found home directory %q\n", homeDir)
1019+
c.Logger.Warn("found home directory %q\n", homeDir)
10061020

10071021
configPath := filepath.Join(homeDir, DotOkta, OktaYaml)
10081022
yamlConfig, err := os.ReadFile(configPath)
10091023
if err != nil {
1010-
fmt.Fprintf(os.Stderr, "WARNING: can't read okta config %q\n", configPath)
1024+
c.Logger.Warn("WARNING: can't read okta config %q\n", configPath)
10111025
return
10121026
}
1013-
fmt.Fprintf(os.Stderr, "okta.yaml is readable %q\n", configPath)
1027+
c.Logger.Warn("okta.yaml is readable %q\n", configPath)
10141028

10151029
conf := map[string]any{}
10161030
err = yaml.Unmarshal(yamlConfig, &conf)
10171031
if err != nil {
1018-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml is invalid yaml format\n")
1032+
c.Logger.Warn("WARNING: okta.yaml is invalid yaml format\n")
10191033
return
10201034
}
1021-
fmt.Fprintf(os.Stderr, "okta.yaml is valid yaml\n")
1035+
c.Logger.Warn("okta.yaml is valid yaml\n")
10221036

10231037
awscli, ok := conf["awscli"]
10241038
if !ok {
1025-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml missing \"awscli\" section\n")
1039+
c.Logger.Warn("WARNING: okta.yaml missing \"awscli\" section\n")
10261040
return
10271041
}
1028-
fmt.Fprintf(os.Stderr, "okta.yaml has root \"awscli\" section\n")
1042+
c.Logger.Warn("okta.yaml has root \"awscli\" section\n")
10291043

10301044
if awscli == nil {
1031-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli\" section has no values\n")
1045+
c.Logger.Warn("WARNING: okta.yaml \"awscli\" section has no values\n")
10321046
return
10331047
}
10341048
_awscli, ok := awscli.(map[any]any)
10351049
if !ok {
1036-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli\" is not a map of values\n")
1050+
c.Logger.Warn("WARNING: okta.yaml \"awscli\" is not a map of values\n")
10371051
}
10381052
idps, ok := _awscli["idps"]
10391053
if !ok {
1040-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml missing \"awscli.idps\" section\n")
1054+
c.Logger.Warn("WARNING: okta.yaml missing \"awscli.idps\" section\n")
10411055
return
10421056
}
10431057
if idps == nil {
1044-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.idps\" section has no values\n")
1058+
c.Logger.Warn("WARNING: okta.yaml \"awscli.idps\" section has no values\n")
10451059
return
10461060
}
10471061

10481062
// map[interface {}]interface {}
10491063
_idps, ok := idps.(map[any]any)
10501064
if !ok {
1051-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.idps\" section is not a map of ARN string key to friendly string label values\n")
1065+
c.Logger.Warn("WARNING: okta.yaml \"awscli.idps\" section is not a map of ARN string key to friendly string label values\n")
10521066
return
10531067
}
10541068
if len(_idps) == 0 {
1055-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.idps\" section is an empty map of ARN string key to friendly string label values\n")
1069+
c.Logger.Warn("WARNING: okta.yaml \"awscli.idps\" section is an empty map of ARN string key to friendly string label values\n")
10561070
return
10571071
}
10581072

10591073
for k, v := range _idps {
10601074
if _, ok := k.(string); !ok {
1061-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.idps\" value of ARN key \"%v\" is not a string\n", k)
1075+
c.Logger.Warn("okta.yaml \"awscli.idps\" value of ARN key \"%v\" is not a string\n", k)
10621076
return
10631077
}
10641078
if _, ok := v.(string); !ok {
1065-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.idps\" ARN key %q's friendly label value \"%v\" is not a string\n", k, v)
1079+
c.Logger.Warn("okta.yaml \"awscli.idps\" ARN key %q's friendly label value \"%v\" is not a string\n", k, v)
10661080
return
10671081
}
10681082
}
10691083

1070-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.idps\" section is a map of %d ARN string keys to friendly string label values\n", len(_idps))
1084+
c.Logger.Warn("okta.yaml \"awscli.idps\" section is a map of %d ARN string keys to friendly string label values\n", len(_idps))
10711085

10721086
roles, ok := _awscli["roles"]
10731087
if !ok {
1074-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml missing \"awscli.roles\" section\n")
1088+
c.Logger.Warn("WARNING: okta.yaml missing \"awscli.roles\" section\n")
10751089
return
10761090
}
10771091
if roles == nil {
1078-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.roles\" section has no values\n")
1092+
c.Logger.Warn("WARNING: okta.yaml \"awscli.roles\" section has no values\n")
10791093
return
10801094
}
10811095

10821096
_roles, ok := roles.(map[any]any)
10831097
if !ok {
1084-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.roles\" section is not a map of ARN string key to friendly string label values\n")
1098+
c.Logger.Warn("WARNING: okta.yaml \"awscli.roles\" section is not a map of ARN string key to friendly string label values\n")
10851099
return
10861100
}
10871101
if len(_roles) == 0 {
1088-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.roles\" section is an empty map of ARN string key to friendly string label values\n")
1102+
c.Logger.Warn("WARNING: okta.yaml \"awscli.roles\" section is an empty map of ARN string key to friendly string label values\n")
10891103
return
10901104
}
10911105

10921106
for k, v := range _roles {
10931107
if _, ok := k.(string); !ok {
1094-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.roles\" value of ARN key \"%v\" is not a string\n", k)
1108+
c.Logger.Warn("okta.yaml \"awscli.roles\" value of ARN key \"%v\" is not a string\n", k)
10951109
return
10961110
}
10971111
if _, ok := v.(string); !ok {
1098-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.roles\" ARN key %q's friendly label value \"%v\" is not a string\n", k, v)
1112+
c.Logger.Warn("okta.yaml \"awscli.roles\" ARN key %q's friendly label value \"%v\" is not a string\n", k, v)
10991113
return
11001114
}
11011115
}
11021116

1103-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.roles\" section is a map of %d ARN string keys to friendly string label values\n", len(_roles))
1117+
c.Logger.Warn("okta.yaml \"awscli.roles\" section is a map of %d ARN string keys to friendly string label values\n", len(_roles))
11041118

11051119
profiles, ok := _awscli["profiles"]
11061120
if !ok {
1107-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml missing \"awscli.profiles\" section\n")
1121+
c.Logger.Warn("WARNING: okta.yaml missing \"awscli.profiles\" section\n")
11081122
return
11091123
}
11101124
if profiles == nil {
1111-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.profiles\" section has no values\n")
1125+
c.Logger.Warn("WARNING: okta.yaml \"awscli.profiles\" section has no values\n")
11121126
return
11131127
}
11141128

11151129
_profiles, ok := profiles.(map[any]any)
11161130
if !ok {
1117-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.profiles\" section is not a map of separate config settings keyed by profile name\n")
1131+
c.Logger.Warn("WARNING: okta.yaml \"awscli.profiles\" section is not a map of separate config settings keyed by profile name\n")
11181132
return
11191133
}
11201134
if len(_profiles) == 0 {
1121-
fmt.Fprintf(os.Stderr, "WARNING: okta.yaml \"awscli.profiles\" section is an empty map of separate config settings keyed by profile name\n")
1135+
c.Logger.Warn("WARNING: okta.yaml \"awscli.profiles\" section is an empty map of separate config settings keyed by profile name\n")
11221136
return
11231137
}
11241138

1125-
fmt.Fprintf(os.Stderr, "okta.yaml \"awscli.profiles\" section is a map of %d separate config settings keyed by profile name\n", len(_profiles))
1139+
c.Logger.Warn("okta.yaml \"awscli.profiles\" section is a map of %d separate config settings keyed by profile name\n", len(_profiles))
11261140

1127-
fmt.Fprintf(os.Stderr, "okta.yaml is OK\n")
1141+
c.Logger.Warn("okta.yaml is OK\n")
11281142
return nil
11291143
}
11301144

internal/exec/exec.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@ import (
2323
"strings"
2424

2525
oaws "github.com/okta/okta-aws-cli/internal/aws"
26+
"github.com/okta/okta-aws-cli/internal/config"
2627
"github.com/okta/okta-aws-cli/internal/utils"
2728
)
2829

2930
// Exec is a executor / a process runner
3031
type Exec struct {
31-
name string
32-
args []string
32+
name string
33+
args []string
34+
config *config.Config
3335
}
3436

3537
// NewExec Create a new executor
36-
func NewExec() (*Exec, error) {
38+
func NewExec(c *config.Config) (*Exec, error) {
3739
args := []string{}
3840
foundArgs := false
3941
for _, arg := range os.Args {
@@ -55,8 +57,9 @@ func NewExec() (*Exec, error) {
5557
name := args[0]
5658
args = args[1:]
5759
ex := &Exec{
58-
name: name,
59-
args: args,
60+
name: name,
61+
args: args,
62+
config: c,
6063
}
6164

6265
return ex, nil
@@ -85,14 +88,14 @@ func (e *Exec) Run(cc *oaws.CredentialContainer) error {
8588

8689
out, err := cmd.Output()
8790
if ee, ok := err.(*osexec.ExitError); ok {
88-
fmt.Fprintf(os.Stderr, "error running process\n")
89-
fmt.Fprintf(os.Stderr, "%s %s\n", e.name, strings.Join(e.args, " "))
90-
fmt.Fprintf(os.Stderr, utils.PassThroughStringNewLineFMT, ee.Stderr)
91+
e.config.Logger.Warn("error running process\n")
92+
e.config.Logger.Warn("%s %s\n", e.name, strings.Join(e.args, " "))
93+
e.config.Logger.Warn(utils.PassThroughStringNewLineFMT, ee.Stderr)
9194
}
9295
if err != nil {
9396
return err
9497
}
9598

96-
fmt.Printf("%s", string(out))
99+
e.config.Logger.Info("%s", string(out))
97100
return nil
98101
}

internal/logger/full.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2025-Present, Okta, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package logger
18+
19+
import (
20+
"fmt"
21+
"os"
22+
)
23+
24+
// FullLogger logger for stderr (warn) and stdout (info) logging
25+
type FullLogger struct {
26+
}
27+
28+
func (l *FullLogger) Info(format string, a ...any) (int, error) {
29+
return fmt.Fprintf(os.Stdout, format, a...)
30+
}
31+
32+
func (l *FullLogger) Warn(format string, a ...any) (int, error) {
33+
return fmt.Fprintf(os.Stderr, format, a...)
34+
}

internal/logger/logger.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2025-Present, Okta, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package logger
18+
19+
// Logger Interface used for logging ouput
20+
type Logger interface {
21+
Info(format string, a ...any) (int, error)
22+
Warn(format string, a ...any) (int, error)
23+
}

0 commit comments

Comments
 (0)