Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion api/v1alpha1/accesskey_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ type AccessKeyStatus struct {
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason"
// +kubebuilder:printcolumn:name="Key-ID",type="string",JSONPath=".status.accessKeyId",description="Garage access key identifier"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",priority=1
// +kubebuilder:printcolumn:name="Secret",type="string",JSONPath=".status.secretName",priority=1
// AccessKey is the Schema for the accesskeys API
type AccessKey struct {
metav1.TypeMeta `json:",inline"`
Expand Down
8 changes: 7 additions & 1 deletion api/v1alpha1/accesspolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ type AccessPolicyStatus struct {
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason"
// +kubebuilder:printcolumn:name="Bucket",type="string",JSONPath=".spec.bucket"
// +kubebuilder:printcolumn:name="AccessKey",type="string",JSONPath=".spec.accessKey"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",priority=1
// +kubebuilder:printcolumn:name="Read",type="boolean",JSONPath=".spec.permissions.read",priority=1
// +kubebuilder:printcolumn:name="Write",type="boolean",JSONPath=".spec.permissions.write",priority=1
// +kubebuilder:printcolumn:name="Owner",type="boolean",JSONPath=".spec.permissions.owner",priority=1
// AccessPolicy is the Schema for the accesspolicies API
type AccessPolicy struct {
metav1.TypeMeta `json:",inline"`
Expand Down
7 changes: 6 additions & 1 deletion api/v1alpha1/bucket_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,12 @@ type BucketStatus struct {
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason"
// +kubebuilder:printcolumn:name="Alias",type="string",JSONPath=".status.bucketName",description="Bucket alias as it exists in Garage"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",priority=1
// +kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.bucketId",description="Garage internal bucket identifier",priority=1
// +kubebuilder:printcolumn:name="Max-Size",type="string",JSONPath=".spec.maxSize",priority=1
// +kubebuilder:printcolumn:name="Max-Objects",type="integer",JSONPath=".spec.maxObjects",priority=1

// Bucket is the Schema for the buckets API
type Bucket struct {
Expand Down
12 changes: 12 additions & 0 deletions config/crd/bases/garage.getclustered.net_accesskeys.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,20 @@ spec:
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- description: Garage access key identifier
jsonPath: .status.accessKeyId
name: Key-ID
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
priority: 1
type: string
- jsonPath: .status.secretName
name: Secret
priority: 1
type: string
name: v1alpha1
schema:
Expand Down
22 changes: 22 additions & 0 deletions config/crd/bases/garage.getclustered.net_accesspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,31 @@ spec:
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .spec.bucket
name: Bucket
type: string
- jsonPath: .spec.accessKey
name: AccessKey
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
priority: 1
type: string
- jsonPath: .spec.permissions.read
name: Read
priority: 1
type: boolean
- jsonPath: .spec.permissions.write
name: Write
priority: 1
type: boolean
- jsonPath: .spec.permissions.owner
name: Owner
priority: 1
type: boolean
name: v1alpha1
schema:
openAPIV3Schema:
Expand Down
21 changes: 21 additions & 0 deletions config/crd/bases/garage.getclustered.net_buckets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,30 @@ spec:
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- description: Bucket alias as it exists in Garage
jsonPath: .status.bucketName
name: Alias
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
priority: 1
type: string
- description: Garage internal bucket identifier
jsonPath: .status.bucketId
name: ID
priority: 1
type: string
- jsonPath: .spec.maxSize
name: Max-Size
priority: 1
type: string
- jsonPath: .spec.maxObjects
name: Max-Objects
priority: 1
type: integer
name: v1alpha1
schema:
openAPIV3Schema:
Expand Down
89 changes: 89 additions & 0 deletions internal/controller/printercolumns_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2025.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package controller

import (
"encoding/json"
"strings"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"

garagev1alpha1 "github.com/bmarinov/garage-storage-controller/api/v1alpha1"
)

var _ = Describe("Printer columns", func() {
DescribeTable("the header row",
func(plural, wantPlain, wantWide string) {
gotPlain, gotWide := servedHeaders(plural)

Expect(gotPlain).To(Equal(wantPlain))
Expect(gotWide).To(Equal(wantWide))
},
Entry("kubectl get buckets", "buckets",
"NAME READY ALIAS AGE",
"NAME READY ALIAS AGE REASON ID MAX-SIZE MAX-OBJECTS"),
Entry("kubectl get accesskeys", "accesskeys",
"NAME READY KEY-ID AGE",
"NAME READY KEY-ID AGE REASON SECRET"),
Entry("kubectl get accesspolicies", "accesspolicies",
"NAME READY BUCKET ACCESSKEY AGE",
"NAME READY BUCKET ACCESSKEY AGE REASON READ WRITE OWNER"),
)
})

// servedHeaders retrieves the named resource schema and renders the header row.
func servedHeaders(plural string) (plain, wide string) {
GinkgoHelper()

// envtest installs the manifests from config/crd/bases.
//
// see suite_test.go:
// CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},

tableCfg := rest.CopyConfig(cfg)
tableCfg.GroupVersion = &garagev1alpha1.GroupVersion
tableCfg.APIPath = "/apis"
tableCfg.NegotiatedSerializer = serializer.NewCodecFactory(scheme.Scheme).WithoutConversion()

restClient, err := rest.RESTClientFor(tableCfg)
Expect(err).NotTo(HaveOccurred())

raw, err := restClient.Get().
Resource(plural).
Namespace("default").
SetHeader("Accept", "application/json;as=Table;v=v1;g=meta.k8s.io").
Do(ctx).
Raw()
Expect(err).NotTo(HaveOccurred())

var table metav1.Table
Expect(json.Unmarshal(raw, &table)).To(Succeed())

plainNames := make([]string, 0, len(table.ColumnDefinitions))
wideNames := make([]string, 0, len(table.ColumnDefinitions))
for _, c := range table.ColumnDefinitions {
wideNames = append(wideNames, strings.ToUpper(c.Name))
if c.Priority == 0 {
plainNames = append(plainNames, strings.ToUpper(c.Name))
}
}
return strings.Join(plainNames, " "), strings.Join(wideNames, " ")
}
Loading