Add placeholder-name CLI
- main and unit tests for main - client package to be done in a future commit Signed-off-by: Aram Price <pricear@vmware.com>
This commit is contained in:
parent
9e44bc28d9
commit
27cd82065b
64
cmd/placeholder-name/main.go
Normal file
64
cmd/placeholder-name/main.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 VMware, Inc.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/client-go/pkg/apis/clientauthentication"
|
||||||
|
|
||||||
|
"github.com/suzerain-io/placeholder-name/internal/constable"
|
||||||
|
"github.com/suzerain-io/placeholder-name/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := run(os.LookupEnv, client.ExchangeToken, os.Stdout)
|
||||||
|
if err != nil {
|
||||||
|
_, _ = fmt.Fprintf(os.Stderr, "%s", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type envGetter func(string) (string, bool)
|
||||||
|
type tokenExchanger func(token, caBundle, apiEndpoint string) (*clientauthentication.ExecCredential, error)
|
||||||
|
|
||||||
|
const EnvVarNotSetError = constable.Error("failed to login: environment variable not set")
|
||||||
|
|
||||||
|
func run(envGetter envGetter, tokenExchanger tokenExchanger, outputWriter io.Writer) error {
|
||||||
|
token, varExists := envGetter("PLACEHOLDER_NAME_TOKEN")
|
||||||
|
if !varExists {
|
||||||
|
return envVarNotSetError("PLACEHOLDER_NAME_TOKEN")
|
||||||
|
}
|
||||||
|
|
||||||
|
caBundle, varExists := envGetter("PLACEHOLDER_NAME_CA_BUNDLE")
|
||||||
|
if !varExists {
|
||||||
|
return envVarNotSetError("PLACEHOLDER_NAME_CA_BUNDLE")
|
||||||
|
}
|
||||||
|
|
||||||
|
apiEndpoint, varExists := envGetter("PLACEHOLDER_NAME_K8S_API_ENDPOINT")
|
||||||
|
if !varExists {
|
||||||
|
return envVarNotSetError("PLACEHOLDER_NAME_K8S_API_ENDPOINT")
|
||||||
|
}
|
||||||
|
|
||||||
|
execCredential, err := tokenExchanger(token, caBundle, apiEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to login: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewEncoder(outputWriter).Encode(execCredential)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshall response to stdout: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func envVarNotSetError(varName string) error {
|
||||||
|
return fmt.Errorf("%w: %s", EnvVarNotSetError, varName)
|
||||||
|
}
|
112
cmd/placeholder-name/main_test.go
Normal file
112
cmd/placeholder-name/main_test.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 VMware, Inc.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/client-go/pkg/apis/clientauthentication"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRun(t *testing.T) {
|
||||||
|
spec.Run(t, "Run", func(t *testing.T, when spec.G, it spec.S) {
|
||||||
|
var buffer *bytes.Buffer
|
||||||
|
var tokenExchanger tokenExchanger
|
||||||
|
var fakeEnv map[string]string
|
||||||
|
|
||||||
|
var envGetter envGetter = func(envVarName string) (string, bool) {
|
||||||
|
value, present := fakeEnv[envVarName]
|
||||||
|
if !present {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
buffer = new(bytes.Buffer)
|
||||||
|
fakeEnv = map[string]string{
|
||||||
|
"PLACEHOLDER_NAME_TOKEN": "token from env",
|
||||||
|
"PLACEHOLDER_NAME_CA_BUNDLE": "ca bundle from env",
|
||||||
|
"PLACEHOLDER_NAME_K8S_API_ENDPOINT": "k8s api from env",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
when("env vars are missing", func() {
|
||||||
|
it("returns an error when PLACEHOLDER_NAME_TOKEN is missing", func() {
|
||||||
|
fakeEnv = map[string]string{
|
||||||
|
"PLACEHOLDER_NAME_K8S_API_ENDPOINT": "a",
|
||||||
|
"PLACEHOLDER_NAME_CA_BUNDLE": "b",
|
||||||
|
}
|
||||||
|
err := run(envGetter, tokenExchanger, buffer)
|
||||||
|
require.Error(t, err, "failed to login: environment variable not set: PLACEHOLDER_NAME_TOKEN")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns an error when PLACEHOLDER_NAME_CA_BUNDLE is missing", func() {
|
||||||
|
fakeEnv = map[string]string{
|
||||||
|
"PLACEHOLDER_NAME_K8S_API_ENDPOINT": "a",
|
||||||
|
"PLACEHOLDER_NAME_TOKEN": "b",
|
||||||
|
}
|
||||||
|
err := run(envGetter, tokenExchanger, buffer)
|
||||||
|
require.Error(t, err, "failed to login: environment variable not set: PLACEHOLDER_NAME_CA_BUNDLE")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns an error when PLACEHOLDER_NAME_K8S_API_ENDPOINT is missing", func() {
|
||||||
|
fakeEnv = map[string]string{
|
||||||
|
"PLACEHOLDER_NAME_TOKEN": "a",
|
||||||
|
"PLACEHOLDER_NAME_CA_BUNDLE": "b",
|
||||||
|
}
|
||||||
|
err := run(envGetter, tokenExchanger, buffer)
|
||||||
|
require.Error(t, err, "failed to login: environment variable not set: PLACEHOLDER_NAME_K8S_API_ENDPOINT")
|
||||||
|
})
|
||||||
|
}, spec.Parallel())
|
||||||
|
|
||||||
|
when("the token exchange fails", func() {
|
||||||
|
it.Before(func() {
|
||||||
|
tokenExchanger = func(token, caBundle, apiEndpoint string) (*clientauthentication.ExecCredential, error) {
|
||||||
|
return nil, fmt.Errorf("some error")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns an error", func() {
|
||||||
|
err := run(envGetter, tokenExchanger, buffer)
|
||||||
|
require.Error(t, err, "failed to login: some error")
|
||||||
|
})
|
||||||
|
}, spec.Parallel())
|
||||||
|
|
||||||
|
when("the token exchange succeeds", func() {
|
||||||
|
var actualToken, actualCaBundle, actualAPIEndpoint string
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tokenExchanger = func(token, caBundle, apiEndpoint string) (*clientauthentication.ExecCredential, error) {
|
||||||
|
actualToken, actualCaBundle, actualAPIEndpoint = token, caBundle, apiEndpoint
|
||||||
|
return &clientauthentication.ExecCredential{
|
||||||
|
Status: &clientauthentication.ExecCredentialStatus{Token: "some token"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes the execCredential to the given writer", func() {
|
||||||
|
err := run(envGetter, tokenExchanger, buffer)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, fakeEnv["PLACEHOLDER_NAME_TOKEN"], actualToken)
|
||||||
|
require.Equal(t, fakeEnv["PLACEHOLDER_NAME_CA_BUNDLE"], actualCaBundle)
|
||||||
|
require.Equal(t, fakeEnv["PLACEHOLDER_NAME_K8S_API_ENDPOINT"], actualAPIEndpoint)
|
||||||
|
expected := `{
|
||||||
|
"Spec": {"Interactive": false, "Response": null},
|
||||||
|
"Status": {"ClientCertificateData": "", "ClientKeyData": "", "ExpirationTimestamp": null, "Token": "some token"}
|
||||||
|
}`
|
||||||
|
require.JSONEq(t, expected, buffer.String())
|
||||||
|
})
|
||||||
|
}, spec.Parallel())
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
1
go.mod
1
go.mod
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/golang/mock v1.4.3
|
github.com/golang/mock v1.4.3
|
||||||
github.com/golangci/golangci-lint v1.28.1
|
github.com/golangci/golangci-lint v1.28.1
|
||||||
github.com/google/go-cmp v0.4.0
|
github.com/google/go-cmp v0.4.0
|
||||||
|
github.com/sclevine/spec v1.4.0
|
||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
github.com/suzerain-io/placeholder-name-api v0.0.0-20200724000517-dc602fd8d75e
|
github.com/suzerain-io/placeholder-name-api v0.0.0-20200724000517-dc602fd8d75e
|
||||||
|
2
go.sum
2
go.sum
@ -467,6 +467,8 @@ github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUcc
|
|||||||
github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw=
|
github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw=
|
||||||
github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
|
github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||||
|
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/securego/gosec/v2 v2.3.0 h1:y/9mCF2WPDbSDpL3QDWZD3HHGrSYw0QSHnCqTfs4JPE=
|
github.com/securego/gosec/v2 v2.3.0 h1:y/9mCF2WPDbSDpL3QDWZD3HHGrSYw0QSHnCqTfs4JPE=
|
||||||
github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME=
|
github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME=
|
||||||
|
14
internal/constable/error.go
Normal file
14
internal/constable/error.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 VMware, Inc.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package constable
|
||||||
|
|
||||||
|
var _ error = Error("")
|
||||||
|
|
||||||
|
type Error string
|
||||||
|
|
||||||
|
func (e Error) Error() string {
|
||||||
|
return string(e)
|
||||||
|
}
|
15
pkg/client/client.go
Normal file
15
pkg/client/client.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 VMware, Inc.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import "k8s.io/client-go/pkg/apis/clientauthentication"
|
||||||
|
|
||||||
|
func ExchangeToken(token, caBundle, apiEndpoint string) (*clientauthentication.ExecCredential, error) {
|
||||||
|
_ = token
|
||||||
|
_ = caBundle
|
||||||
|
_ = apiEndpoint
|
||||||
|
return nil, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user