Skip to content

Commit

Permalink
first working version (#4)
Browse files Browse the repository at this point in the history
* first working version

* upate flags

* update readme

* wip

* wip

* wip

* wip

* update shutdown

* remove empty file

* refactor LoadConfigFor

* little things

* add print mappings

* fix format

* fix format

* fix format
  • Loading branch information
oscarbc96 authored Nov 4, 2024
1 parent d9f2b76 commit a2eecf9
Show file tree
Hide file tree
Showing 18 changed files with 796 additions and 336 deletions.
1 change: 1 addition & 0 deletions .run/CMD.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<configuration default="false" name="CMD" type="GoApplicationRunConfiguration" factoryName="Go Application" singleton="false">
<module name="agbridge" />
<working_directory value="$PROJECT_DIR$" />
<parameters value="--region eu-west-1 --rest-api-id zyfi5q93t9 --profile-name staging" />
<kind value="DIRECTORY" />
<package value="github.com/oscarbc96/agbridge" />
<directory value="$PROJECT_DIR$/cmd" />
Expand Down
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ agbridge [flags]

### Flags

| Flag | Description | Default |
|--------------------|------------------------------------------------------------------------------------------------------------------|---------------|
| `--version` | Displays the application version and exits. | |
| `--config` | Path to a configuration file for AGBridge. This flag cannot be used with `--profile-name` or `--resource-id`. | |
| `--profile-name` | Specifies the AWS profile name to access resources. Requires `--resource-id` to be specified. | |
| `--resource-id` | Specifies the resource ID of the AWS API gateway. Required if `--config` is not provided. | |
| `--log-level` | Sets the logging level for output messages. Options: `debug`, `info`, `warn`, `error`, `fatal`. | `info` |
| `--listen-address` | Address where AGBridge will listen for incoming requests. Format should be `host:port`. | `:8080` |
| Flag | Description | Default |
|--------------------|----------------------------------------------------------------------------------------------------------------------------|---------|
| `--version` | Displays the application version and exits. | |
| `--config` | Path to a configuration file for AGBridge. This flag cannot be used with `--profile-name`, `--rest-api-id`, or `--region`. | |
| `--profile-name` | Specifies the AWS profile name to access resources. Requires `--rest-api-id` and `--region` to be specified. | |
| `--rest-api-id` | Specifies the Rest API ID of the AWS API gateway. Required if `--config` is not provided. | |
| `--region` | Specifies the AWS region for the API gateway. Requires `--rest-api-id` and `--profile-name`. | |
| `--log-level` | Sets the logging level for output messages. Options: `debug`, `info`, `warn`, `error`, `fatal`. | `info` |
| `--listen-address` | Address where AGBridge will listen for incoming requests. Format should be `host:port`. | `:8080` |

### Examples

#### Specify Resource with Profile
#### Specify API GW with Profile
Specify a resource and profile to access a private API gateway:
```bash
agbridge --profile-name=myprofile --resource-id=12345
agbridge --profile-name=myprofile --rest-api-id=12345
```

#### Load a Specific Configuration File
Expand Down Expand Up @@ -77,7 +78,7 @@ agbridge --listen-address=:9090
```
2. Run the container with appropriate flags. For example:
```bash
docker run --rm -it -p 8080:8080 ghcr.io/oscarbc96/agbridge:latest --profile-name=myprofile --resource-id=12345 --listen-address=:8080
docker run --rm -it -p 8080:8080 ghcr.io/oscarbc96/agbridge:latest --profile-name=myprofile --rest-api-id=12345 --listen-address=:8080
```

### Option 4: Build from Source
Expand Down
80 changes: 49 additions & 31 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import (
"github.com/oscarbc96/agbridge/pkg/log"
)

const (
DefaultConfigFileYaml = "agbridge.yaml"
DefaultConfigFileYml = "agbridge.yml"
)

func setCustomUsage() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
Expand All @@ -22,8 +27,8 @@ Examples:
# Use a specific config file
%[1]s --config=config.yaml
# Set profile name with a resource ID
%[1]s --profile-name=myprofile --resource-id=12345
# Set profile name with a Rest API ID
%[1]s --profile-name=myprofile --rest-api-id=12345
# Set log level to debug
%[1]s --log-level=debug
Expand All @@ -38,79 +43,92 @@ Examples:
}

type Flags struct {
Version bool
Config string
ProfileName string
ResourceID string
ListenAddress string
LogLevel log.Level
ProfileName string
Region string
RestAPIID string
Version bool
}

func parseFlags() (*Flags, error) {
setCustomUsage()

version := flag.Bool("version", false, "Displays the application version and exits.")
config := flag.String("config", "", "Specifies the path to a configuration file (cannot be used with --profile-name or --resource-id).")
profileName := flag.String("profile-name", "", "Specifies the profile name (requires --resource-id to be specified).")
resourceID := flag.String("resource-id", "", "Specifies the resource ID (required if --config is not provided).")
config := flag.String("config", "", "Specifies the path to a configuration file (cannot be used with --profile-name, --rest-api-id, or --region).")
profileName := flag.String("profile-name", "", "Specifies the profile name (requires --rest-api-id and --region to be specified).")
restAPIID := flag.String("rest-api-id", "", "Specifies the Rest API ID (required if --config is not provided).")
region := flag.String("region", "", "Specifies the AWS region to use with --profile-name and --rest-api-id.")
logLevelStr := flag.String("log-level", "info", "Sets the log verbosity level. Options: debug, info, warn, error, fatal.")
listenAddress := flag.String("listen-address", ":8080", "Address where the proxy server will listen for incoming requests.")

flag.Parse()

// Check for version flag
if *version {
return &Flags{Version: true}, nil
}

// Parse log level
logLevel, err := log.ParseLogLevel(*logLevelStr)
if err != nil {
return nil, err
return &Flags{LogLevel: logLevel}, err
}

flags := &Flags{
Version: *version,
Config: *config,
ProfileName: *profileName,
ResourceID: *resourceID,
RestAPIID: *restAPIID,
ListenAddress: *listenAddress,
LogLevel: logLevel,
Region: *region,
}

// Validate listen address format
if _, _, err := net.SplitHostPort(*listenAddress); err != nil {
return flags, fmt.Errorf("invalid listen address format")
return flags, fmt.Errorf("invalid listen address format: %w", err)
}

// Check if a custom config file is specified and verify its existence
if *config != "" {
// If config is specified, it must not be combined with other flags
if *profileName != "" || *resourceID != "" {
return flags, errors.New("--config cannot be combined with --profile-name or --resource-id")
if *profileName != "" || *restAPIID != "" || *region != "" {
return flags, errors.New("`--config` cannot be combined with `--profile-name`, `--rest-api-id`, or `--region`")
}

// Ensure the config file exists
if _, err := os.Stat(*config); os.IsNotExist(err) {
return flags, errors.New("config file does not exist")
return flags, fmt.Errorf("config file does not exist: %w", err)
}
} else {
// If config is not specified, check the necessity of resource ID
if *resourceID == "" && *profileName != "" {
return flags, errors.New("--profile-name requires --resource-id to be specified")
// If no --config, check the rules for --rest-api-id, --region, and --profile-name

// --profile-name requires both --region and --rest-api-id
if *profileName != "" && (*restAPIID == "" || *region == "") {
return flags, errors.New("`--profile-name` requires both `--region` and `--rest-api-id` to be specified")
}

// --region requires --rest-api-id
if *region != "" && *restAPIID == "" {
return flags, errors.New("`--region` requires `--rest-api-id` to be specified")
}

// If no config and no resource ID, check for default config files
if *resourceID == "" {
if _, err := os.Stat("agbridge.yaml"); os.IsNotExist(err) {
if _, err := os.Stat("agbridge.yml"); os.IsNotExist(err) {
return flags, errors.New("please provide --resource-id, --config, or ensure agbridge.yaml or agbridge.yml exists")
} else {
flags.Config = "agbridge.yml" // Default to agbridge.yml if it exists
}
} else {
flags.Config = "agbridge.yaml" // Default to agbridge.yaml if it exists
// If neither --config nor --rest-api-id is provided, fallback to default config file check
if *restAPIID == "" {
configFile, err := checkConfigFileExists(DefaultConfigFileYml, DefaultConfigFileYaml)
if err != nil {
return flags, errors.New("please provide `--rest-api-id`, `--config`, or ensure agbridge.yaml or agbridge.yml exists")
}
flags.Config = configFile
}
}

return flags, nil
}

func checkConfigFileExists(filenames ...string) (string, error) {
for _, filename := range filenames {
if _, err := os.Stat(filename); err == nil {
return filename, nil
}
}
return "", errors.New("no config file found")
}
Loading

0 comments on commit a2eecf9

Please sign in to comment.