Skip to content

Commit

Permalink
feat/improvements (#15)
Browse files Browse the repository at this point in the history
* improve documentation
* improve resolver so it can handle, json, yaml, ini
* move pkg to own repo
* add update command to makefile
  • Loading branch information
gi8lino authored Dec 18, 2024
1 parent 0047e5d commit fb60541
Show file tree
Hide file tree
Showing 59 changed files with 43 additions and 5,601 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ test:

# Generate and display test coverage
cover:
sudo go test ./cmd/... ./pkg/... ./internal/... -count=1 -coverprofile=coverage.out
sudo go test ./cmd/... ./internal/... -count=1 -coverprofile=coverage.out
go tool cover -html=coverage.out

# Clean up generated files
clean:
rm -f coverage.out coverage.html

# Update dependencies
update:
go get -u ./...
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Types are: `http`, `icmp` or `tcp`.

- **`--http.<IDENTIFIER>.address`** = `string`
The target's address.
**Resolvable:** `env:ENV_VAR`, `file:path/to/file.txt`. see below.
**Resolvable:** See [Resolving Variables](#resolving-variables) below.

- **`--http.<IDENTIFIER>.interval`** = `duration`
The interval between HTTP requests (e.g., `1s`). Overwrites the global `--default-interval`.
Expand All @@ -45,7 +45,7 @@ Types are: `http`, `icmp` or `tcp`.
- **`--http.<IDENTIFIER>.header`** = `string`
A HTTP header in `key=value` format. Can be specified multiple times.
**Example:** `Authorization=Bearer token`
**Resolvable:** The value of the Header is resolvable: `env:ENV_VAR`, `file:path/to/file.txt`. see below.
**Resolvable:** See [Resolving Variables](#resolving-variables) below.

- **`--http.<IDENTIFIER>.allow-duplicate-headers`** = `bool`
Allow duplicate headers. Defaults to `false`.
Expand All @@ -66,7 +66,7 @@ Types are: `http`, `icmp` or `tcp`.

- **`--icmp.<IDENTIFIER>.address`** = `string`
The target's address.
**Resolvable:** The value of the Address is resolvable: `env:ENV_VAR`, `file:path/to/file.txt`.
**Resolvable:** See [Resolving Variables](#resolving-variables) below.

- **`--icmp.<IDENTIFIER>.interval`** = `duration`
The interval between ICMP requests (e.g., `1s`). Overwrites the global `--default-interval`.
Expand All @@ -77,29 +77,35 @@ Types are: `http`, `icmp` or `tcp`.
- **`--icmp.<IDENTIFIER>.write-timeout`** = `duration`
The write timeout for the ICMP connection (e.g., `1s`).Defaults to `1s`.

### TCP Flags
#### TCP Flags

- **`--tcp.<IDENTIFIER>.name`** = `string`
The name of the target. If not specified, it uses the `<IDENTIFIER>` as the name.

- **`--tcp.<IDENTIFIER>.address`** = `string`
The target's address.
**Resolvable:** `env:ENV_VAR`, `file:path/to/file.txt`. see below.
**Resolvable:** See [Resolving Variables](#resolving-variables) below.

- **`--tcp.<IDENTIFIER>.interval`** = `duration`
The interval between ICMP requests (e.g., `1s`). Overwrites the global `--default-interval`.

### Resolving variables
#### Resolving variables

Each `address` field can be resolved using environment variables, files, or plain text:
Each `address` field can be resolved using `environment variables`, `files`, `JSON`, `YAML`, and `INI` files.

- **Plain Text**: Simply input the credentials directly in plain text.
- **Environment Variable**: Use the `env:` prefix, followed by the name of the environment variable that stores the credentials.
- **File**: Use the `file:` prefix, followed by the path of the file that contains the credentials. The file should contain only the credentials.
- `env`: – Resolves environment variables.
Example: `env:PATH` returns the value of the `PATH` environment variable.
- `file`: – Resolves values from a simple key-value file.
Example: `file:/config/app.txt//KeyName` returns the value associated with `KeyName` in `app.txt`.
- `json`: – Resolves values from a JSON file. Supports dot notation for nested keys.
Example: `json:/config/app.json//database.host` returns `host` field under `database` in `app.json`. It is also possible to indexing into arrays (e.g., `json:/config/app.json//servers.0.host`).
- `yaml`: – Resolves values from a YAML file. Supports dot notation for nested keys.
Example: `yaml:/config/app.yaml//server.port` returns `port` under `server` in `app.yaml`.It is also possible to indexing into arrays (e.g., `yaml:/config/app.yaml//servers.0.host`).
- `ini`: – Resolves values from an INI file. Can specify a section and key, or just a key in the default section.
Example: `ini:/config/app.ini//Section.Key` returns the value of `Key` under `Section`.
- No prefix – Returns the value as-is, unchanged.

In case the file contains multiple key-value pairs, the specific key for the credentials can be selected by appending `//KEY` to the end of the path. Each key-value pair in the file must follow the `key = value` format. The system will use the value corresponding to the specified `//KEY`.

HTTP headers values can also be resolved using the same mechanism, (`--
HTTP headers values can also be resolved using the same mechanism, (from a environment variable `--http.<IDENTIFIER>.header="header=env:SECRET_HEADER"` or from a file `--http.<IDENTIFIER>.header="header=file:PATH_TO_FILE"`).

### Examples

Expand Down
2 changes: 1 addition & 1 deletion cmd/portpatrol/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func TestRunConfigErrorUnsupportedCheckType(t *testing.T) {
err := run(ctx, args, &output)

assert.Error(t, err)
assert.EqualError(t, err, "configuration error: no checkers configured")
assert.EqualError(t, err, "configuration error: Flag parsing error: unknown flag: --target.unsupported.name")
}

func TestRunConfigErrorInvalidHeaders(t *testing.T) {
Expand Down
105 changes: 0 additions & 105 deletions examples/advanced.go

This file was deleted.

112 changes: 0 additions & 112 deletions examples/simple.go

This file was deleted.

4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ module github.com/containeroo/portpatrol
go 1.23.2

require (
github.com/containeroo/dynflags v0.0.2
github.com/containeroo/httputils v0.0.1
github.com/containeroo/resolver v0.0.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.10.0
golang.org/x/net v0.32.0
Expand All @@ -13,5 +16,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.28.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
github.com/containeroo/dynflags v0.0.2 h1:UmGXDnJ54QwezYHxPzjI1qUJY2Hs0HwywMtO16frtlc=
github.com/containeroo/dynflags v0.0.2/go.mod h1:RFbmo73djvKZKwrlcsAcxfij/LJDtJ1dsbSIKcbzOLg=
github.com/containeroo/httputils v0.0.1 h1:W9SbW6nbmnGgaEOXRH5nY9ZwLarBo3+FLUCx6EtS2mc=
github.com/containeroo/httputils v0.0.1/go.mod h1:TrmDptapH6SBe6CeHFWY2kxy63O/9ZWBWrLKpc2SFjI=
github.com/containeroo/resolver v0.0.1 h1:fGDZ6XlLC3TNvLaQsbcPpJOl3leLazCEMbsQGmWp7Lo=
github.com/containeroo/resolver v0.0.1/go.mod h1:Mii90RfUdmpyjDAt5aJxEjZS05tbfZGu4X3DfuIVGJ8=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -14,5 +20,7 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5 changes: 3 additions & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"io"
"time"

"github.com/containeroo/portpatrol/pkg/dynflags"
"github.com/containeroo/dynflags"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -57,12 +57,13 @@ func ParseFlags(args []string, version string, output io.Writer) (*ParsedFlags,
return nil, fmt.Errorf("error parsing dynamic flags: %w", err)
}

unknownArgs := dynFlags.UnparsedArgs()
unknownArgs := dynFlags.UnknownArgs()

// Parse known flags
if err := flagSet.Parse(unknownArgs); err != nil {
return nil, fmt.Errorf("Flag parsing error: %s", err.Error())
}

// Handle special flags (e.g., --help or --version)
if err := handleSpecialFlags(flagSet, version); err != nil {
return nil, err
Expand Down
15 changes: 0 additions & 15 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@ func TestParseFlags(t *testing.T) {
assert.Equal(t, 5*time.Second, parsedFlags.DefaultCheckInterval)
})

t.Run("Unknown Dynamic Flag", func(t *testing.T) {
t.Parallel()

args := []string{"--unknown.identifier.flag=value"}
var output bytes.Buffer

parsedFlags, err := ParseFlags(args, "1.0.0", &output)
assert.NoError(t, err)

df := parsedFlags.DynFlags
g := df.Unknown()

assert.NotNil(t, g)
})

t.Run("Handle Help Flag", func(t *testing.T) {
t.Parallel()

Expand Down
Loading

0 comments on commit fb60541

Please sign in to comment.