Skip to content
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

Merged
merged 1 commit into from
May 7, 2024

Conversation

jcantrill
Copy link
Contributor

Description

This PR:

  • Is an initial implementation of the proposed ClusterLogForwarder.observability.io/v1 API

Links

cc @alanconway @periklis @xperimental @cahartma @Clee2691 @vparfonov

/hold

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Apr 27, 2024
@openshift-ci-robot
Copy link

openshift-ci-robot commented Apr 27, 2024

@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:

Description

This PR:

  • Is an initial implementation of the proposed ClusterLogForwarder.observability.io/v1 API

Links

cc @alanconway @periklis @xperimental @cahartma @Clee2691 @vparfonov

/hold

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.

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 27, 2024
@jcantrill jcantrill added release/6.0 and removed do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels Apr 27, 2024
@jcantrill
Copy link
Contributor Author

/hold

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 27, 2024
Copy link
Contributor

openshift-ci bot commented Apr 27, 2024

[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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 27, 2024
Copy link
Contributor

@periklis periklis left a 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.

api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/output_types.go Outdated Show resolved Hide resolved
listKind: ClusterLogForwarderList
plural: clusterlogforwarders
singular: clusterlogforwarder
scope: Namespaced
Copy link
Contributor

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?

Copy link
Contributor Author

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

@openshift-ci openshift-ci bot added the midstream/Dockerfile A Dockerfile.in sync is needed with midstream label Apr 30, 2024
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 30, 2024
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 1, 2024
Copy link
Contributor

@periklis periklis left a 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:

  1. 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.
  2. Same for // +required, we should use also // +kubebuilder:validation:Required
  3. Do we need to add //+nullable for optional fields at all or is this a legacy thing?
  4. 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?

api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
Comment on lines 70 to 76
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"`
Copy link
Contributor

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?

Copy link
Contributor Author

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 Show resolved Hide resolved
Comment on lines 105 to 128
// +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"`
Copy link
Contributor

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?

Copy link
Contributor Author

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

Comment on lines 131 to 155
// 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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 Show resolved Hide resolved
Comment on lines 184 to 200
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"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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"`

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 2, 2024
Copy link
Contributor

@xperimental xperimental left a 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.

.bingo/operator-sdk.mod Show resolved Hide resolved
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"`
Copy link
Contributor

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).

api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
Comment on lines 251 to 236
// +kubebuilder:object:root=true
// ClusterLogForwarderList contains a list of ClusterLogForwarder
Copy link
Contributor

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:

Suggested change
// +kubebuilder:object:root=true
// ClusterLogForwarderList contains a list of ClusterLogForwarder
// ClusterLogForwarderList contains a list of ClusterLogForwarder
//
// +kubebuilder:object:root=true

Alternative 2:

Suggested change
// +kubebuilder:object:root=true
// ClusterLogForwarderList contains a list of ClusterLogForwarder
//+kubebuilder:object:root=true
// ClusterLogForwarderList contains a list of ClusterLogForwarder

api/observability/v1/conditions.go Show resolved Hide resolved
@jcantrill
Copy link
Contributor Author

  1. Do we need to add //+nullable for optional fields at all or is this a legacy thing?

Can not speak to this. I copied and followed the pattern there so likely a legacy thing

  1. 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?

Probably a legacy thing as well

@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 3, 2024
.bingo/operator-sdk.mod Show resolved Hide resolved
// +kubebuilder:validation:Required
// +listType:=map
// +listMapKey:=name
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Receiver Outputs"
Copy link
Contributor

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"?

Suggested change
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Receiver Outputs"
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Log Outputs"

Copy link
Contributor Author

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"
Copy link
Contributor

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"?

Suggested change
// +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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify to "Log Pipelines"?

Suggested change
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Forwarder Pipelines"
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Log Pipelines"

api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/clusterlogforwarder_types.go Outdated Show resolved Hide resolved
api/observability/v1/filter_types.go Outdated Show resolved Hide resolved
api/observability/v1/output_types.go Outdated Show resolved Hide resolved
@jcantrill
Copy link
Contributor Author

/hold cancel

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 6, 2024
@xperimental
Copy link
Contributor

Looks good to me 👍

@jcantrill
Copy link
Contributor Author

/override ci/prow/e2e-target

Copy link
Contributor

openshift-ci bot commented May 7, 2024

@jcantrill: Overrode contexts on behalf of jcantrill: ci/prow/e2e-target

In response to this:

/override ci/prow/e2e-target

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.

@xperimental
Copy link
Contributor

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label May 7, 2024
Copy link
Contributor

openshift-ci bot commented May 7, 2024

@jcantrill: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-target 98d6fc7 link true /test e2e-target

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.

@openshift-merge-bot openshift-merge-bot bot merged commit 0b4f2e6 into openshift:master May 7, 2024
7 checks passed
@jcantrill jcantrill deleted the log4990 branch May 7, 2024 15:48
Copy link

@JoelSpeed JoelSpeed left a 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

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

Comment on lines +59 to +79
// 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"`

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`.

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"`

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"`

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"`

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"`

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"`

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"`

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. midstream/Dockerfile A Dockerfile.in sync is needed with midstream release/6.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants