-
Notifications
You must be signed in to change notification settings - Fork 141
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
LOG-4990: Initial impl of CLF.obs API #2451
Conversation
@jcantrill: This pull request references LOG-4990 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "4.8.0" version, but no target version was set. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
/hold |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jcantrill The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
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.
LGTM to me. Left some comments for impovement. Key question remains if Namespaced
is wanted for this resource. If yes, see my ask on the enhancement proposal to explain when it is used and what for.
listKind: ClusterLogForwarderList | ||
plural: clusterlogforwarders | ||
singular: clusterlogforwarder | ||
scope: Namespaced |
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.
Double checking here. Is Namespaced
intended?
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.
Yes. Maps to mCLF concept. Added reference in enhancement based upon comment
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.
Looks overall good to me. A couple of general minor enhancements:
- Every field being optional and marked with
//+optional
should be marked with// +kubebuilder:validation:Optional
because this is the future-proof marker. I don't know if and when the others will be dropped, but let's add the new ones too. - Same for
// +required
, we should use also// +kubebuilder:validation:Required
- Do we need to add
//+nullable
for optional fields at all or is this a legacy thing? - The
kubebuilder:validation:minLength:=1
marker is used on many required fields. Is this needed if the field is properly marked as required? Maybe we were simply missing// +kubebuilder:validation:Required
in the old logging CLF types?
Rules []auditv1.PolicyRule `json:"rules,omitempty"` | ||
|
||
// OmitStages is a list of stages for which no events are created. | ||
// Note that this can also be specified per rule in which case the union of both are omitted. | ||
// +optional | ||
OmitStages []auditv1.Stage `json:"omitStages,omitempty"` |
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.
Any possibility to add //+listType
and //+listMapKey
here?
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.
Skipping for now since I don't know how this applies. I don't believe there is a place for "unique" entry in the list
api/observability/v1/input_types.go
Outdated
// +optional | ||
Includes []NamespaceContainerSpec `json:"includes,omitempty"` | ||
|
||
// Excludes is the set of namespaces and containers to ignore when collecting logs. | ||
// Takes precedence over Includes option. | ||
// | ||
// +optional | ||
Excludes []NamespaceContainerSpec `json:"excludes,omitempty"` |
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.
Possibility to add // +listType:=map
and // +listMapKey:=namespace
here. WDYT?
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 don't think this applies for these since they can have either namespace or container and neither is really an identifying key
api/observability/v1/input_types.go
Outdated
// Infrastructure enables infrastructure logs. | ||
// Sources of these logs: | ||
// * container workloads deployed to namespaces: default, kube*, openshift* | ||
// * journald logs from cluster nodes | ||
type Infrastructure struct { | ||
|
||
// Sources defines the list of infrastructure sources to collect. | ||
// This field is optional and omission results in the collection of all infrastructure sources. | ||
// Valid sources are: node, container | ||
// | ||
// +optional | ||
Sources []string `json:"sources,omitempty"` | ||
} | ||
|
||
const ( | ||
|
||
// InfrastructureSourceNode are journald logs from the node | ||
InfrastructureSourceNode string = "node" | ||
|
||
// InfrastructureSourceContainer are container logs from workloads deployed | ||
// in any of the following namespaces: default, kube*, openshift* | ||
InfrastructureSourceContainer string = "container" | ||
) | ||
|
||
var InfrastructureSources = sets.NewString(InfrastructureSourceNode, InfrastructureSourceContainer) |
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.
// Infrastructure enables infrastructure logs. | |
// Sources of these logs: | |
// * container workloads deployed to namespaces: default, kube*, openshift* | |
// * journald logs from cluster nodes | |
type Infrastructure struct { | |
// Sources defines the list of infrastructure sources to collect. | |
// This field is optional and omission results in the collection of all infrastructure sources. | |
// Valid sources are: node, container | |
// | |
// +optional | |
Sources []string `json:"sources,omitempty"` | |
} | |
const ( | |
// InfrastructureSourceNode are journald logs from the node | |
InfrastructureSourceNode string = "node" | |
// InfrastructureSourceContainer are container logs from workloads deployed | |
// in any of the following namespaces: default, kube*, openshift* | |
InfrastructureSourceContainer string = "container" | |
) | |
var InfrastructureSources = sets.NewString(InfrastructureSourceNode, InfrastructureSourceContainer) | |
// Infrastructure enables infrastructure logs. | |
// Sources of these logs: | |
// * container workloads deployed to namespaces: default, kube*, openshift* | |
// * journald logs from cluster nodes | |
type Infrastructure struct { | |
// Sources defines the list of infrastructure sources to collect. | |
// This field is optional and omission results in the collection of all infrastructure sources. | |
// Valid sources are: node, container | |
// | |
// +optional | |
// +kubebuilder:validation:UniqueItems:=true | |
Sources []InfrastructureSourceType `json:"sources,omitempty"` | |
} | |
type InfrastructureSourceType string | |
const ( | |
// InfrastructureSourceNode are journald logs from the node | |
InfrastructureSourceNode InfrastructureSourceType = "node" | |
// InfrastructureSourceContainer are container logs from workloads deployed | |
// in any of the following namespaces: default, kube*, openshift* | |
InfrastructureSourceContainer InfrastructureSourceType = "container" | |
) | |
var InfrastructureSources = sets.NewString(InfrastructureSourceNode, InfrastructureSourceContainer) |
api/observability/v1/input_types.go
Outdated
const ( | ||
ReceiverTypeHttp = "http" | ||
ReceiverTypeSyslog = "syslog" | ||
|
||
// InputReceiverFormatKubeAPIAudit Log events in k8s list format, e.g. API audit log events. | ||
InputReceiverFormatKubeAPIAudit = "kubeAPIAudit" | ||
) | ||
|
||
var ReservedInputReceiverNames = sets.NewString(ReceiverTypeHttp, ReceiverTypeSyslog) | ||
|
||
// ReceiverSpec is a union of input Receiver types. | ||
type ReceiverSpec struct { | ||
|
||
// Type of Receiver plugin. | ||
// +kubebuilder:validation:Enum:=http;syslog | ||
// +required | ||
Type string `json:"type,omitempty"` |
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.
const ( | |
ReceiverTypeHttp = "http" | |
ReceiverTypeSyslog = "syslog" | |
// InputReceiverFormatKubeAPIAudit Log events in k8s list format, e.g. API audit log events. | |
InputReceiverFormatKubeAPIAudit = "kubeAPIAudit" | |
) | |
var ReservedInputReceiverNames = sets.NewString(ReceiverTypeHttp, ReceiverTypeSyslog) | |
// ReceiverSpec is a union of input Receiver types. | |
type ReceiverSpec struct { | |
// Type of Receiver plugin. | |
// +kubebuilder:validation:Enum:=http;syslog | |
// +required | |
Type string `json:"type,omitempty"` | |
type ReceiverType string | |
const ( | |
ReceiverTypeHttp ReceiverType = "http" | |
ReceiverTypeSyslog ReceiverType = "syslog" | |
// InputReceiverFormatKubeAPIAudit Log events in k8s list format, e.g. API audit log events. | |
InputReceiverFormatKubeAPIAudit string = "kubeAPIAudit" | |
) | |
var ReservedInputReceiverNames = sets.NewString(ReceiverTypeHttp, ReceiverTypeSyslog) | |
// ReceiverSpec is a union of input Receiver types. | |
type ReceiverSpec struct { | |
// Type of Receiver plugin. | |
// +kubebuilder:validation:Enum:=http;syslog | |
// +required | |
Type ReceiverType `json:"type,omitempty"` |
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 the list of comments I'd have to add would be quite long and it would essentially duplicate the work when you then need to apply them. So I made a branch with the changes instead.
There's always a "change commit" which describes what I've changed and a subsequent "update bundle" one that just does the codegeneration, so there's essentially 2x the commits it would need.
type ClusterLogForwarderStatus struct { | ||
// Conditions of the log forwarder. | ||
//+operator-sdk:csv:customresourcedefinitions:type=status,displayName="Forwarder Conditions",xDescriptors={"urn:alm:descriptor:io.kubernetes.conditions"} | ||
Conditions status.Conditions `json:"conditions,omitempty"` |
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.
status
is an internal package, it should not be used in the public API. I propose we reuse the Condition
struct in the Kubernetes API (k8s.io/apimachinery/pkg/apis/meta/v1
).
// +kubebuilder:object:root=true | ||
// ClusterLogForwarderList contains a list of ClusterLogForwarder |
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.
(see above comment for longer explanation)
Alternative 1:
// +kubebuilder:object:root=true | |
// ClusterLogForwarderList contains a list of ClusterLogForwarder | |
// ClusterLogForwarderList contains a list of ClusterLogForwarder | |
// | |
// +kubebuilder:object:root=true |
Alternative 2:
// +kubebuilder:object:root=true | |
// ClusterLogForwarderList contains a list of ClusterLogForwarder | |
//+kubebuilder:object:root=true | |
// ClusterLogForwarderList contains a list of ClusterLogForwarder |
Can not speak to this. I copied and followed the pattern there so likely a legacy thing
Probably a legacy thing as well |
// +kubebuilder:validation:Required | ||
// +listType:=map | ||
// +listMapKey:=name | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Receiver Outputs" |
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.
Noticed the inputs description was changed to just "Log Inputs", why have "Receiver" here and not just "Log Outputs"?
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Receiver Outputs" | |
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Log Outputs" |
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 I'm going to update all of them to say "Log Forwarder" since Log seems not descriptive enough
// +kubebuilder:validation:Optional | ||
// +listType:=map | ||
// +listMapKey:=name | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Forwarder Pipeline Filters" |
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.
Similarly here: Why use "Forwarder"?
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Forwarder Pipeline Filters" | |
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Log Pipeline Filters" |
// +kubebuilder:validation:Required | ||
// +listType:=map | ||
// +listMapKey:=name | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Forwarder Pipelines" |
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.
Simplify to "Log Pipelines"?
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Forwarder Pipelines" | |
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Log Pipelines" |
/hold cancel |
Looks good to me 👍 |
/override ci/prow/e2e-target |
@jcantrill: Overrode contexts on behalf of jcantrill: ci/prow/e2e-target In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/lgtm |
@jcantrill: The following test failed, say
Full PR test history. Your PR dashboard. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
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.
Tried to leave some general feedback on API conventions and validations you could look into, have tried not to repeat myself but quite a few of the things I mention you may want to comb through for repeats of, but hopefully this gives you some food for thought on improving the API validations without changing the shape too much, let me know if you want any more details on the suggestions
|
||
// InputType specifies the type of log input to create. | ||
// | ||
// +kubebuilder:validation:Enum:=audit;application;infrastructure;receiver |
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.
Enums should be PascalCase to fit kube conventions
// Application, named set of `application` logs that | ||
// can specify a set of match criteria | ||
// | ||
// +kubebuilder:validation:Optional | ||
// +nullable | ||
Application *Application `json:"application,omitempty"` | ||
|
||
// Infrastructure, Enables `infrastructure` logs. | ||
// | ||
// +kubebuilder:validation:Optional | ||
Infrastructure *Infrastructure `json:"infrastructure,omitempty"` | ||
|
||
// Audit, enables `audit` logs. | ||
// | ||
// +kubebuilder:validation:Optional | ||
Audit *Audit `json:"audit,omitempty"` | ||
|
||
// Receiver to receive logs from non-cluster sources. | ||
// | ||
// +kubebuilder:validation:Optional | ||
Receiver *ReceiverSpec `json:"receiver,omitempty"` |
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.
You could use CEL to prevent the wrong union member from being added when the Type specifies a specific member, eg https://github.com/openshift/api/blob/ba11c1587003dc84cb014fd8db3fa597a3faaa63/example/v1/types_stable.go#L108-L125
|
||
// InputSpec defines a selector of log messages for a given log type. | ||
type InputSpec struct { | ||
// Name used to refer to the input of a `pipeline`. |
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.
Kube conventions suggest using the json tag name for the start of the comment, since users are used to seeing serialized versions of fields, not the Go versions
// Note: infrastructure namespaces are still excluded for "*" values unless a qualifying glob pattern is specified. | ||
// | ||
// +kubebuilder:validation:Optional | ||
Includes []NamespaceContainerSpec `json:"includes,omitempty"` |
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.
Should add listType
to this, either atomic or map, and if map, add listMapKey
for the key field within the struct
// Supports glob patterns and presumes "*" if omitted. | ||
// | ||
// +kubebuilder:validation:Optional | ||
Namespace string `json:"namespace,omitempty"` |
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.
Generally good to add length limits and specific character sets to strings where possible
// See the `secret` field for more details. | ||
// | ||
// +kubebuilder:validation:Required | ||
URL string `json:"url"` |
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.
You should add a length limit to this, and use CEL to validate that it is a valid URL
|
||
// BaseOutputTuningSpec tuning parameters for an output | ||
type BaseOutputTuningSpec struct { | ||
Delivery DeliveryMode `json:"delivery,omitempty"` |
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.
Missing godoc, also not marked as optional or required
// MaxWrite limits the maximum payload in terms of bytes of a single "send" to the output. | ||
// | ||
// +kubebuilder:validation:Optional | ||
MaxWrite *resource.Quantity `json:"maxWrite,omitempty"` |
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.
CEL can now validate quantities as well
// Headers specify optional headers to be sent with the request | ||
// | ||
// +kubebuilder:validation:Optional | ||
Headers map[string]string `json:"headers,omitempty"` |
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.
Generally it's best to avoid maps in CRDs, they make it hard to make structural schemas. Create instead a list with a struct type with a key and value
headers:
- name: ...
values: []
// Emergency Alert Critical Error Warning Notice Informational Debug | ||
// | ||
// +kubebuilder:validation:Optional | ||
// TODO: Add regex validation |
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.
Regex, CEL, enum? CEL in general can provide more flexibility
Description
This PR:
Links
cc @alanconway @periklis @xperimental @cahartma @Clee2691 @vparfonov
/hold