Logs Explore: logsdrilldown authorizer permissions, rtkq (#114320)

* Logs Explore: logsdrilldown app platform authorizer permissions, rtkq
---------

Co-authored-by: Austin Pond <austin.pond@grafana.com>
This commit is contained in:
Liza Detrick
2025-12-02 09:07:36 -08:00
committed by GitHub
co-authored by Austin Pond
parent 68b02c2283
commit a112c6c169
32 changed files with 5161 additions and 11 deletions
+1
View File
@@ -750,6 +750,7 @@ i18next.config.ts @grafana/grafana-frontend-platform
/packages/grafana-api-clients/src/clients/rtkq/dashboard/ @grafana/dashboards-squad
/packages/grafana-api-clients/src/clients/rtkq/folder/ @grafana/grafana-search-navigate-organise
/packages/grafana-api-clients/src/clients/rtkq/iam/ @grafana/access-squad @grafana/identity-squad
/packages/grafana-api-clients/src/clients/rtkq/logsdrilldown/ @grafana/observability-logs
/packages/grafana-api-clients/src/clients/rtkq/preferences/ @grafana/plugins-platform-frontend
/packages/grafana-api-clients/src/clients/rtkq/provisioning/ @grafana/grafana-git-ui-sync-team
/packages/grafana-api-clients/src/clients/rtkq/shorturl/ @grafana/sharing-squad
+17 -4
View File
@@ -1,10 +1,23 @@
package kinds
logsdrilldownv0alpha1: {
LogsDrilldownSpecv1alpha1: {
defaultFields: [...string] | *[]
prettifyJSON: bool
wrapLogMessage: bool
interceptDismissed: bool
}
logsdrilldownv1alpha1: {
kind: "LogsDrilldown" // note: must be uppercase
schema: {
spec: {
defaultFields: [...string] | *[]
}
spec: LogsDrilldownSpecv1alpha1
}
}
logsdrilldownDefaultsv1alpha1: {
kind: "LogsDrilldownDefaults" // note: must be uppercase
pluralName: "LogsDrilldownDefaults"
schema: {
spec: LogsDrilldownSpecv1alpha1
}
}
+2 -2
View File
@@ -35,12 +35,12 @@ manifest: {
// It includes kinds which the v1alpha1 API serves, and (future) custom routes served globally from the v1alpha1 version.
v1alpha1: {
// kinds is the list of kinds served by this version
kinds: [logsdrilldownv0alpha1]
kinds: [logsdrilldownv1alpha1, logsdrilldownDefaultsv1alpha1]
// [OPTIONAL]
// served indicates whether this particular version is served by the API server.
// served should be set to false before a version is removed from the manifest entirely.
// served defaults to true if not present.
served: true
served: true
// [OPTIONAL]
// Codegen is a trait that tells the grafana-app-sdk, or other code generation tooling, how to process this kind.
// If not present, default values within the codegen trait are used.
@@ -0,0 +1,15 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1alpha1
// +k8s:openapi-gen=true
type GetDefaultFields struct {
DefaultFields []string `json:"defaultFields"`
}
// NewGetDefaultFields creates a new GetDefaultFields object.
func NewGetDefaultFields() *GetDefaultFields {
return &GetDefaultFields{
DefaultFields: []string{},
}
}
@@ -4,7 +4,10 @@ package v1alpha1
// +k8s:openapi-gen=true
type LogsDrilldownSpec struct {
DefaultFields []string `json:"defaultFields"`
DefaultFields []string `json:"defaultFields"`
PrettifyJSON bool `json:"prettifyJSON"`
WrapLogMessage bool `json:"wrapLogMessage"`
InterceptDismissed bool `json:"interceptDismissed"`
}
// NewLogsDrilldownSpec creates a new LogsDrilldownSpec object.
@@ -0,0 +1,99 @@
package v1alpha1
import (
"context"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type LogsDrilldownDefaultsClient struct {
client *resource.TypedClient[*LogsDrilldownDefaults, *LogsDrilldownDefaultsList]
}
func NewLogsDrilldownDefaultsClient(client resource.Client) *LogsDrilldownDefaultsClient {
return &LogsDrilldownDefaultsClient{
client: resource.NewTypedClient[*LogsDrilldownDefaults, *LogsDrilldownDefaultsList](client, LogsDrilldownDefaultsKind()),
}
}
func NewLogsDrilldownDefaultsClientFromGenerator(generator resource.ClientGenerator) (*LogsDrilldownDefaultsClient, error) {
c, err := generator.ClientFor(LogsDrilldownDefaultsKind())
if err != nil {
return nil, err
}
return NewLogsDrilldownDefaultsClient(c), nil
}
func (c *LogsDrilldownDefaultsClient) Get(ctx context.Context, identifier resource.Identifier) (*LogsDrilldownDefaults, error) {
return c.client.Get(ctx, identifier)
}
func (c *LogsDrilldownDefaultsClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*LogsDrilldownDefaultsList, error) {
return c.client.List(ctx, namespace, opts)
}
func (c *LogsDrilldownDefaultsClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*LogsDrilldownDefaultsList, error) {
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
for resp.GetContinue() != "" {
page, err := c.client.List(ctx, namespace, resource.ListOptions{
Continue: resp.GetContinue(),
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
resp.SetContinue(page.GetContinue())
resp.SetResourceVersion(page.GetResourceVersion())
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
}
return resp, nil
}
func (c *LogsDrilldownDefaultsClient) Create(ctx context.Context, obj *LogsDrilldownDefaults, opts resource.CreateOptions) (*LogsDrilldownDefaults, error) {
// Make sure apiVersion and kind are set
obj.APIVersion = GroupVersion.Identifier()
obj.Kind = LogsDrilldownDefaultsKind().Kind()
return c.client.Create(ctx, obj, opts)
}
func (c *LogsDrilldownDefaultsClient) Update(ctx context.Context, obj *LogsDrilldownDefaults, opts resource.UpdateOptions) (*LogsDrilldownDefaults, error) {
return c.client.Update(ctx, obj, opts)
}
func (c *LogsDrilldownDefaultsClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*LogsDrilldownDefaults, error) {
return c.client.Patch(ctx, identifier, req, opts)
}
func (c *LogsDrilldownDefaultsClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus LogsDrilldownDefaultsStatus, opts resource.UpdateOptions) (*LogsDrilldownDefaults, error) {
return c.client.Update(ctx, &LogsDrilldownDefaults{
TypeMeta: metav1.TypeMeta{
Kind: LogsDrilldownDefaultsKind().Kind(),
APIVersion: GroupVersion.Identifier(),
},
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: opts.ResourceVersion,
Namespace: identifier.Namespace,
Name: identifier.Name,
},
Status: newStatus,
}, resource.UpdateOptions{
Subresource: "status",
ResourceVersion: opts.ResourceVersion,
})
}
func (c *LogsDrilldownDefaultsClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
return c.client.Delete(ctx, identifier, opts)
}
@@ -0,0 +1,28 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v1alpha1
import (
"encoding/json"
"io"
"github.com/grafana/grafana-app-sdk/resource"
)
// LogsDrilldownDefaultsJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
type LogsDrilldownDefaultsJSONCodec struct{}
// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
func (*LogsDrilldownDefaultsJSONCodec) Read(reader io.Reader, into resource.Object) error {
return json.NewDecoder(reader).Decode(into)
}
// Write writes JSON-encoded bytes into `writer` marshaled from `from`
func (*LogsDrilldownDefaultsJSONCodec) Write(writer io.Writer, from resource.Object) error {
return json.NewEncoder(writer).Encode(from)
}
// Interface compliance checks
var _ resource.Codec = &LogsDrilldownDefaultsJSONCodec{}
@@ -0,0 +1,31 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1alpha1
import (
time "time"
)
// metadata contains embedded CommonMetadata and can be extended with custom string fields
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
// without external reference as using the CommonMetadata reference breaks thema codegen.
type LogsDrilldownDefaultsMetadata struct {
UpdateTimestamp time.Time `json:"updateTimestamp"`
CreatedBy string `json:"createdBy"`
Uid string `json:"uid"`
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
ResourceVersion string `json:"resourceVersion"`
Generation int64 `json:"generation"`
UpdatedBy string `json:"updatedBy"`
Labels map[string]string `json:"labels"`
}
// NewLogsDrilldownDefaultsMetadata creates a new LogsDrilldownDefaultsMetadata object.
func NewLogsDrilldownDefaultsMetadata() *LogsDrilldownDefaultsMetadata {
return &LogsDrilldownDefaultsMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
}
@@ -0,0 +1,319 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v1alpha1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"time"
)
// +k8s:openapi-gen=true
type LogsDrilldownDefaults struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
// Spec is the spec of the LogsDrilldownDefaults
Spec LogsDrilldownDefaultsSpec `json:"spec" yaml:"spec"`
Status LogsDrilldownDefaultsStatus `json:"status" yaml:"status"`
}
func (o *LogsDrilldownDefaults) GetSpec() any {
return o.Spec
}
func (o *LogsDrilldownDefaults) SetSpec(spec any) error {
cast, ok := spec.(LogsDrilldownDefaultsSpec)
if !ok {
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
}
o.Spec = cast
return nil
}
func (o *LogsDrilldownDefaults) GetSubresources() map[string]any {
return map[string]any{
"status": o.Status,
}
}
func (o *LogsDrilldownDefaults) GetSubresource(name string) (any, bool) {
switch name {
case "status":
return o.Status, true
default:
return nil, false
}
}
func (o *LogsDrilldownDefaults) SetSubresource(name string, value any) error {
switch name {
case "status":
cast, ok := value.(LogsDrilldownDefaultsStatus)
if !ok {
return fmt.Errorf("cannot set status type %#v, not of type LogsDrilldownDefaultsStatus", value)
}
o.Status = cast
return nil
default:
return fmt.Errorf("subresource '%s' does not exist", name)
}
}
func (o *LogsDrilldownDefaults) GetStaticMetadata() resource.StaticMetadata {
gvk := o.GroupVersionKind()
return resource.StaticMetadata{
Name: o.ObjectMeta.Name,
Namespace: o.ObjectMeta.Namespace,
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
}
}
func (o *LogsDrilldownDefaults) SetStaticMetadata(metadata resource.StaticMetadata) {
o.Name = metadata.Name
o.Namespace = metadata.Namespace
o.SetGroupVersionKind(schema.GroupVersionKind{
Group: metadata.Group,
Version: metadata.Version,
Kind: metadata.Kind,
})
}
func (o *LogsDrilldownDefaults) GetCommonMetadata() resource.CommonMetadata {
dt := o.DeletionTimestamp
var deletionTimestamp *time.Time
if dt != nil {
deletionTimestamp = &dt.Time
}
// Legacy ExtraFields support
extraFields := make(map[string]any)
if o.Annotations != nil {
extraFields["annotations"] = o.Annotations
}
if o.ManagedFields != nil {
extraFields["managedFields"] = o.ManagedFields
}
if o.OwnerReferences != nil {
extraFields["ownerReferences"] = o.OwnerReferences
}
return resource.CommonMetadata{
UID: string(o.UID),
ResourceVersion: o.ResourceVersion,
Generation: o.Generation,
Labels: o.Labels,
CreationTimestamp: o.CreationTimestamp.Time,
DeletionTimestamp: deletionTimestamp,
Finalizers: o.Finalizers,
UpdateTimestamp: o.GetUpdateTimestamp(),
CreatedBy: o.GetCreatedBy(),
UpdatedBy: o.GetUpdatedBy(),
ExtraFields: extraFields,
}
}
func (o *LogsDrilldownDefaults) SetCommonMetadata(metadata resource.CommonMetadata) {
o.UID = types.UID(metadata.UID)
o.ResourceVersion = metadata.ResourceVersion
o.Generation = metadata.Generation
o.Labels = metadata.Labels
o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
if metadata.DeletionTimestamp != nil {
dt := metav1.NewTime(*metadata.DeletionTimestamp)
o.DeletionTimestamp = &dt
} else {
o.DeletionTimestamp = nil
}
o.Finalizers = metadata.Finalizers
if o.Annotations == nil {
o.Annotations = make(map[string]string)
}
if !metadata.UpdateTimestamp.IsZero() {
o.SetUpdateTimestamp(metadata.UpdateTimestamp)
}
if metadata.CreatedBy != "" {
o.SetCreatedBy(metadata.CreatedBy)
}
if metadata.UpdatedBy != "" {
o.SetUpdatedBy(metadata.UpdatedBy)
}
// Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
if metadata.ExtraFields != nil {
if annotations, ok := metadata.ExtraFields["annotations"]; ok {
if cast, ok := annotations.(map[string]string); ok {
o.Annotations = cast
}
}
if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
o.ManagedFields = cast
}
}
if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
o.OwnerReferences = cast
}
}
}
}
func (o *LogsDrilldownDefaults) GetCreatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/createdBy"]
}
func (o *LogsDrilldownDefaults) SetCreatedBy(createdBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
}
func (o *LogsDrilldownDefaults) GetUpdateTimestamp() time.Time {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
return parsed
}
func (o *LogsDrilldownDefaults) SetUpdateTimestamp(updateTimestamp time.Time) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
}
func (o *LogsDrilldownDefaults) GetUpdatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
}
func (o *LogsDrilldownDefaults) SetUpdatedBy(updatedBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
}
func (o *LogsDrilldownDefaults) Copy() resource.Object {
return resource.CopyObject(o)
}
func (o *LogsDrilldownDefaults) DeepCopyObject() runtime.Object {
return o.Copy()
}
func (o *LogsDrilldownDefaults) DeepCopy() *LogsDrilldownDefaults {
cpy := &LogsDrilldownDefaults{}
o.DeepCopyInto(cpy)
return cpy
}
func (o *LogsDrilldownDefaults) DeepCopyInto(dst *LogsDrilldownDefaults) {
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
dst.TypeMeta.Kind = o.TypeMeta.Kind
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
o.Spec.DeepCopyInto(&dst.Spec)
o.Status.DeepCopyInto(&dst.Status)
}
// Interface compliance compile-time check
var _ resource.Object = &LogsDrilldownDefaults{}
// +k8s:openapi-gen=true
type LogsDrilldownDefaultsList struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata" yaml:"metadata"`
Items []LogsDrilldownDefaults `json:"items" yaml:"items"`
}
func (o *LogsDrilldownDefaultsList) DeepCopyObject() runtime.Object {
return o.Copy()
}
func (o *LogsDrilldownDefaultsList) Copy() resource.ListObject {
cpy := &LogsDrilldownDefaultsList{
TypeMeta: o.TypeMeta,
Items: make([]LogsDrilldownDefaults, len(o.Items)),
}
o.ListMeta.DeepCopyInto(&cpy.ListMeta)
for i := 0; i < len(o.Items); i++ {
if item, ok := o.Items[i].Copy().(*LogsDrilldownDefaults); ok {
cpy.Items[i] = *item
}
}
return cpy
}
func (o *LogsDrilldownDefaultsList) GetItems() []resource.Object {
items := make([]resource.Object, len(o.Items))
for i := 0; i < len(o.Items); i++ {
items[i] = &o.Items[i]
}
return items
}
func (o *LogsDrilldownDefaultsList) SetItems(items []resource.Object) {
o.Items = make([]LogsDrilldownDefaults, len(items))
for i := 0; i < len(items); i++ {
o.Items[i] = *items[i].(*LogsDrilldownDefaults)
}
}
func (o *LogsDrilldownDefaultsList) DeepCopy() *LogsDrilldownDefaultsList {
cpy := &LogsDrilldownDefaultsList{}
o.DeepCopyInto(cpy)
return cpy
}
func (o *LogsDrilldownDefaultsList) DeepCopyInto(dst *LogsDrilldownDefaultsList) {
resource.CopyObjectInto(dst, o)
}
// Interface compliance compile-time check
var _ resource.ListObject = &LogsDrilldownDefaultsList{}
// Copy methods for all subresource types
// DeepCopy creates a full deep copy of Spec
func (s *LogsDrilldownDefaultsSpec) DeepCopy() *LogsDrilldownDefaultsSpec {
cpy := &LogsDrilldownDefaultsSpec{}
s.DeepCopyInto(cpy)
return cpy
}
// DeepCopyInto deep copies Spec into another Spec object
func (s *LogsDrilldownDefaultsSpec) DeepCopyInto(dst *LogsDrilldownDefaultsSpec) {
resource.CopyObjectInto(dst, s)
}
// DeepCopy creates a full deep copy of LogsDrilldownDefaultsStatus
func (s *LogsDrilldownDefaultsStatus) DeepCopy() *LogsDrilldownDefaultsStatus {
cpy := &LogsDrilldownDefaultsStatus{}
s.DeepCopyInto(cpy)
return cpy
}
// DeepCopyInto deep copies LogsDrilldownDefaultsStatus into another LogsDrilldownDefaultsStatus object
func (s *LogsDrilldownDefaultsStatus) DeepCopyInto(dst *LogsDrilldownDefaultsStatus) {
resource.CopyObjectInto(dst, s)
}
@@ -0,0 +1,34 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v1alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaLogsDrilldownDefaults = resource.NewSimpleSchema("logsdrilldown.grafana.app", "v1alpha1", &LogsDrilldownDefaults{}, &LogsDrilldownDefaultsList{}, resource.WithKind("LogsDrilldownDefaults"),
resource.WithPlural("logsdrilldowndefaults"), resource.WithScope(resource.NamespacedScope))
kindLogsDrilldownDefaults = resource.Kind{
Schema: schemaLogsDrilldownDefaults,
Codecs: map[resource.KindEncoding]resource.Codec{
resource.KindEncodingJSON: &LogsDrilldownDefaultsJSONCodec{},
},
}
)
// Kind returns a resource.Kind for this Schema with a JSON codec
func LogsDrilldownDefaultsKind() resource.Kind {
return kindLogsDrilldownDefaults
}
// Schema returns a resource.SimpleSchema representation of LogsDrilldownDefaults
func LogsDrilldownDefaultsSchema() *resource.SimpleSchema {
return schemaLogsDrilldownDefaults
}
// Interface compliance checks
var _ resource.Schema = kindLogsDrilldownDefaults
@@ -0,0 +1,18 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1alpha1
// +k8s:openapi-gen=true
type LogsDrilldownDefaultsSpec struct {
DefaultFields []string `json:"defaultFields"`
PrettifyJSON bool `json:"prettifyJSON"`
WrapLogMessage bool `json:"wrapLogMessage"`
InterceptDismissed bool `json:"interceptDismissed"`
}
// NewLogsDrilldownDefaultsSpec creates a new LogsDrilldownDefaultsSpec object.
func NewLogsDrilldownDefaultsSpec() *LogsDrilldownDefaultsSpec {
return &LogsDrilldownDefaultsSpec{
DefaultFields: []string{},
}
}
@@ -0,0 +1,44 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1alpha1
// +k8s:openapi-gen=true
type LogsDrilldownDefaultsstatusOperatorState struct {
// lastEvaluation is the ResourceVersion last evaluated
LastEvaluation string `json:"lastEvaluation"`
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
State LogsDrilldownDefaultsStatusOperatorStateState `json:"state"`
// descriptiveState is an optional more descriptive state field which has no requirements on format
DescriptiveState *string `json:"descriptiveState,omitempty"`
// details contains any extra information that is operator-specific
Details map[string]interface{} `json:"details,omitempty"`
}
// NewLogsDrilldownDefaultsstatusOperatorState creates a new LogsDrilldownDefaultsstatusOperatorState object.
func NewLogsDrilldownDefaultsstatusOperatorState() *LogsDrilldownDefaultsstatusOperatorState {
return &LogsDrilldownDefaultsstatusOperatorState{}
}
// +k8s:openapi-gen=true
type LogsDrilldownDefaultsStatus struct {
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
OperatorStates map[string]LogsDrilldownDefaultsstatusOperatorState `json:"operatorStates,omitempty"`
// additionalFields is reserved for future use
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
}
// NewLogsDrilldownDefaultsStatus creates a new LogsDrilldownDefaultsStatus object.
func NewLogsDrilldownDefaultsStatus() *LogsDrilldownDefaultsStatus {
return &LogsDrilldownDefaultsStatus{}
}
// +k8s:openapi-gen=true
type LogsDrilldownDefaultsStatusOperatorStateState string
const (
LogsDrilldownDefaultsStatusOperatorStateStateSuccess LogsDrilldownDefaultsStatusOperatorStateState = "success"
LogsDrilldownDefaultsStatusOperatorStateStateInProgress LogsDrilldownDefaultsStatusOperatorStateState = "in_progress"
LogsDrilldownDefaultsStatusOperatorStateStateFailed LogsDrilldownDefaultsStatusOperatorStateState = "failed"
)
@@ -0,0 +1,14 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1alpha1
type ReplaceDefaultFieldsRequestBody struct {
DefaultFields []string `json:"defaultFields"`
}
// NewReplaceDefaultFieldsRequestBody creates a new ReplaceDefaultFieldsRequestBody object.
func NewReplaceDefaultFieldsRequestBody() *ReplaceDefaultFieldsRequestBody {
return &ReplaceDefaultFieldsRequestBody{
DefaultFields: []string{},
}
}
@@ -0,0 +1,15 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1alpha1
// +k8s:openapi-gen=true
type ReplaceDefaultFields struct {
DefaultFields []string `json:"defaultFields"`
}
// NewReplaceDefaultFields creates a new ReplaceDefaultFields object.
func NewReplaceDefaultFields() *ReplaceDefaultFields {
return &ReplaceDefaultFields{
DefaultFields: []string{},
}
}
+18 -4
View File
@@ -14,14 +14,18 @@ import (
"github.com/grafana/grafana-app-sdk/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kube-openapi/pkg/spec3"
"k8s.io/kube-openapi/pkg/validation/spec"
v1alpha1 "github.com/grafana/grafana/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1"
)
var (
rawSchemaLogsDrilldownv1alpha1 = []byte(`{"LogsDrilldown":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"defaultFields":{"items":{"type":"string"},"type":"array"}},"required":["defaultFields"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaLogsDrilldownv1alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaLogsDrilldownv1alpha1, &versionSchemaLogsDrilldownv1alpha1)
rawSchemaLogsDrilldownv1alpha1 = []byte(`{"LogsDrilldown":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"defaultFields":{"items":{"type":"string"},"type":"array"},"interceptDismissed":{"type":"boolean"},"prettifyJSON":{"type":"boolean"},"wrapLogMessage":{"type":"boolean"}},"required":["defaultFields","prettifyJSON","wrapLogMessage","interceptDismissed"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaLogsDrilldownv1alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaLogsDrilldownv1alpha1, &versionSchemaLogsDrilldownv1alpha1)
rawSchemaLogsDrilldownDefaultsv1alpha1 = []byte(`{"LogsDrilldownDefaults":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"defaultFields":{"items":{"type":"string"},"type":"array"},"interceptDismissed":{"type":"boolean"},"prettifyJSON":{"type":"boolean"},"wrapLogMessage":{"type":"boolean"}},"required":["defaultFields","prettifyJSON","wrapLogMessage","interceptDismissed"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaLogsDrilldownDefaultsv1alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaLogsDrilldownDefaultsv1alpha1, &versionSchemaLogsDrilldownDefaultsv1alpha1)
)
var appManifestData = app.ManifestData{
@@ -40,10 +44,19 @@ var appManifestData = app.ManifestData{
Conversion: false,
Schema: &versionSchemaLogsDrilldownv1alpha1,
},
{
Kind: "LogsDrilldownDefaults",
Plural: "LogsDrilldownDefaults",
Scope: "Namespaced",
Conversion: false,
Schema: &versionSchemaLogsDrilldownDefaultsv1alpha1,
},
},
Routes: app.ManifestVersionRoutes{
Namespaced: map[string]spec3.PathProps{},
Cluster: map[string]spec3.PathProps{},
Schemas: map[string]spec.Schema{},
},
},
},
@@ -58,7 +71,8 @@ func RemoteManifest() app.Manifest {
}
var kindVersionToGoType = map[string]resource.Kind{
"LogsDrilldown/v1alpha1": v1alpha1.LogsDrilldownKind(),
"LogsDrilldown/v1alpha1": v1alpha1.LogsDrilldownKind(),
"LogsDrilldownDefaults/v1alpha1": v1alpha1.LogsDrilldownDefaultsKind(),
}
// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
+3
View File
@@ -28,6 +28,9 @@ func New(cfg app.Config) (app.App, error) {
{
Kind: logsdrilldownv1alpha1.LogsDrilldownKind(),
},
{
Kind: logsdrilldownv1alpha1.LogsDrilldownDefaultsKind(),
},
},
}
@@ -2,9 +2,15 @@
export interface Spec {
defaultFields: string[];
prettifyJSON: boolean;
wrapLogMessage: boolean;
interceptDismissed: boolean;
}
export const defaultSpec = (): Spec => ({
defaultFields: [],
prettifyJSON: false,
wrapLogMessage: false,
interceptDismissed: false,
});
@@ -0,0 +1,49 @@
/*
* This file was generated by grafana-app-sdk. DO NOT EDIT.
*/
import { Spec } from './types.spec.gen';
import { Status } from './types.status.gen';
export interface Metadata {
name: string;
namespace: string;
generateName?: string;
selfLink?: string;
uid?: string;
resourceVersion?: string;
generation?: number;
creationTimestamp?: string;
deletionTimestamp?: string;
deletionGracePeriodSeconds?: number;
labels?: Record<string, string>;
annotations?: Record<string, string>;
ownerReferences?: OwnerReference[];
finalizers?: string[];
managedFields?: ManagedFieldsEntry[];
}
export interface OwnerReference {
apiVersion: string;
kind: string;
name: string;
uid: string;
controller?: boolean;
blockOwnerDeletion?: boolean;
}
export interface ManagedFieldsEntry {
manager?: string;
operation?: string;
apiVersion?: string;
time?: string;
fieldsType?: string;
subresource?: string;
}
export interface LogsDrilldownDefaults {
kind: string;
apiVersion: string;
metadata: Metadata;
spec: Spec;
status: Status;
}
@@ -0,0 +1,30 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
// metadata contains embedded CommonMetadata and can be extended with custom string fields
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
// without external reference as using the CommonMetadata reference breaks thema codegen.
export interface Metadata {
updateTimestamp: string;
createdBy: string;
uid: string;
creationTimestamp: string;
deletionTimestamp?: string;
finalizers: string[];
resourceVersion: string;
generation: number;
updatedBy: string;
labels: Record<string, string>;
}
export const defaultMetadata = (): Metadata => ({
updateTimestamp: "",
createdBy: "",
uid: "",
creationTimestamp: "",
finalizers: [],
resourceVersion: "",
generation: 0,
updatedBy: "",
labels: {},
});
@@ -0,0 +1,16 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
export interface Spec {
defaultFields: string[];
prettifyJSON: boolean;
wrapLogMessage: boolean;
interceptDismissed: boolean;
}
export const defaultSpec = (): Spec => ({
defaultFields: [],
prettifyJSON: false,
wrapLogMessage: false,
interceptDismissed: false,
});
@@ -0,0 +1,30 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
export interface OperatorState {
// lastEvaluation is the ResourceVersion last evaluated
lastEvaluation: string;
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
state: "success" | "in_progress" | "failed";
// descriptiveState is an optional more descriptive state field which has no requirements on format
descriptiveState?: string;
// details contains any extra information that is operator-specific
details?: Record<string, any>;
}
export const defaultOperatorState = (): OperatorState => ({
lastEvaluation: "",
state: "success",
});
export interface Status {
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
operatorStates?: Record<string, OperatorState>;
// additionalFields is reserved for future use
additionalFields?: Record<string, any>;
}
export const defaultStatus = (): Status => ({
});
@@ -87,6 +87,10 @@
"./rtkq/historian.alerting/v0alpha1": {
"import": "./src/clients/rtkq/historian.alerting/v0alpha1/index.ts",
"require": "./src/clients/rtkq/historian.alerting/v0alpha1/index.ts"
},
"./rtkq/logsdrilldown/v1alpha1": {
"import": "./src/clients/rtkq/logsdrilldown/v1alpha1/index.ts",
"require": "./src/clients/rtkq/logsdrilldown/v1alpha1/index.ts"
}
},
"publishConfig": {
@@ -8,6 +8,7 @@ import { generatedAPI as dashboardAPIv0alpha1 } from './dashboard/v0alpha1';
import { generatedAPI as folderAPIv1beta1 } from './folder/v1beta1';
import { generatedAPI as historianAlertingAPIv0alpha1 } from './historian.alerting/v0alpha1';
import { generatedAPI as iamAPIv0alpha1 } from './iam/v0alpha1';
import { generatedAPI as logsdrilldownAPIv1alpha1 } from './logsdrilldown/v1alpha1';
import { generatedAPI as migrateToCloudAPI } from './migrate-to-cloud';
import { generatedAPI as playlistAPIv0alpha1 } from './playlist/v0alpha1';
import { generatedAPI as preferencesUserAPI } from './preferences/user';
@@ -33,6 +34,7 @@ export const allMiddleware = [
correlationsAPIv0alpha1.middleware,
legacyUserAPI.middleware,
historianAlertingAPIv0alpha1.middleware,
logsdrilldownAPIv1alpha1.middleware,
// PLOP_INJECT_MIDDLEWARE
] as const;
@@ -52,6 +54,7 @@ export const allReducers = {
[correlationsAPIv0alpha1.reducerPath]: correlationsAPIv0alpha1.reducer,
[legacyUserAPI.reducerPath]: legacyUserAPI.reducer,
[historianAlertingAPIv0alpha1.reducerPath]: historianAlertingAPIv0alpha1.reducer,
[logsdrilldownAPIv1alpha1.reducerPath]: logsdrilldownAPIv1alpha1.reducer,
// PLOP_INJECT_REDUCER
};
@@ -0,0 +1,16 @@
import { createApi } from '@reduxjs/toolkit/query/react';
import { getAPIBaseURL } from '../../../../utils/utils';
import { createBaseQuery } from '../../createBaseQuery';
export const API_GROUP = 'logsdrilldown.grafana.app' as const;
export const API_VERSION = 'v1alpha1' as const;
export const BASE_URL = getAPIBaseURL(API_GROUP, API_VERSION);
export const api = createApi({
reducerPath: 'logsdrilldownAPIv1alpha1',
baseQuery: createBaseQuery({
baseURL: BASE_URL,
}),
endpoints: () => ({}),
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
export { BASE_URL, API_GROUP, API_VERSION } from './baseAPI';
import { generatedAPI as rawAPI } from './endpoints.gen';
export * from './endpoints.gen';
export const generatedAPI = rawAPI.enhanceEndpoints({});
@@ -109,6 +109,7 @@ const config: ConfigFile = {
...createAPIConfig('provisioning', 'v0alpha1'),
...createAPIConfig('shorturl', 'v1beta1'),
...createAPIConfig('historian.alerting', 'v0alpha1'),
...createAPIConfig('logsdrilldown', 'v1alpha1'),
// PLOP_INJECT_API_CLIENT - Used by the API client generator
},
};
@@ -0,0 +1,78 @@
package logsdrilldown
import (
"context"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
// GetAuthorizer returns an authorizer for all kinds managed by the logsdrilldown app.
func GetAuthorizer() authorizer.Authorizer {
return authorizer.AuthorizerFunc(func(
ctx context.Context, attr authorizer.Attributes,
) (authorized authorizer.Decision, reason string, err error) {
if !attr.IsResourceRequest() {
return authorizer.DecisionNoOpinion, "", nil
}
// require a user
u, err := identity.GetRequester(ctx)
if err != nil {
return authorizer.DecisionDeny, "valid user is required", err
}
// Auth handling for LogsDrilldownDefaults resource
if attr.GetResource() == "logsdrilldowndefaults" {
// Allow list and get for everyone
if attr.GetVerb() == "list" || attr.GetVerb() == "get" {
return authorizer.DecisionAllow, "", nil
}
// Only allow admins to update (create, update, patch, delete)
if u.GetIsGrafanaAdmin() {
return authorizer.DecisionAllow, "", nil
}
// Deny all other operations for non-admins
return authorizer.DecisionDeny, "admin access required", nil
}
// check if is admin
if u.GetIsGrafanaAdmin() {
return authorizer.DecisionAllow, "", nil
}
p := u.GetPermissions()
if len(p) == 0 {
return authorizer.DecisionDeny, "no permissions", nil
}
_, ok := p[accesscontrol.ActionDatasourcesExplore]
if !ok {
// defer to the default authorizer if datasources:explore is not present
return authorizer.DecisionNoOpinion, "", nil
}
switch attr.GetVerb() {
case "list":
// Allow everyone to list logsdrilldowns
return authorizer.DecisionAllow, "", nil
case "get":
// Allow everyone to get individual logsdrilldowns
return authorizer.DecisionAllow, "", nil
case "create":
// Create requests are validated later since we don't have access to the resource name
return authorizer.DecisionAllow, "", nil
case "delete", "patch", "update":
// Only allow the user to access their own settings
if !compareResourceNameAndUserUID(attr.GetName(), u) {
return authorizer.DecisionDeny, "forbidden", nil
}
return authorizer.DecisionAllow, "", nil
default:
// Forbid the rest
return authorizer.DecisionDeny, "forbidden", nil
}
})
}
@@ -1,6 +1,7 @@
package logsdrilldown
import (
"k8s.io/apiserver/pkg/authorization/authorizer"
restclient "k8s.io/client-go/rest"
"github.com/grafana/grafana-app-sdk/app"
@@ -21,6 +22,10 @@ type LogsDrilldownAppInstaller struct {
cfg *setting.Cfg
}
func (l *LogsDrilldownAppInstaller) GetAuthorizer() authorizer.Authorizer {
return GetAuthorizer()
}
func RegisterAppInstaller(
cfg *setting.Cfg,
features featuremgmt.FeatureToggles,
@@ -0,0 +1,40 @@
package logsdrilldown
import (
"errors"
"strings"
"github.com/grafana/grafana/pkg/apimachinery/identity"
)
func compareResourceNameAndUserUID(name string, u identity.Requester) bool {
parsedName, err := parseName(name)
if err != nil {
return false
}
// u.GetUID() returns user:<user_uid> so we need to remove the user: prefix
userUID := strings.Split(u.GetUID(), ":")
if len(userUID) != 2 {
return false
}
return parsedName.UID == userUID[1]
}
type storageObjectName struct {
Service string
UID string
}
func parseName(name string) (*storageObjectName, error) {
vals := strings.Split(name, ":")
if len(vals) != 2 {
return nil, errors.New("name must be in the format <service>:<user_uid>")
}
return &storageObjectName{
Service: vals[0],
UID: vals[1],
}, nil
}
File diff suppressed because it is too large Load Diff
+4
View File
@@ -35,6 +35,7 @@ func TestIntegrationOpenAPIs(t *testing.T) {
featuremgmt.FlagKubernetesShortURLs,
featuremgmt.FlagKubernetesCorrelations,
featuremgmt.FlagKubernetesAlertingHistorian,
featuremgmt.FlagKubernetesLogsDrilldown,
},
})
@@ -119,6 +120,9 @@ func TestIntegrationOpenAPIs(t *testing.T) {
}, {
Group: "testdata.datasource.grafana.app",
Version: "v0alpha1",
}, {
Group: "logsdrilldown.grafana.app",
Version: "v1alpha1",
}}
for _, gv := range groups {
VerifyOpenAPISnapshots(t, dir, gv, h)