-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Kinesis logging endpoint #177
Add support for Kinesis logging endpoint #177
Conversation
3c70a40
to
0bfb086
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only a few minor comments. Otherwise looking good 👍🏻
pkg/logging/kinesis/create.go
Outdated
"github.com/fastly/go-fastly/v2/fastly" | ||
) | ||
|
||
// CreateCommand calls the Fastly API to create Amazon Kinesis logging endpoints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be singular, not plural for 'endpoint'
// CreateCommand calls the Fastly API to create Amazon Kinesis logging endpoints. | |
// CreateCommand calls the Fastly API to create an Amazon Kinesis logging endpoint. |
pkg/logging/kinesis/create.go
Outdated
c.CmdClause.Flag("name", "The name of the Kinesis logging object. Used as a primary key for API access").Short('n').Required().StringVar(&c.EndpointName) | ||
c.CmdClause.Flag("service-id", "Service ID").Short('s').StringVar(&c.manifest.Flag.ServiceID) | ||
c.CmdClause.Flag("version", "Number of service version").Required().IntVar(&c.Version) | ||
|
||
c.CmdClause.Flag("stream-name", "The Amazon Kinesis stream to send logs to").Required().StringVar(&c.StreamName) | ||
c.CmdClause.Flag("access-key", "The access key associated with the target Amazon Kinesis stream").Required().StringVar(&c.AccessKey) | ||
c.CmdClause.Flag("secret-key", "The secret key associated with the target Amazon Kinesis stream").Required().StringVar(&c.SecretKey) | ||
|
||
c.CmdClause.Flag("region", "The AWS region where the Kinesis stream exists").Required().StringVar(&c.Region) | ||
c.CmdClause.Flag("format", "Apache style log formatting").Action(c.Format.Set).StringVar(&c.Format.Value) | ||
c.CmdClause.Flag("format-version", "The version of the custom logging format used for the configured endpoint. Can be either 2 (default) or 1").Action(c.FormatVersion.Set).UintVar(&c.FormatVersion.Value) | ||
c.CmdClause.Flag("response-condition", "The name of an existing condition in the configured endpoint, or leave blank to always execute").Action(c.ResponseCondition.Set).StringVar(&c.ResponseCondition.Value) | ||
c.CmdClause.Flag("placement", "Where in the generated VCL the logging call should be placed, overriding any format_version default. Can be none or waf_debug").Action(c.Placement.Set).StringVar(&c.Placement.Value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking the flags should be grouped by 'required' followed by 'optional'...
c.CmdClause.Flag("name", "The name of the Kinesis logging object. Used as a primary key for API access").Short('n').Required().StringVar(&c.EndpointName) | |
c.CmdClause.Flag("service-id", "Service ID").Short('s').StringVar(&c.manifest.Flag.ServiceID) | |
c.CmdClause.Flag("version", "Number of service version").Required().IntVar(&c.Version) | |
c.CmdClause.Flag("stream-name", "The Amazon Kinesis stream to send logs to").Required().StringVar(&c.StreamName) | |
c.CmdClause.Flag("access-key", "The access key associated with the target Amazon Kinesis stream").Required().StringVar(&c.AccessKey) | |
c.CmdClause.Flag("secret-key", "The secret key associated with the target Amazon Kinesis stream").Required().StringVar(&c.SecretKey) | |
c.CmdClause.Flag("region", "The AWS region where the Kinesis stream exists").Required().StringVar(&c.Region) | |
c.CmdClause.Flag("format", "Apache style log formatting").Action(c.Format.Set).StringVar(&c.Format.Value) | |
c.CmdClause.Flag("format-version", "The version of the custom logging format used for the configured endpoint. Can be either 2 (default) or 1").Action(c.FormatVersion.Set).UintVar(&c.FormatVersion.Value) | |
c.CmdClause.Flag("response-condition", "The name of an existing condition in the configured endpoint, or leave blank to always execute").Action(c.ResponseCondition.Set).StringVar(&c.ResponseCondition.Value) | |
c.CmdClause.Flag("placement", "Where in the generated VCL the logging call should be placed, overriding any format_version default. Can be none or waf_debug").Action(c.Placement.Set).StringVar(&c.Placement.Value) | |
c.CmdClause.Flag("name", "The name of the Kinesis logging object. Used as a primary key for API access").Short('n').Required().StringVar(&c.EndpointName) | |
c.CmdClause.Flag("version", "Number of service version").Required().IntVar(&c.Version) | |
c.CmdClause.Flag("stream-name", "The Amazon Kinesis stream to send logs to").Required().StringVar(&c.StreamName) | |
c.CmdClause.Flag("access-key", "The access key associated with the target Amazon Kinesis stream").Required().StringVar(&c.AccessKey) | |
c.CmdClause.Flag("secret-key", "The secret key associated with the target Amazon Kinesis stream").Required().StringVar(&c.SecretKey) | |
c.CmdClause.Flag("region", "The AWS region where the Kinesis stream exists").Required().StringVar(&c.Region) | |
c.CmdClause.Flag("service-id", "Service ID").Short('s').StringVar(&c.manifest.Flag.ServiceID) | |
c.CmdClause.Flag("format", "Apache style log formatting").Action(c.Format.Set).StringVar(&c.Format.Value) | |
c.CmdClause.Flag("format-version", "The version of the custom logging format used for the configured endpoint. Can be either 2 (default) or 1").Action(c.FormatVersion.Set).UintVar(&c.FormatVersion.Value) | |
c.CmdClause.Flag("response-condition", "The name of an existing condition in the configured endpoint, or leave blank to always execute").Action(c.ResponseCondition.Set).StringVar(&c.ResponseCondition.Value) | |
c.CmdClause.Flag("placement", "Where in the generated VCL the logging call should be placed, overriding any format_version default. Can be none or waf_debug").Action(c.Placement.Set).StringVar(&c.Placement.Value) |
c.CmdClause.Flag("access-key", "The access key associated with the target Amazon Kinesis stream").Required().StringVar(&c.AccessKey) | ||
c.CmdClause.Flag("secret-key", "The secret key associated with the target Amazon Kinesis stream").Required().StringVar(&c.SecretKey) | ||
|
||
c.CmdClause.Flag("region", "The AWS region where the Kinesis stream exists").Required().StringVar(&c.Region) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure 'region' is required? It doesn't look to be in the API docs example (nor in Go-Fastly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it is required. The configuration validation will fail if it is not present. I see what you mean in the case of go-fastly
. I followed the existing patterns of other logging endpoints when I did that work and they all seem to only have ServiceId
and ServiceVersion
as required. My guess is that the enforcement of required fields was deferred to the config validation, but maybe we want to revisit that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
The configuration validation will fail if it is not present.
I presume 'config validation' refers to the upstream API's own validation, would that be correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see Go-Fastly currently doesn't define validation for the 'region' field, but if we're saying the API itself is expecting a region field otherwise it'll return an error, then we should ensure a validation check for the 'region' field is added into Go-Fastly (I have an existing PR open I can add this to).
But for the time being, this is fine to be marked as .Required()
considering Go-Fastly doesn't currently have logic to catch the missing field.
Note: I can't actually test whether the API expects 'region' to be provided because it seems Kinesis logging isn't available on my personal Fastly account 😬 I did login as an admin to see if it's something I could enable as a feature flag but nothing obvious was coming up in my search.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, just FYI (most of which will be obvious to you): my perspective on this is that we have three tools at play here:
CLI > Go-Fastly > API
We should be able to trust the API to always have the right validation in place, but (as you know) by having validation outside of the API it means we can prevent slowing down a client trying to carry out operations that otherwise we know are just going to fail by the time they reach the API layer, so short-circuiting those requests is better for the client as far as the 'feedback loop' is concerned but also good for the API because it doesn't have to handle the request in the first place.
Considering Go-Fastly and CLI sit at effectively the same level (i.e. they exist on the client) we need to decide which 'tool' is responsible for handling validation of obvious issues with a client request, and for me that should be Go-Fastly as it's the thing that's ultimately fronting the API.
So my hope is that with the work @doramatadora has been doing on the new OpenAPI specification it will mean we can move to a place where we more concretely know what is a required field and have Go-Fastly handle validation and thus reduce duplicating logic in the CLI (although admittedly at this point in time the OpenAPI spec for Kinesis logging still doesn't indicate that 'region' is a required field nor does it show it as part of its example code so that would likely need updating).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume 'config validation' refers to the upstream API's own validation, would that be correct?
That's correct.
Note: I can't actually test whether the API expects 'region' to be provided because it seems Kinesis logging isn't available on my personal Fastly account grimacing I did login as an admin to see if it's something I could enable as a feature flag but nothing obvious was coming up in my search.
If you send me the service id in slack I can enable this for you.
I'll also follow-up on the docs side of things and open a change request if needed to have it indicate region
as required.
pkg/logging/kinesis/delete.go
Outdated
"github.com/fastly/go-fastly/v2/fastly" | ||
) | ||
|
||
// DeleteCommand calls the Fastly API to delete Amazon Kinesis logging endpoints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be singular, not plural for 'endpoint'
// DeleteCommand calls the Fastly API to delete Amazon Kinesis logging endpoints. | |
// DeleteCommand calls the Fastly API to delete an Amazon Kinesis logging endpoint. |
fmt.Fprintf(out, "Service ID: %s\n", kinesis.ServiceID) | ||
fmt.Fprintf(out, "Version: %d\n", kinesis.ServiceVersion) | ||
fmt.Fprintf(out, "Name: %s\n", kinesis.Name) | ||
fmt.Fprintf(out, "Stream name: %s\n", kinesis.StreamName) | ||
fmt.Fprintf(out, "Region: %s\n", kinesis.Region) | ||
fmt.Fprintf(out, "Access key: %s\n", kinesis.AccessKey) | ||
fmt.Fprintf(out, "Secret key: %s\n", kinesis.SecretKey) | ||
fmt.Fprintf(out, "Format: %s\n", kinesis.Format) | ||
fmt.Fprintf(out, "Format version: %d\n", kinesis.FormatVersion) | ||
fmt.Fprintf(out, "Response condition: %s\n", kinesis.ResponseCondition) | ||
fmt.Fprintf(out, "Placement: %s\n", kinesis.Placement) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should create a new /pkg/text/lines.go
to make it easier to render output for newline information (like logging endpoints) and then we'd also be consistent with other packages in the CLI that use the text package.
Something generic like this would suffice: https://play.golang.org/p/csgKDzLZPeu
Which means you could do something like:
import "github.com/fastly/cli/pkg/text"
text.PrintLines(out, text.Lines{
"Service ID": kinesis.ServiceID,
"Version": kinesis.ServiceVersion,
"Name": kinesis.Name,
...
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@phamann what do you think about this...
If we combined this generic implementation (see my comment above) with textio.NewPrefixWriter
then we could probably end up reducing quite a few of the existing Print<T>
functions (e.g. PrintBackend
, PrintDictionaryItemKV
etc).
You could even take it a step further and add in the ability to pass in an optional callback function for those edge cases such as PrintDictionaryItem
where they only print lines that have values (although to be fair that's probably logic you'd shift back up into the consuming package). But I'm just 'brain dumping' ideas at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 to this idea from me. I'd say this is probably out of scope for this PR, but I think it would be a good change to implement broadly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on both accounts:
- Very useful abstraction and would reduce repetition across the codebase.
- Out of scope of this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻 👌🏻
pkg/logging/kinesis/root.go
Outdated
func NewRootCommand(parent common.Registerer, globals *config.Data) *RootCommand { | ||
var c RootCommand | ||
c.Globals = globals | ||
c.CmdClause = parent.Command("kinesis", "Manipulate Fastly service version Kinesis logging endpoints") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of the wording used in the CLI currently as it doesn't read like a correct sentence.
c.CmdClause = parent.Command("kinesis", "Manipulate Fastly service version Kinesis logging endpoints") | |
c.CmdClause = parent.Command("kinesis", "Manipulate a Kinesis logging endpoint for a specific Fastly service version") |
This could be something I fix more broadly in a separate PR though.
Oh, actually -- is this command even reachable (after looking at Exec
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, actually -- is this command even reachable (after looking at Exec)?
All command groups have unreachable roots in the tree. This is the root for this group of commands, the text is only used in help
output when, for instance, fastly logging --help
is ran.
return nil | ||
} | ||
|
||
fmt.Fprintf(out, "Service ID: %s\n", c.Input.ServiceID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to my earlier comment I think a new generic text implementation could be useful here as well.
ed2d1e6
to
7eb1d32
Compare
pkg/logging/kinesis/create.go
Outdated
|
||
// required | ||
c.CmdClause.Flag("name", "The name of the Kinesis logging object. Used as a primary key for API access").Short('n').Required().StringVar(&c.EndpointName) | ||
c.CmdClause.Flag("service-id", "Service ID").Required().Short('s').StringVar(&c.manifest.Flag.ServiceID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that service-id
is not marked as required in many or maybe all of the logging endpoint code. I've set it for Kinesis in this PR, but I'll address the inconsistency in the rest of the logging endpoints in another PR.
@kellymclaughlin just checking, was this PR ready for another review? |
@Integralist Yes, this should be good for another look. Thanks! |
go.sum
Outdated
@@ -32,6 +32,8 @@ github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg | |||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= | |||
github.com/fastly/go-fastly/v2 v2.0.0 h1:dCPOEbTXy8ic5CGj6YibPNvRYG01y15H7kHTlC4d57k= | |||
github.com/fastly/go-fastly/v2 v2.0.0/go.mod h1:+gom+YR+9Q5I4biSk/ZjHQGWXxqpRxC3YDVYQcRpZwQ= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we run a go mod tidy
to see if we can get the v2.0.0 go-fastly dependency cleared from this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
pkg/logging/kinesis/delete.go
Outdated
c.Globals = globals | ||
c.manifest.File.Read(manifest.Filename) | ||
c.CmdClause = parent.Command("delete", "Delete a Kinesis logging endpoint on a Fastly service version").Alias("remove") | ||
c.CmdClause.Flag("service-id", "Service ID").Required().Short('s').StringVar(&c.manifest.Flag.ServiceID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kellymclaughlin so interestingly I'm not sure if service-id needs to be 'required' in the sense that later on in Exec
we have...
serviceID, source := c.manifest.ServiceID()
if source == manifest.SourceUndefined {
return errors.ErrNoServiceID
}
If we inspect the ServiceID()
method it's checking first the flag and then the manifest file for a service id before erroring if both are missing...
cli/pkg/compute/manifest/manifest.go
Lines 52 to 63 in c0f3373
// ServiceID yields a ServiceID. | |
func (d *Data) ServiceID() (string, Source) { | |
if d.Flag.ServiceID != "" { | |
return d.Flag.ServiceID, SourceFlag | |
} | |
if d.File.ServiceID != "" { | |
return d.File.ServiceID, SourceFile | |
} | |
return "", SourceUndefined | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh interesting. Ok, I'll remove the Required
and move the service-id
option to the optional section then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kellymclaughlin this LGTM but before merging could you first rebase master.
Depending on when you see this notification you might need to wait until I've gotten someone to approve this PR (which will cut a new 'patch' CLI release v0.21.2
).
Once that's done and you've rebased, then your PR can be cut as a 'minor' release v0.22.0
(along with your Splunk PR).
Thanks!
62ab724
to
42e6b99
Compare
This requires moving to version 2.1.0 of
go-fastly
. If there's other work that needs to be done before that can happen that's fine, but I wanted to go ahead and get the PR out there even if it can't be merged right away.