TUN-5754: Allow ingress validate to take plaintext option
Ingress validate currently validates config from a file. This PR adds a new --json/-j flag to provide the ingress/config data as a plaintext command line argument.
This commit is contained in:
parent
051b2cf352
commit
9909e9d63c
|
@ -1,6 +1,7 @@
|
||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
@ -12,6 +13,15 @@ import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ingressDataJSONFlagName = "json"
|
||||||
|
|
||||||
|
var ingressDataJSON = &cli.StringFlag{
|
||||||
|
Name: ingressDataJSONFlagName,
|
||||||
|
Aliases: []string{"j"},
|
||||||
|
Usage: `Accepts data in the form of json as an input rather than read from a file`,
|
||||||
|
EnvVars: []string{"TUNNEL_INGRESS_VALIDATE_JSON"},
|
||||||
|
}
|
||||||
|
|
||||||
func buildIngressSubcommand() *cli.Command {
|
func buildIngressSubcommand() *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "ingress",
|
Name: "ingress",
|
||||||
|
@ -49,6 +59,7 @@ func buildValidateIngressCommand() *cli.Command {
|
||||||
Usage: "Validate the ingress configuration ",
|
Usage: "Validate the ingress configuration ",
|
||||||
UsageText: "cloudflared tunnel [--config FILEPATH] ingress validate",
|
UsageText: "cloudflared tunnel [--config FILEPATH] ingress validate",
|
||||||
Description: "Validates the configuration file, ensuring your ingress rules are OK.",
|
Description: "Validates the configuration file, ensuring your ingress rules are OK.",
|
||||||
|
Flags: []cli.Flag{ingressDataJSON},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,12 +80,11 @@ func buildTestURLCommand() *cli.Command {
|
||||||
|
|
||||||
// validateIngressCommand check the syntax of the ingress rules in the cloudflared config file
|
// validateIngressCommand check the syntax of the ingress rules in the cloudflared config file
|
||||||
func validateIngressCommand(c *cli.Context, warnings string) error {
|
func validateIngressCommand(c *cli.Context, warnings string) error {
|
||||||
conf := config.GetConfiguration()
|
conf, err := getConfiguration(c)
|
||||||
if conf.Source() == "" {
|
if err != nil {
|
||||||
fmt.Println("No configuration file was found. Please create one, or use the --config flag to specify its filepath. You can use the help command to learn more about configuration files")
|
return err
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
fmt.Println("Validating rules from", conf.Source())
|
|
||||||
if _, err := ingress.ParseIngress(conf); err != nil {
|
if _, err := ingress.ParseIngress(conf); err != nil {
|
||||||
return errors.Wrap(err, "Validation failed")
|
return errors.Wrap(err, "Validation failed")
|
||||||
}
|
}
|
||||||
|
@ -90,6 +100,22 @@ func validateIngressCommand(c *cli.Context, warnings string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getConfiguration(c *cli.Context) (*config.Configuration, error) {
|
||||||
|
var conf *config.Configuration
|
||||||
|
if c.IsSet(ingressDataJSONFlagName) {
|
||||||
|
ingressJSON := c.String(ingressDataJSONFlagName)
|
||||||
|
fmt.Println("Validating rules from cmdline flag --json")
|
||||||
|
err := json.Unmarshal([]byte(ingressJSON), &conf)
|
||||||
|
return conf, err
|
||||||
|
}
|
||||||
|
conf = config.GetConfiguration()
|
||||||
|
if conf.Source() == "" {
|
||||||
|
return nil, errors.New("No configuration file was found. Please create one, or use the --config flag to specify its filepath. You can use the help command to learn more about configuration files")
|
||||||
|
}
|
||||||
|
fmt.Println("Validating rules from", conf.Source())
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
// testURLCommand checks which ingress rule matches the given URL.
|
// testURLCommand checks which ingress rule matches the given URL.
|
||||||
func testURLCommand(c *cli.Context) error {
|
func testURLCommand(c *cli.Context) error {
|
||||||
requestArg := c.Args().First()
|
requestArg := c.Args().First()
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cfapi"
|
"github.com/cloudflare/cloudflared/cfapi"
|
||||||
|
@ -322,3 +323,48 @@ func Test_subcommandContext_Delete(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_subcommandContext_ValidateIngressCommand(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
c *cli.Context
|
||||||
|
wantErr bool
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "read a valid configuration from data",
|
||||||
|
c: func() *cli.Context {
|
||||||
|
data := `{ "warp-routing": {"enabled": true}, "originRequest" : {"connectTimeout": 10}, "ingress" : [ {"hostname": "test", "service": "https://localhost:8000" } , {"service": "http_status:404"} ]}`
|
||||||
|
flagSet := flag.NewFlagSet("json", flag.PanicOnError)
|
||||||
|
flagSet.String(ingressDataJSONFlagName, data, "")
|
||||||
|
c := cli.NewContext(cli.NewApp(), flagSet, nil)
|
||||||
|
_ = c.Set(ingressDataJSONFlagName, data)
|
||||||
|
return c
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "read an invalid configuration with multiple mistakes",
|
||||||
|
c: func() *cli.Context {
|
||||||
|
data := `{ "ingress" : [ {"hostname": "test", "service": "localhost:8000" } , {"service": "http_status:invalid_status"} ]}`
|
||||||
|
flagSet := flag.NewFlagSet("json", flag.PanicOnError)
|
||||||
|
flagSet.String(ingressDataJSONFlagName, data, "")
|
||||||
|
c := cli.NewContext(cli.NewApp(), flagSet, nil)
|
||||||
|
_ = c.Set(ingressDataJSONFlagName, data)
|
||||||
|
return c
|
||||||
|
}(),
|
||||||
|
wantErr: true,
|
||||||
|
expectedErr: errors.New("Validation failed: localhost:8000 is an invalid address, please make sure it has a scheme and a hostname"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
err := validateIngressCommand(tt.c, "")
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Equal(t, tt.expectedErr.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue