diff --git a/cleanenv.go b/cleanenv.go index 0af02ea..6cf6028 100644 --- a/cleanenv.go +++ b/cleanenv.go @@ -313,8 +313,13 @@ func readEnvVars(cfg interface{}, update bool) error { } if rawValue == nil && meta.required && meta.isFieldValueZero() { - err := fmt.Errorf("field %q is required but the value is not provided", - meta.fieldName) + envList := "" + for _, env := range meta.envList { + envList = envList + env + " " + } + envList = strings.Trim(envList, " ") + err := fmt.Errorf("field %q is required but the value is not provided. Envs names: %q", + meta.fieldName, envList) return err } @@ -512,8 +517,10 @@ func GetDescription(cfg interface{}, headerText *string) (string, error) { } elemDescription += fmt.Sprintf("\n \t%s", m.description) if m.defValue != nil { - elemDescription += fmt.Sprintf(" (default %q)", *m.defValue) + elemDescription += fmt.Sprintf("\n \tDefault: %q", *m.defValue) } + elemDescription += fmt.Sprintf("\n \tRequired: %t", m.required) + description += elemDescription } } diff --git a/cleanenv_test.go b/cleanenv_test.go index c39e0b9..32df56f 100644 --- a/cleanenv_test.go +++ b/cleanenv_test.go @@ -693,9 +693,9 @@ func TestGetDescription(t *testing.T) { cfg: &testSingleEnv{}, header: nil, want: "Environment variables:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo" + - "\n THREE int\n \tthree", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n THREE int\n \tthree\n \tRequired: false", wantErr: false, }, @@ -704,10 +704,10 @@ func TestGetDescription(t *testing.T) { cfg: &testSeveralEnv{}, header: nil, want: "Environment variables:" + - "\n ONE int\n \tone" + - "\n ENO int (alternative to ONE)\n \tone" + - "\n TWO int\n \ttwo" + - "\n OWT int (alternative to TWO)\n \ttwo", + "\n ONE int\n \tone\n \tRequired: false" + + "\n ENO int (alternative to ONE)\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n OWT int (alternative to TWO)\n \ttwo\n \tRequired: false", wantErr: false, }, @@ -716,9 +716,9 @@ func TestGetDescription(t *testing.T) { cfg: &testDefaultEnv{}, header: nil, want: "Environment variables:" + - "\n ONE int\n \tone (default \"1\")" + - "\n TWO int\n \ttwo (default \"2\")" + - "\n THREE int\n \tthree (default \"3\")", + "\n ONE int\n \tone\n \tDefault: \"1\"\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tDefault: \"2\"\n \tRequired: false" + + "\n THREE int\n \tthree\n \tDefault: \"3\"\n \tRequired: false", wantErr: false, }, @@ -727,8 +727,8 @@ func TestGetDescription(t *testing.T) { cfg: &testDeep{}, header: nil, want: "Environment variables:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false", wantErr: false, }, @@ -745,9 +745,9 @@ func TestGetDescription(t *testing.T) { cfg: &testSingleEnv{}, header: &header, want: "test header:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo" + - "\n THREE int\n \tthree", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n THREE int\n \tthree\n \tRequired: false", wantErr: false, }, @@ -764,11 +764,11 @@ func TestGetDescription(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := GetDescription(tt.cfg, tt.header) if (err != nil) != tt.wantErr { - t.Errorf("wrong error behavior %v, wantErr %v", err, tt.wantErr) + t.Errorf("case %q: wrong error behavior %v, wantErr %v", tt.name, err, tt.wantErr) return } if got != tt.want { - t.Errorf("wrong description text %s, want %s", got, tt.want) + t.Errorf("case %q: wrong description text:\n %s\n want:\n %s", tt.name, got, tt.want) } }) } @@ -794,9 +794,9 @@ func TestFUsage(t *testing.T) { headerText: nil, usageTexts: nil, want: "Environment variables:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo" + - "\n THREE int\n \tthree\n", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n THREE int\n \tthree\n \tRequired: false\n", }, { @@ -804,9 +804,9 @@ func TestFUsage(t *testing.T) { headerText: &customHeader, usageTexts: nil, want: "test header:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo" + - "\n THREE int\n \tthree\n", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n THREE int\n \tthree\n \tRequired: false\n", }, { @@ -819,9 +819,9 @@ func TestFUsage(t *testing.T) { }, want: "test1\ntest2\ntest3\n" + "\nEnvironment variables:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo" + - "\n THREE int\n \tthree\n", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n THREE int\n \tthree\n \tRequired: false\n", }, { @@ -834,9 +834,9 @@ func TestFUsage(t *testing.T) { }, want: "test1\ntest2\ntest3\n" + "\ntest header:" + - "\n ONE int\n \tone" + - "\n TWO int\n \ttwo" + - "\n THREE int\n \tthree\n", + "\n ONE int\n \tone\n \tRequired: false" + + "\n TWO int\n \ttwo\n \tRequired: false" + + "\n THREE int\n \tthree\n \tRequired: false\n", }, } for _, tt := range tests { @@ -856,7 +856,7 @@ func TestFUsage(t *testing.T) { got := string(gotRaw) if got != tt.want { - t.Errorf("wrong output %v, want %v", got, tt.want) + t.Errorf("wrong output\n %v, want\n %v", got, tt.want) } }) } diff --git a/example/simple_config/config.yml b/example/simple_config/config.yml deleted file mode 100644 index d2723f1..0000000 --- a/example/simple_config/config.yml +++ /dev/null @@ -1,7 +0,0 @@ -database: - host: localhost - port: 5432 - -server: - host: localhost - port: 8888 \ No newline at end of file diff --git a/example_test.go b/example_test.go index bc5473e..7a4100e 100644 --- a/example_test.go +++ b/example_test.go @@ -27,10 +27,13 @@ func ExampleGetDescription() { //Output: Environment variables: // ONE int64 // first parameter + // Required: false // TWO float64 // second parameter + // Required: false // THREE string // third parameter + // Required: false } // ExampleGetDescription_defaults builds a description text from structure tags with description of default values @@ -51,11 +54,17 @@ func ExampleGetDescription_defaults() { fmt.Println(text) //Output: Environment variables: // ONE int64 - // first parameter (default "1") + // first parameter + // Default: "1" + // Required: false // TWO float64 - // second parameter (default "2.2") + // second parameter + // Default: "2.2" + // Required: false // THREE string - // third parameter (default "test") + // third parameter + // Default: "test" + // Required: false } // ExampleGetDescription_variableList builds a description text from structure tags with description of alternative variables @@ -75,10 +84,13 @@ func ExampleGetDescription_variableList() { //Output: Environment variables: // ONE int64 // first found parameter + // Required: false // TWO int64 (alternative to ONE) // first found parameter + // Required: false // THREE int64 (alternative to ONE) // first found parameter + // Required: false } // ExampleGetDescription_customHeaderText builds a description text from structure tags with custom header string @@ -102,10 +114,13 @@ func ExampleGetDescription_customHeaderText() { //Output: Custom header text: // ONE int64 // first parameter + // Required: false // TWO float64 // second parameter + // Required: false // THREE string // third parameter + // Required: false } // ExampleUpdateEnv updates variables in the configuration structure. @@ -250,8 +265,11 @@ func ExampleUsage() { // My sweet variables: // ONE int64 // first parameter + // Required: false // TWO float64 // second parameter + // Required: false // THREE string // third parameter + // Required: false } diff --git a/go.mod b/go.mod index 00f2e53..258b5cb 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/ilyakaznacheev/cleanenv +module github.com/mashinapetro/cleanenv require ( github.com/BurntSushi/toml v0.3.1