Skip to content

Commit b1c644e

Browse files
committed
feat(cli): Add flag --offline that will prevent kfutil from reaching out to GitHub for latest releases of resources like store type definitions.
chore(docs): Update docs with `--offline` flag Signed-off-by: spbsoluble <[email protected]>
1 parent 58d6e96 commit b1c644e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+245
-139
lines changed

cmd/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const (
3030
DebugFuncEnter = "entered: %s"
3131
DebugFuncExit = "exiting: %s"
3232
DebugFuncCall = "calling: %s"
33+
MinHttpTimeout = 3
3334
)
3435

3536
var ProviderTypeChoices = []string{

cmd/root.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ var (
4545
kfcAPIPath string
4646
logInsecure bool
4747
outputFormat string
48+
offline bool
4849
)
4950

5051
func hashSecretValue(secretValue string) string {
@@ -361,6 +362,12 @@ func init() {
361362
false,
362363
"Enable expEnabled features. (USE AT YOUR OWN RISK, these features are not supported and may change or be removed at any time.)",
363364
)
365+
RootCmd.PersistentFlags().BoolVar(
366+
&offline,
367+
"offline",
368+
false,
369+
"Will not attempt to connect to GitHub for latest release information and resources.",
370+
)
364371
RootCmd.PersistentFlags().BoolVar(&debugFlag, "debug", false, "Enable debugFlag logging.")
365372
RootCmd.PersistentFlags().BoolVar(
366373
&logInsecure,

cmd/storeTypes.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"os"
2424
"sort"
2525
"strings"
26+
"time"
2627

2728
"github.com/AlecAivazis/survey/v2"
2829
"github.com/Keyfactor/keyfactor-go-client/v2/api"
@@ -174,7 +175,7 @@ var storesTypeCreateCmd = &cobra.Command{
174175
} else {
175176
typesToCreate = validStoreTypes
176177
}
177-
storeTypeConfig, stErr := readStoreTypesConfig("", gitRef)
178+
storeTypeConfig, stErr := readStoreTypesConfig("", gitRef, offline)
178179
if stErr != nil {
179180
log.Error().Err(stErr).Send()
180181
return stErr
@@ -364,7 +365,7 @@ var fetchStoreTypesCmd = &cobra.Command{
364365
if gitRef == "" {
365366
gitRef = "main"
366367
}
367-
templates, err := readStoreTypesConfig("", gitRef)
368+
templates, err := readStoreTypesConfig("", gitRef, offline)
368369
if err != nil {
369370
log.Error().Err(err).Send()
370371
return err
@@ -454,7 +455,14 @@ func getStoreTypesInternet(gitRef string) (map[string]interface{}, error) {
454455
Str("url", url).
455456
Msg("Getting store types from internet")
456457

457-
resp, rErr := http.Get(url)
458+
// Define the timeout duration
459+
timeout := MinHttpTimeout * time.Second
460+
461+
// Create a custom http.Client with the timeout
462+
client := &http.Client{
463+
Timeout: timeout,
464+
}
465+
resp, rErr := client.Get(url)
458466
if rErr != nil {
459467
return nil, rErr
460468
}
@@ -489,7 +497,7 @@ func getValidStoreTypes(fp string, gitRef string) []string {
489497
Str("file", fp).
490498
Str("gitRef", gitRef).
491499
Msg("Reading store types config.")
492-
validStoreTypes, rErr := readStoreTypesConfig(fp, gitRef)
500+
validStoreTypes, rErr := readStoreTypesConfig(fp, gitRef, offline)
493501
if rErr != nil {
494502
log.Error().Err(rErr).Msg("unable to read store types")
495503
return nil
@@ -502,12 +510,22 @@ func getValidStoreTypes(fp string, gitRef string) []string {
502510
return validStoreTypesList
503511
}
504512

505-
func readStoreTypesConfig(fp, gitRef string) (map[string]interface{}, error) {
513+
func readStoreTypesConfig(fp, gitRef string, offline bool) (map[string]interface{}, error) {
506514
log.Debug().Str("file", fp).Str("gitRef", gitRef).Msg("Entering readStoreTypesConfig")
507515

508-
sTypes, stErr := getStoreTypesInternet(gitRef)
516+
var (
517+
sTypes map[string]interface{}
518+
stErr error
519+
)
520+
if offline {
521+
log.Debug().Msg("Reading store types config from file")
522+
} else {
523+
log.Debug().Msg("Reading store types config from internet")
524+
sTypes, stErr = getStoreTypesInternet(gitRef)
525+
}
526+
509527
if stErr != nil || sTypes == nil || len(sTypes) == 0 {
510-
log.Warn().Err(stErr).Msg("Unable to read store types from internet, using embedded definitions")
528+
log.Warn().Err(stErr).Msg("Using embedded store-type definitions")
511529
var emStoreTypes []interface{}
512530
if err := json.Unmarshal(EmbeddedStoreTypesJSON, &emStoreTypes); err != nil {
513531
log.Error().Err(err).Msg("Unable to unmarshal embedded store type definitions")

cmd/storeTypes_test.go

Lines changed: 96 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"strings"
2323
"testing"
2424

25+
"github.com/spf13/cobra"
2526
"github.com/stretchr/testify/assert"
2627
)
2728

@@ -204,88 +205,107 @@ func Test_StoreTypesCreateFromTemplatesCmd(t *testing.T) {
204205
createAllStoreTypes(t, storeTypes)
205206
}
206207

207-
func createAllStoreTypes(t *testing.T, storeTypes map[string]interface{}) {
208-
t.Run(
209-
fmt.Sprintf("Create ALL StoreTypes"), func(t *testing.T) {
210-
testCmd := RootCmd
211-
// check if I'm running inside a GitHub Action
212-
testArgs := []string{"store-types", "create", "--all"}
213-
isGhAction := os.Getenv("GITHUB_ACTIONS")
214-
t.Log("GITHUB_ACTIONS: ", isGhAction)
215-
if isGhAction == "true" {
216-
ghBranch := os.Getenv("GITHUB_REF")
217-
ghBranch = strings.Replace(ghBranch, "refs/heads/", "", 1)
218-
// url escape the branch name
219-
ghBranch = url.QueryEscape(ghBranch)
220-
testArgs = append(testArgs, "--git-ref", fmt.Sprintf("%s", ghBranch))
221-
t.Log("GITHUB_REF: ", ghBranch)
222-
}
223-
t.Log("testArgs: ", testArgs)
224-
allowFail := false
225-
// Attempt to get the AWS store type because it comes with the product
226-
testCmd.SetArgs(testArgs)
227-
output := captureOutput(
228-
func() {
229-
err := testCmd.Execute()
230-
231-
if err != nil {
232-
eMsg := err.Error()
233-
eMsg = strings.Replace(eMsg, "while creating store types:", "", -1)
234-
for _, exception := range UndeleteableExceptions {
235-
eMsg = strings.Replace(eMsg, exception, "", -1)
236-
}
237-
eMsg = strings.TrimSpace(eMsg)
238-
if eMsg == "" {
239-
return
240-
}
241-
t.Error("Emsg: ", eMsg)
242-
if !allowFail {
243-
assert.NoError(t, err)
244-
}
245-
}
246-
if !allowFail {
247-
assert.NoError(t, err)
248-
}
249-
},
250-
)
208+
func testCreateStoreType(
209+
t *testing.T,
210+
testCmd *cobra.Command,
211+
testArgs []string,
212+
storeTypes map[string]interface{},
213+
) error {
214+
isGhAction := os.Getenv("GITHUB_ACTIONS")
215+
t.Log("GITHUB_ACTIONS: ", isGhAction)
216+
if isGhAction == "true" {
217+
ghBranch := os.Getenv("GITHUB_REF")
218+
ghBranch = strings.Replace(ghBranch, "refs/heads/", "", 1)
219+
// url escape the branch name
220+
ghBranch = url.QueryEscape(ghBranch)
221+
testArgs = append(testArgs, "--git-ref", fmt.Sprintf("%s", ghBranch))
222+
t.Log("GITHUB_REF: ", ghBranch)
223+
}
224+
t.Log("testArgs: ", testArgs)
225+
allowFail := false
226+
// Attempt to get the AWS store type because it comes with the product
227+
testCmd.SetArgs(testArgs)
228+
output := captureOutput(
229+
func() {
230+
err := testCmd.Execute()
251231

232+
if err != nil {
233+
eMsg := err.Error()
234+
eMsg = strings.Replace(eMsg, "while creating store types:", "", -1)
235+
for _, exception := range UndeleteableExceptions {
236+
eMsg = strings.Replace(eMsg, exception, "", -1)
237+
}
238+
eMsg = strings.TrimSpace(eMsg)
239+
if eMsg == "" {
240+
return
241+
}
242+
t.Error("Emsg: ", eMsg)
243+
if !allowFail {
244+
assert.NoError(t, err)
245+
}
246+
}
252247
if !allowFail {
253-
assert.NotNil(t, output, "No output returned from create all command")
248+
assert.NoError(t, err)
254249
}
250+
},
251+
)
255252

256-
// iterate over the store types and verify that each has a name shortname and storetype
257-
for sType := range storeTypes {
258-
storeType := storeTypes[sType].(map[string]interface{})
259-
assert.NotNil(t, storeType["Name"], "Expected store type to have a name")
260-
assert.NotNil(t, storeType["ShortName"], "Expected store type to have short name")
261-
262-
// verify short name is a string
263-
_, ok := storeType["ShortName"].(string)
264-
assert.True(t, ok, "Expected short name to be a string")
265-
// verify name is a string
266-
_, ok = storeType["Name"].(string)
267-
assert.True(t, ok, "Expected name to be a string")
268-
269-
// Attempt to create the store type
270-
shortName := storeType["ShortName"].(string)
271-
allowStoreTypeFail := false
272-
if checkIsUnDeleteable(shortName) {
273-
t.Logf("WARNING: Skipping check for un-deletable store-type: %s", shortName)
274-
allowStoreTypeFail = true
275-
}
253+
if !allowFail {
254+
assert.NotNil(t, output, "No output returned from create all command")
255+
}
276256

277-
if !allowStoreTypeFail {
278-
assert.Contains(
279-
t,
280-
output,
281-
fmt.Sprintf("Certificate store type %s created with ID", shortName),
282-
"Expected output to contain store type created message",
283-
)
284-
}
257+
// iterate over the store types and verify that each has a name shortname and storetype
258+
for sType := range storeTypes {
259+
storeType := storeTypes[sType].(map[string]interface{})
260+
assert.NotNil(t, storeType["Name"], "Expected store type to have a name")
261+
assert.NotNil(t, storeType["ShortName"], "Expected store type to have short name")
285262

286-
// Delete again after create
287-
deleteStoreTypeTest(t, shortName, allowStoreTypeFail)
288-
}
263+
// verify short name is a string
264+
_, ok := storeType["ShortName"].(string)
265+
assert.True(t, ok, "Expected short name to be a string")
266+
// verify name is a string
267+
_, ok = storeType["Name"].(string)
268+
assert.True(t, ok, "Expected name to be a string")
269+
270+
// Attempt to create the store type
271+
shortName := storeType["ShortName"].(string)
272+
allowStoreTypeFail := false
273+
if checkIsUnDeleteable(shortName) {
274+
t.Logf("WARNING: Skipping check for un-deletable store-type: %s", shortName)
275+
allowStoreTypeFail = true
276+
}
277+
278+
if !allowStoreTypeFail {
279+
assert.Contains(
280+
t,
281+
output,
282+
fmt.Sprintf("Certificate store type %s created with ID", shortName),
283+
"Expected output to contain store type created message",
284+
)
285+
}
286+
287+
// Delete again after create
288+
deleteStoreTypeTest(t, shortName, allowStoreTypeFail)
289+
}
290+
return nil
291+
}
292+
293+
func createAllStoreTypes(t *testing.T, storeTypes map[string]interface{}) {
294+
t.Run(
295+
fmt.Sprintf("ONLINE Create ALL StoreTypes"), func(t *testing.T) {
296+
testCmd := RootCmd
297+
// check if I'm running inside a GitHub Action
298+
testArgs := []string{"store-types", "create", "--all"}
299+
testCreateStoreType(t, testCmd, testArgs, storeTypes)
300+
301+
},
302+
)
303+
t.Run(
304+
fmt.Sprintf("OFFLINE Create ALL StoreTypes"), func(t *testing.T) {
305+
testCmd := RootCmd
306+
// check if I'm running inside a GitHub Action
307+
testArgs := []string{"store-types", "create", "--all", "--offline"}
308+
testCreateStoreType(t, testCmd, testArgs, storeTypes)
289309
},
290310
)
291311
}

docs/kfutil.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ A CLI wrapper around the Keyfactor Platform API.
2121
--hostname string Hostname to use for authenticating to Keyfactor Command.
2222
--log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.)
2323
--no-prompt Do not prompt for any user input and assume defaults or environmental variables are set.
24+
--offline Will not attempt to connect to GitHub for latest release information and resources.
2425
--password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text.
2526
--profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists.
2627
--username string Username to use for authenticating to Keyfactor Command.
@@ -42,4 +43,4 @@ A CLI wrapper around the Keyfactor Platform API.
4243
* [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities.
4344
* [kfutil version](kfutil_version.md) - Shows version of kfutil
4445

45-
###### Auto generated by spf13/cobra on 27-Feb-2024
46+
###### Auto generated by spf13/cobra on 8-Sep-2024

docs/kfutil_completion.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ See each sub-command's help for details on how to use the generated script.
2828
--hostname string Hostname to use for authenticating to Keyfactor Command.
2929
--log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.)
3030
--no-prompt Do not prompt for any user input and assume defaults or environmental variables are set.
31+
--offline Will not attempt to connect to GitHub for latest release information and resources.
3132
--password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text.
3233
--profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists.
3334
--username string Username to use for authenticating to Keyfactor Command.
@@ -41,4 +42,4 @@ See each sub-command's help for details on how to use the generated script.
4142
* [kfutil completion powershell](kfutil_completion_powershell.md) - Generate the autocompletion script for powershell
4243
* [kfutil completion zsh](kfutil_completion_zsh.md) - Generate the autocompletion script for zsh
4344

44-
###### Auto generated by spf13/cobra on 27-Feb-2024
45+
###### Auto generated by spf13/cobra on 8-Sep-2024

docs/kfutil_completion_bash.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ kfutil completion bash
5151
--hostname string Hostname to use for authenticating to Keyfactor Command.
5252
--log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.)
5353
--no-prompt Do not prompt for any user input and assume defaults or environmental variables are set.
54+
--offline Will not attempt to connect to GitHub for latest release information and resources.
5455
--password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text.
5556
--profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists.
5657
--username string Username to use for authenticating to Keyfactor Command.
@@ -60,4 +61,4 @@ kfutil completion bash
6061

6162
* [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell
6263

63-
###### Auto generated by spf13/cobra on 27-Feb-2024
64+
###### Auto generated by spf13/cobra on 8-Sep-2024

docs/kfutil_completion_fish.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ kfutil completion fish [flags]
4242
--hostname string Hostname to use for authenticating to Keyfactor Command.
4343
--log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.)
4444
--no-prompt Do not prompt for any user input and assume defaults or environmental variables are set.
45+
--offline Will not attempt to connect to GitHub for latest release information and resources.
4546
--password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text.
4647
--profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists.
4748
--username string Username to use for authenticating to Keyfactor Command.
@@ -51,4 +52,4 @@ kfutil completion fish [flags]
5152

5253
* [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell
5354

54-
###### Auto generated by spf13/cobra on 27-Feb-2024
55+
###### Auto generated by spf13/cobra on 8-Sep-2024

docs/kfutil_completion_powershell.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ kfutil completion powershell [flags]
3939
--hostname string Hostname to use for authenticating to Keyfactor Command.
4040
--log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.)
4141
--no-prompt Do not prompt for any user input and assume defaults or environmental variables are set.
42+
--offline Will not attempt to connect to GitHub for latest release information and resources.
4243
--password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text.
4344
--profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists.
4445
--username string Username to use for authenticating to Keyfactor Command.
@@ -48,4 +49,4 @@ kfutil completion powershell [flags]
4849

4950
* [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell
5051

51-
###### Auto generated by spf13/cobra on 27-Feb-2024
52+
###### Auto generated by spf13/cobra on 8-Sep-2024

docs/kfutil_completion_zsh.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ kfutil completion zsh [flags]
5353
--hostname string Hostname to use for authenticating to Keyfactor Command.
5454
--log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.)
5555
--no-prompt Do not prompt for any user input and assume defaults or environmental variables are set.
56+
--offline Will not attempt to connect to GitHub for latest release information and resources.
5657
--password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text.
5758
--profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists.
5859
--username string Username to use for authenticating to Keyfactor Command.
@@ -62,4 +63,4 @@ kfutil completion zsh [flags]
6263

6364
* [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell
6465

65-
###### Auto generated by spf13/cobra on 27-Feb-2024
66+
###### Auto generated by spf13/cobra on 8-Sep-2024

0 commit comments

Comments
 (0)