Skip to content

Commit

Permalink
Update Traefik configuration with comments and remove redirection
Browse files Browse the repository at this point in the history
- Update grpc-go for use of `NewClient` instead of `Dial`.
- Linter updates and style fixes.
- Sync `vendor/` for updated dependencies.
- All test variations pass.
  • Loading branch information
bconway committed May 29, 2024
1 parent c0874a7 commit e520e25
Show file tree
Hide file tree
Showing 99 changed files with 1,540 additions and 1,029 deletions.
4 changes: 2 additions & 2 deletions build/deploy/hermes-deps/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ services:
traefik:
image: traefik:v2.11
ports:
# Comment 80 when enabling 443
- "80:80"
# - "443:443"
- "50051:50051"
environment:
- TRAEFIK_LOG_LEVEL=INFO
- TRAEFIK_PROVIDERS_DOCKER=true
- TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT=false
# Comment PLAINTEXT when enabling TLS, do not redirect
- TRAEFIK_ENTRYPOINTS_PLAINTEXT_ADDRESS=:80
# - TRAEFIK_ENTRYPOINTS_TLS_ADDRESS=:443
- TRAEFIK_ENTRYPOINTS_GRPC_ADDRESS=:50051
# - TRAEFIK_CERTIFICATESRESOLVERS_HERMES-TLS_ACME_TLSCHALLENGE=true
# - TRAEFIK_CERTIFICATESRESOLVERS_HERMES-TLS_ACME_EMAIL=letsencrypt@ownmfa.com
# - TRAEFIK_CERTIFICATESRESOLVERS_HERMES-TLS_ACME_STORAGE=/tls/acme.json
# - TRAEFIK_ENTRYPOINTS_PLAINTEXT_HTTP_REDIRECTIONS_ENTRYPOINT_TO=tls
# - TRAEFIK_ENTRYPOINTS_PLAINTEXT_HTTP_REDIRECTIONS_ENTRYPOINT_SCHEME=https
# - TRAEFIK_PROVIDERS_FILE_FILENAME=/tls/options.yaml
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Expand Down
4 changes: 2 additions & 2 deletions build/deploy/hermes/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
hermes-api:
image: ghcr.io/ownmfa/hermes:df826d5d
image: ghcr.io/ownmfa/hermes:86c7af6f
command: hermes-api
restart: on-failure
depends_on:
Expand Down Expand Up @@ -35,7 +35,7 @@ services:
- "traefik.http.services.hermes-grpc.loadbalancer.server.scheme=h2c"

