Skip to content

Commit

Permalink
Improved handling of stack trace log file
Browse files Browse the repository at this point in the history
  • Loading branch information
charliecon committed Jan 30, 2025
1 parent 3fc3a8b commit 3520dd4
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ func GenerateGrammarResource(
description string,
) string {
return fmt.Sprintf(`
resource "genesyscloud_architect_grammar" "%s" {
resource "%s" "%s" {
name = "%s"
description = "%s"
}
`, resourceLabel, name, description)
`, ResourceType, resourceLabel, name, description)
}
10 changes: 5 additions & 5 deletions genesyscloud/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ func New(version string, providerResources map[string]*schema.Resource, provider
Description: "If set to true the provider will log stack traces to a file instead of crashing, where possible. Can be set with the `GENESYSCLOUD_LOG_STACK_TRACES` environment variable.",
},
"log_stack_traces_file_path": {
Type: schema.TypeString,
Optional: true,
Description: "Specifies the file path for the stack trace logs. Can be set with the `GENESYSCLOUD_LOG_STACK_TRACES_FILE_PATH` environment variable. Default value is genesyscloud_stack_traces.log",
DefaultFunc: schema.EnvDefaultFunc("GENESYSCLOUD_LOG_STACK_TRACES_FILE_PATH", "genesyscloud_stack_traces.log"),
ValidateFunc: validation.StringDoesNotMatch(regexp.MustCompile(`^(|\s+)$`), "Invalid File path "),
Type: schema.TypeString,
Optional: true,
Description: "Specifies the file path for the stack trace logs. Can be set with the `GENESYSCLOUD_LOG_STACK_TRACES_FILE_PATH` environment variable. Default value is genesyscloud_stack_traces.log",
DefaultFunc: schema.EnvDefaultFunc("GENESYSCLOUD_LOG_STACK_TRACES_FILE_PATH", "genesyscloud_stack_traces.log"),
ValidateDiagFunc: validateLogFilePath,
},
"gateway": {
Type: schema.TypeSet,
Expand Down
31 changes: 31 additions & 0 deletions genesyscloud/provider/provider_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package provider

import (
"fmt"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -44,6 +47,34 @@ func TestDefaultHomeDivision(resource string) resource.TestCheckFunc {
}
}

// validateLogFilePath validates that a log file path is not empty, does
// not contain any whitespaces, and that it ends with ".log"
// (Keeping this inside validators causes import cycle)
func validateLogFilePath(filepath any, _ cty.Path) (err diag.Diagnostics) {
defer func() {
if err != nil {
err = diag.Errorf("validateLogFilePath failed: %v", err)
}
}()

val, ok := filepath.(string)
if !ok {
return diag.Errorf("expected type of %v to be string, got %T", filepath, filepath)
}

// Check if the string is empty or contains any whitespace
if val == "" || strings.ContainsAny(val, " \t\n\r") {
return diag.Errorf("filepath must not be empty or contain whitespace, got: %s", val)
}

// Check if the file ends with .log
if !strings.HasSuffix(val, ".log") {
return diag.Errorf("%s must end with .log extension", val)
}

return err
}

func GetOrgDefaultCountryCode() string {
return orgDefaultCountryCode
}
66 changes: 66 additions & 0 deletions genesyscloud/provider/provider_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package provider

import (
"testing"
)

func TestUnitValidateLogFilePath(t *testing.T) {
testCases := []struct {
name string
path interface{}
expectError bool
}{
{
name: "Valid log file path",
path: "logs/application.log",
expectError: false,
},
{
name: "Empty path",
path: "",
expectError: true,
},
{
name: "Non-string value",
path: 123,
expectError: true,
},
{
name: "Relative path with directory",
path: "./logs/currentTestCase.log",
expectError: false,
},
{
name: "Absolute path",
path: "/var/logs/currentTestCase.log",
expectError: false,
},
{
name: "Path with spaces",
path: "logs/current TestCase.log",
expectError: true,
},
{
name: "Incorrect file extension",
path: "terraform.tfstate",
expectError: true,
},
{
name: "Incorrect file extension",
path: "main.go",
expectError: true,
},
}

for _, currentTestCase := range testCases {
t.Run(currentTestCase.name, func(t *testing.T) {
diagErr := validateLogFilePath(currentTestCase.path, nil)
if currentTestCase.expectError && diagErr == nil {
t.Fatalf("Expected an error, but got none")
}
if !currentTestCase.expectError && diagErr != nil {
t.Fatalf("Unexpected error: %v", diagErr)
}
})
}
}
32 changes: 32 additions & 0 deletions genesyscloud/util/panic_recovery_logger/panic_recovery_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package panic_recovery_logger

import (
"fmt"
"log"
"os"
"runtime/debug"
)
Expand All @@ -14,6 +15,9 @@ type PanicRecoveryLogger struct {
var panicRecoverLogger *PanicRecoveryLogger

func InitPanicRecoveryLoggerInstance(enabled bool, filepath string) {
if err := deleteFileIfExists(filepath); err != nil {
log.Println(err)
}
panicRecoverLogger = &PanicRecoveryLogger{
LoggerEnabled: enabled,
filePath: filepath,
Expand Down Expand Up @@ -61,3 +65,31 @@ func appendToFile(filename string, data []byte) (err error) {
_ = file.Close()
return err
}

// deleteFileIfExists deletes file at filepath if it exists and does nothing if it doesn't
func deleteFileIfExists(filepath string) (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("deleteFileIfExists failed: %w (%s may contain stack traces from the previous deployment)", err, filepath)
}
}()

// Check if file exists
_, err = os.Stat(filepath)
if err != nil {
if os.IsNotExist(err) {
// File doesn't exist, return nil as this is not an error condition
return nil
}
// Return other errors (permission issues, etc.)
return fmt.Errorf("failed to check file existence: %w", err)
}

// File exists, try to remove it
err = os.Remove(filepath)
if err != nil {
return fmt.Errorf("failed to delete file %s: %w", filepath, err)
}

return err
}
1 change: 1 addition & 0 deletions genesyscloud/util/util_retries.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
)

func WithRetries(ctx context.Context, timeout time.Duration, method func() *retry.RetryError) diag.Diagnostics {
method = wrapReadMethodWithRecover(method)
err := diag.FromErr(retry.RetryContext(ctx, timeout, method))
if err != nil && strings.Contains(fmt.Sprintf("%v", err), "timeout while waiting for state to become") {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
Expand Down
4 changes: 2 additions & 2 deletions genesyscloud/validators/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"terraform-provider-genesyscloud/genesyscloud/util"
"terraform-provider-genesyscloud/genesyscloud/util/resourcedata"

files "terraform-provider-genesyscloud/genesyscloud/util/files"
lists "terraform-provider-genesyscloud/genesyscloud/util/lists"
"terraform-provider-genesyscloud/genesyscloud/util/files"
"terraform-provider-genesyscloud/genesyscloud/util/lists"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand Down

0 comments on commit 3520dd4

Please sign in to comment.