hermes-notifier:
image: ghcr.io/ownmfa/hermes:df826d5d
image: ghcr.io/ownmfa/hermes:86c7af6f
command: hermes-notifier
restart: on-failure
environment:
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require (
github.com/NYTimes/gziphandler v1.1.1
github.com/google/uuid v1.6.0
github.com/gregdel/pushover v1.3.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1
github.com/jackc/pgx/v5 v5.5.5
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
github.com/jackc/pgx/v5 v5.6.0
github.com/jellydator/ttlcache/v3 v3.2.0
github.com/mennanov/fmutils v0.3.0
github.com/nsqio/go-nsq v1.1.0
Expand All @@ -18,7 +18,7 @@ require (
github.com/stretchr/testify v1.9.0
go.uber.org/mock v0.4.0
golang.org/x/crypto v0.23.0
google.golang.org/grpc v1.63.2
google.golang.org/grpc v1.64.0
google.golang.org/protobuf v1.34.1
)

Expand All @@ -37,7 +37,7 @@ require (
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
23 changes: 11 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,8 @@ github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+
github.com/gregdel/pushover v1.3.1 h1:4bMLITOZ15+Zpi6qqoGqOPuVHCwSUvMCgVnN5Xhilfo=
github.com/gregdel/pushover v1.3.1/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand All @@ -530,8 +530,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE=
Expand Down Expand Up @@ -1042,13 +1042,12 @@ google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZV
google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs=
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae h1:AH34z6WAGVNkllnKs5raNq3yRq93VnjBG6rpfub/jYk=
google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae h1:c55+MER4zkBS14uJhSZMGGmya0yJx5iHV4x/fpOSNRk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
Expand Down Expand Up @@ -1085,8 +1084,8 @@ google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
Expand Down
15 changes: 6 additions & 9 deletions internal/hermes-api/test/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,25 @@ func authGRPCConn(role api.Role, plan api.Plan) (
return "", nil, err
}

if err = globalUserDAO.UpdatePassword(ctx, createUser.GetId(), createOrg.GetId(),
globalHash); err != nil {
if err = globalUserDAO.UpdatePassword(ctx, createUser.GetId(),
createOrg.GetId(), globalHash); err != nil {
return "", nil, err
}

sessCli := api.NewSessionServiceClient(globalNoAuthGRPCConn)
login, err := sessCli.Login(ctx, &api.LoginRequest{
Email: createUser.GetEmail(), OrgName: createOrg.GetName(), Password: globalPass,
Email: createUser.GetEmail(), OrgName: createOrg.GetName(),
Password: globalPass,
})
if err != nil {
return "", nil, err
}

opts := []grpc.DialOption{
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithPerRPCCredentials(&credential{token: login.GetToken()}),
}
authConn, err := grpc.Dial(iapi.GRPCHost+iapi.GRPCPort, opts...)
authConn, err := grpc.NewClient(iapi.GRPCHost+iapi.GRPCPort, opts...)
if err != nil {
return "", nil, err
}
Expand All @@ -101,12 +100,10 @@ func keyGRPCConn(conn *grpc.ClientConn, role api.Role) (
}

opts := []grpc.DialOption{
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithPerRPCCredentials(&credential{token: createKey.GetToken()}),
}
keyConn, err := grpc.Dial(iapi.GRPCHost+iapi.GRPCPort, opts...)
keyConn, err := grpc.NewClient(iapi.GRPCHost+iapi.GRPCPort, opts...)
if err != nil {
return nil, err
}
Expand Down
5 changes: 2 additions & 3 deletions internal/hermes-api/test/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,11 @@ func TestMain(m *testing.M) {

// Build unauthenticated gRPC connection.
opts := []grpc.DialOption{
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(grpc.UseCompressor(gzip.Name)),
}
globalNoAuthGRPCConn, err = grpc.Dial(iapi.GRPCHost+iapi.GRPCPort, opts...)
globalNoAuthGRPCConn, err = grpc.NewClient(iapi.GRPCHost+iapi.GRPCPort,
opts...)
if err != nil {
log.Fatalf("TestMain grpc.Dial: %v", err)
}
Expand Down
20 changes: 9 additions & 11 deletions internal/hermes-api/test/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ func TestLogin(t *testing.T) {
t.Logf("createUser, err: %+v, %v", createUser, err)
require.NoError(t, err)

err = globalUserDAO.UpdatePassword(ctx, createUser.GetId(), createOrg.GetId(),
globalHash)
err = globalUserDAO.UpdatePassword(ctx, createUser.GetId(),
createOrg.GetId(), globalHash)
t.Logf("err: %v", err)
require.NoError(t, err)

Expand All @@ -59,8 +59,8 @@ func TestLogin(t *testing.T) {
t.Logf("createDisUser, err: %+v, %v", createDisUser, err)
require.NoError(t, err)

err = globalUserDAO.UpdatePassword(ctx, createDisUser.GetId(), createOrg.GetId(),
globalHash)
err = globalUserDAO.UpdatePassword(ctx, createDisUser.GetId(),
createOrg.GetId(), globalHash)
t.Logf("err: %v", err)
require.NoError(t, err)

Expand All @@ -71,8 +71,8 @@ func TestLogin(t *testing.T) {
t.Logf("createUnspecUser, err: %+v, %v", createUnspecUser, err)
require.NoError(t, err)

err = globalUserDAO.UpdatePassword(ctx, createUnspecUser.GetId(), createOrg.GetId(),
globalHash)
err = globalUserDAO.UpdatePassword(ctx, createUnspecUser.GetId(),
createOrg.GetId(), globalHash)
t.Logf("err: %v", err)
require.NoError(t, err)

Expand Down Expand Up @@ -199,8 +199,8 @@ func TestCreateKey(t *testing.T) {
t.Logf("createKey, err: %+v, %v", createKey, err)
require.NoError(t, err)
require.NotEqual(t, key.GetId(), createKey.GetKey().GetId())
require.WithinDuration(t, time.Now(), createKey.GetKey().GetCreatedAt().AsTime(),
2*time.Second)
require.WithinDuration(t, time.Now(),
createKey.GetKey().GetCreatedAt().AsTime(), 2*time.Second)
require.NotEmpty(t, createKey.GetToken())
})

Expand Down Expand Up @@ -314,12 +314,10 @@ func TestDeleteKey(t *testing.T) {
require.NoError(t, err)

opts := []grpc.DialOption{
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithPerRPCCredentials(&credential{token: createKey.GetToken()}),
}
keyConn, err := grpc.Dial(iapi.GRPCHost+iapi.GRPCPort, opts...)
keyConn, err := grpc.NewClient(iapi.GRPCHost+iapi.GRPCPort, opts...)
require.NoError(t, err)

sessCli = api.NewSessionServiceClient(keyConn)
Expand Down
40 changes: 23 additions & 17 deletions tool/hermes-create/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,17 @@ const usage = `Usage:
`

func main() {
checkErr := func(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), usage, os.Args[0])
_, err := fmt.Fprintf(flag.CommandLine.Output(), usage, os.Args[0])
checkErr(err)

flag.PrintDefaults()
}

Expand All @@ -54,29 +63,22 @@ func main() {
os.Exit(2)
}

checkErr := func(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

switch flag.Arg(0) {
// Generate UUID and return.
case "uuid":
fmt.Fprintln(os.Stdout, uuid.NewString())
_, err := fmt.Fprintln(os.Stdout, uuid.NewString())
checkErr(err)

return
// Generate UniqID and return.
case "uniqid":
fmt.Fprintln(os.Stdout, random.String(16))
_, err := fmt.Fprintln(os.Stdout, random.String(16))
checkErr(err)

return
// Log in user.
case "login":
opts := []grpc.DialOption{
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithDefaultCallOptions(grpc.UseCompressor(gzip.Name)),
}

Expand All @@ -89,7 +91,7 @@ func main() {
credentials.NewTLS(&tls.Config{MinVersion: tls.VersionTLS12})))
}

conn, err := grpc.Dial(*grpcURI, opts...)
conn, err := grpc.NewClient(*grpcURI, opts...)
checkErr(err)

cli := api.NewSessionServiceClient(conn)
Expand All @@ -101,7 +103,8 @@ func main() {
checkErr(err)
checkErr(conn.Close())

fmt.Fprintf(os.Stdout, "Login: %+v\n", login)
_, err = fmt.Fprintf(os.Stdout, "Login: %+v\n", login)
checkErr(err)

return
}
Expand Down Expand Up @@ -135,7 +138,8 @@ func main() {
checkErr(err)

orgID = createOrg.GetId()
fmt.Fprintf(os.Stdout, "Org: %+v\n", createOrg)
_, err = fmt.Fprintf(os.Stdout, "Org: %+v\n", createOrg)
checkErr(err)

fallthrough
// Create user.
Expand All @@ -158,7 +162,8 @@ func main() {
checkErr(err)

checkErr(userDAO.UpdatePassword(ctx, createUser.GetId(), orgID, hash))
fmt.Fprintf(os.Stdout, "User: %+v\n", createUser)
_, err = fmt.Fprintf(os.Stdout, "User: %+v\n", createUser)
checkErr(err)
// Generate QR code.
case "qr":
identKey, err := base64.StdEncoding.DecodeString(flag.Arg(1))
Expand All @@ -180,6 +185,7 @@ func main() {
qr, err := otp.QR(app.GetDisplayName())
checkErr(err)

fmt.Fprint(os.Stdout, base64.StdEncoding.EncodeToString(qr))
_, err = fmt.Fprint(os.Stdout, base64.StdEncoding.EncodeToString(qr))
checkErr(err)
}
}
24 changes: 15 additions & 9 deletions tool/hermes-hash/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,38 @@ const usage = `Usage:
`

func main() {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), usage, os.Args[0])
flag.PrintDefaults()
}

flag.Parse()

checkErr := func(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

flag.Usage = func() {
_, err := fmt.Fprintf(flag.CommandLine.Output(), usage, os.Args[0])
checkErr(err)

flag.PrintDefaults()
}

flag.Parse()

switch {
// Hash password.
case flag.NArg() == 2 && flag.Arg(0) == "pass":
hash, err := crypto.HashPass(flag.Arg(1))
checkErr(err)
fmt.Fprintf(os.Stdout, "%s\n", hash)

_, err = fmt.Fprintf(os.Stdout, "%s\n", hash)
checkErr(err)
// Decrypt and validate web token.
case flag.NArg() == 3 && flag.Arg(0) == "pwt":
key, err := base64.StdEncoding.DecodeString(flag.Arg(1))
checkErr(err)

sess, err := session.ValidateWebToken(key, flag.Arg(2))
fmt.Fprintf(os.Stdout, "Session: %+v\nError: %v\n", sess, err)
_, err = fmt.Fprintf(os.Stdout, "Session: %+v\nError: %v\n", sess, err)
checkErr(err)
default:
flag.Usage()
os.Exit(2)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e520e25

Please sign in to comment.