Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.

Commit 25c6e64

Browse files
authored
Fix for #3610 All other fluxv2 plugin operations must also support UX request with cluster (#3620)
* switch from json to gob encoding when storing data in redis cache. All tests passing * step 2 * step 3 * step 3
1 parent 04e8109 commit 25c6e64

6 files changed

Lines changed: 100 additions & 57 deletions

File tree

cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ func (c NamespacedResourceWatcherCache) onAddOrModify(add bool, unstructuredObj
363363
log.Errorf("Failed to set value for object with key [%s] in cache due to: %v", key, err)
364364
return err
365365
} else {
366-
log.Infof("Set value for key [%s] in cache", key)
366+
log.V(4).Infof("Set value for key [%s] in cache", key)
367367
}
368368
}
369369
return nil
@@ -456,7 +456,7 @@ func (c NamespacedResourceWatcherCache) listKeys(filters []string) ([]string, er
456456
if err != nil {
457457
return nil, err
458458
}
459-
log.Infof("listKeys: SCAN returned keys: %s, cursor: [%d]", keys, cursor)
459+
log.V(4).Infof("listKeys: SCAN returned keys: %s, cursor: [%d]", keys, cursor)
460460
for _, key := range keys {
461461
redisKeys[key] = struct{}{}
462462
}

cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release_integration_test.go

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ import (
3737
// at this point.
3838
// 3) run './kind-cluster-setup.sh deploy' once prior to these tests
3939

40-
// TODO (gfichtenholt) currently core server's has broken logic inside plugins.go
41-
// createConfigGetterWithParams(...). Refer to my comment in there. I had to make suggested changes
42-
// locally to make these tests pass
43-
4440
const (
4541
// the only repo these tests use so far. This is local copy of the first few entries
4642
// on "https://stefanprodan.github.io/podinfo/index.yaml" as of Sept 10 2021 with the chart
@@ -51,60 +47,72 @@ const (
5147
)
5248

5349
type integrationTestCreateSpec struct {
54-
testName string
55-
repoUrl string
56-
request *corev1.CreateInstalledPackageRequest
57-
expectedDetail *corev1.InstalledPackageDetail
58-
expectedPodPrefix string
50+
testName string
51+
repoUrl string
52+
request *corev1.CreateInstalledPackageRequest
53+
expectedDetail *corev1.InstalledPackageDetail
54+
expectedPodPrefix string
55+
// different from expectedStatusCode due to async nature of install
5956
expectInstallFailure bool
6057
noCleanup bool
61-
unauthorized bool
58+
expectedStatusCode codes.Code
6259
}
6360

6461
func TestKindClusterCreateInstalledPackage(t *testing.T) {
6562
fluxPluginClient := checkEnv(t)
6663

6764
testCases := []integrationTestCreateSpec{
6865
{
69-
testName: "create test (simplest case)",
70-
repoUrl: podinfo_repo_url,
71-
request: create_request_basic,
72-
expectedDetail: expected_detail_basic,
73-
expectedPodPrefix: "@TARGET_NS@-my-podinfo-",
66+
testName: "create test (simplest case)",
67+
repoUrl: podinfo_repo_url,
68+
request: create_request_basic,
69+
expectedDetail: expected_detail_basic,
70+
expectedPodPrefix: "@TARGET_NS@-my-podinfo-",
71+
expectedStatusCode: codes.OK,
7472
},
7573
{
76-
testName: "create package (semver constraint)",
77-
repoUrl: podinfo_repo_url,
78-
request: create_request_semver_constraint,
79-
expectedDetail: expected_detail_semver_constraint,
80-
expectedPodPrefix: "@TARGET_NS@-my-podinfo-2-",
74+
testName: "create package (semver constraint)",
75+
repoUrl: podinfo_repo_url,
76+
request: create_request_semver_constraint,
77+
expectedDetail: expected_detail_semver_constraint,
78+
expectedPodPrefix: "@TARGET_NS@-my-podinfo-2-",
79+
expectedStatusCode: codes.OK,
8180
},
8281
{
83-
testName: "create package (reconcile options)",
84-
repoUrl: podinfo_repo_url,
85-
request: create_request_reconcile_options,
86-
expectedDetail: expected_detail_reconcile_options,
87-
expectedPodPrefix: "@TARGET_NS@-my-podinfo-3-",
82+
testName: "create package (reconcile options)",
83+
repoUrl: podinfo_repo_url,
84+
request: create_request_reconcile_options,
85+
expectedDetail: expected_detail_reconcile_options,
86+
expectedPodPrefix: "@TARGET_NS@-my-podinfo-3-",
87+
expectedStatusCode: codes.OK,
8888
},
8989
{
90-
testName: "create package (with values)",
91-
repoUrl: podinfo_repo_url,
92-
request: create_request_with_values,
93-
expectedDetail: expected_detail_with_values,
94-
expectedPodPrefix: "@TARGET_NS@-my-podinfo-4-",
90+
testName: "create package (with values)",
91+
repoUrl: podinfo_repo_url,
92+
request: create_request_with_values,
93+
expectedDetail: expected_detail_with_values,
94+
expectedPodPrefix: "@TARGET_NS@-my-podinfo-4-",
95+
expectedStatusCode: codes.OK,
9596
},
9697
{
9798
testName: "install fails",
9899
repoUrl: podinfo_repo_url,
99100
request: create_request_install_fails,
100101
expectedDetail: expected_detail_install_fails,
101102
expectInstallFailure: true,
103+
expectedStatusCode: codes.OK,
102104
},
103105
{
104-
testName: "unauthorized",
105-
repoUrl: podinfo_repo_url,
106-
request: create_request_basic,
107-
unauthorized: true,
106+
testName: "unauthorized",
107+
repoUrl: podinfo_repo_url,
108+
request: create_request_basic,
109+
expectedStatusCode: codes.Unauthenticated,
110+
},
111+
{
112+
testName: "wrong cluster",
113+
repoUrl: podinfo_repo_url,
114+
request: create_request_wrong_cluster,
115+
expectedStatusCode: codes.Unimplemented,
108116
},
109117
}
110118

@@ -195,6 +203,7 @@ func TestKindClusterUpdateInstalledPackage(t *testing.T) {
195203
request: update_request_6,
196204
unauthorized: true,
197205
},
206+
// TODO (gfichtenholt) test automatic upgrade to new version when it becomes available
198207
}
199208

200209
grpcContext := newGrpcContext(t, "test-update-admin")
@@ -412,13 +421,13 @@ func createAndWaitForHelmRelease(t *testing.T, tc integrationTestCreateSpec, flu
412421
}
413422

414423
ctx := grpcContext
415-
if tc.unauthorized {
424+
if tc.expectedStatusCode == codes.Unauthenticated {
416425
ctx = context.TODO()
417426
}
418427
resp, err := fluxPluginClient.CreateInstalledPackage(ctx, tc.request)
419-
if tc.unauthorized {
420-
if status.Code(err) != codes.Unauthenticated {
421-
t.Fatalf("Expected Unathenticated, got: %v", err)
428+
if tc.expectedStatusCode != codes.OK {
429+
if status.Code(err) != tc.expectedStatusCode {
430+
t.Fatalf("Expected %v, got: %v", tc.expectedStatusCode, err)
422431
}
423432
return nil // done, nothing more to check
424433
} else if err != nil {
@@ -481,7 +490,7 @@ func createAndWaitForHelmRelease(t *testing.T, tc integrationTestCreateSpec, flu
481490
}
482491

483492
func waitUntilInstallCompletes(t *testing.T, fluxPluginClient fluxplugin.FluxV2PackagesServiceClient, grpcContext context.Context, installedPackageRef *corev1.InstalledPackageReference, expectInstallFailure bool) (actualResp *corev1.GetInstalledPackageDetailResponse) {
484-
const maxWait = 25
493+
const maxWait = 30
485494
for i := 0; i <= maxWait; i++ {
486495
resp2, err := fluxPluginClient.GetInstalledPackageDetail(
487496
grpcContext,
@@ -521,6 +530,7 @@ var (
521530
Name: "my-podinfo",
522531
TargetContext: &corev1.Context{
523532
Namespace: "test-1",
533+
Cluster: KubeappsCluster,
524534
},
525535
}
526536

@@ -549,6 +559,7 @@ var (
549559
Name: "my-podinfo-2",
550560
TargetContext: &corev1.Context{
551561
Namespace: "test-2",
562+
Cluster: KubeappsCluster,
552563
},
553564
PkgVersionReference: &corev1.VersionReference{
554565
Version: "> 5",
@@ -580,6 +591,7 @@ var (
580591
Name: "my-podinfo-3",
581592
TargetContext: &corev1.Context{
582593
Namespace: "test-3",
594+
Cluster: KubeappsCluster,
583595
},
584596
ReconciliationOptions: &corev1.ReconciliationOptions{
585597
Interval: 60,
@@ -615,6 +627,7 @@ var (
615627
Name: "my-podinfo-4",
616628
TargetContext: &corev1.Context{
617629
Namespace: "test-4",
630+
Cluster: KubeappsCluster,
618631
},
619632
Values: "{\"ui\": { \"message\": \"what we do in the shadows\" } }",
620633
}
@@ -645,6 +658,7 @@ var (
645658
Name: "my-podinfo-5",
646659
TargetContext: &corev1.Context{
647660
Namespace: "test-5",
661+
Cluster: KubeappsCluster,
648662
},
649663
Values: "{\"replicaCount\": \"what we do in the shadows\" }",
650664
}
@@ -682,6 +696,7 @@ var (
682696
Name: "my-podinfo-6",
683697
TargetContext: &corev1.Context{
684698
Namespace: "test-6",
699+
Cluster: KubeappsCluster,
685700
},
686701
PkgVersionReference: &corev1.VersionReference{
687702
Version: "=5.2.1",
@@ -733,6 +748,7 @@ var (
733748
Name: "my-podinfo-7",
734749
TargetContext: &corev1.Context{
735750
Namespace: "test-7",
751+
Cluster: KubeappsCluster,
736752
},
737753
PkgVersionReference: &corev1.VersionReference{
738754
Version: "=5.2.1",
@@ -785,6 +801,7 @@ var (
785801
Name: "my-podinfo-8",
786802
TargetContext: &corev1.Context{
787803
Namespace: "test-8",
804+
Cluster: KubeappsCluster,
788805
},
789806
PkgVersionReference: &corev1.VersionReference{
790807
Version: "=5.2.1",
@@ -839,6 +856,7 @@ var (
839856
Name: "my-podinfo-9",
840857
TargetContext: &corev1.Context{
841858
Namespace: "test-9",
859+
Cluster: KubeappsCluster,
842860
},
843861
PkgVersionReference: &corev1.VersionReference{
844862
Version: "=5.2.1",
@@ -892,6 +910,7 @@ var (
892910
Name: "my-podinfo-10",
893911
TargetContext: &corev1.Context{
894912
Namespace: "test-10",
913+
Cluster: KubeappsCluster,
895914
},
896915
PkgVersionReference: &corev1.VersionReference{
897916
Version: "=5.2.1",
@@ -925,6 +944,7 @@ var (
925944
Name: "my-podinfo-11",
926945
TargetContext: &corev1.Context{
927946
Namespace: "test-11",
947+
Cluster: KubeappsCluster,
928948
},
929949
}
930950

@@ -1000,6 +1020,7 @@ var (
10001020
Name: "my-podinfo-12",
10011021
TargetContext: &corev1.Context{
10021022
Namespace: "test-12",
1023+
Cluster: KubeappsCluster,
10031024
},
10041025
PkgVersionReference: &corev1.VersionReference{
10051026
Version: "=5.2.1",
@@ -1031,6 +1052,7 @@ var (
10311052
Name: "my-podinfo-13",
10321053
TargetContext: &corev1.Context{
10331054
Namespace: "test-13",
1055+
Cluster: KubeappsCluster,
10341056
},
10351057
PkgVersionReference: &corev1.VersionReference{
10361058
Version: "=5.2.1",
@@ -1056,4 +1078,13 @@ var (
10561078
"kubectl -n @TARGET_NS@ port-forward deploy/@TARGET_NS@-my-podinfo-13 8080:9898\n",
10571079
AvailablePackageRef: availableRef("podinfo-13/podinfo", "default"),
10581080
}
1081+
1082+
create_request_wrong_cluster = &corev1.CreateInstalledPackageRequest{
1083+
AvailablePackageRef: availableRef("podinfo-14/podinfo", "default"),
1084+
Name: "my-podinfo",
1085+
TargetContext: &corev1.Context{
1086+
Namespace: "test-14",
1087+
Cluster: "this is not the cluster you're looking for",
1088+
},
1089+
}
10591090
)

cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ limitations under the License.
1313
package main
1414

1515
import (
16+
"bytes"
1617
"context"
17-
"encoding/json"
18+
"encoding/gob"
1819
"fmt"
1920
"time"
2021

@@ -265,12 +266,13 @@ func onAddOrModifyRepo(key string, unstructuredRepo map[string]interface{}) (int
265266
return nil, false, err
266267
}
267268

268-
jsonBytes, err := json.Marshal(charts)
269-
if err != nil {
269+
// use gob encoding instead of json, it peforms much better
270+
var buf bytes.Buffer
271+
enc := gob.NewEncoder(&buf)
272+
if err = enc.Encode(charts); err != nil {
270273
return nil, false, err
271274
}
272-
273-
return jsonBytes, true, nil
275+
return buf.Bytes(), true, nil
274276
} else {
275277
// repo is not quite ready to be indexed - not really an error condition,
276278
// just skip it eventually there will be another event when it is in ready state
@@ -280,16 +282,17 @@ func onAddOrModifyRepo(key string, unstructuredRepo map[string]interface{}) (int
280282
}
281283

282284
func onGetRepo(key string, value interface{}) (interface{}, error) {
283-
bytes, ok := value.([]byte)
285+
b, ok := value.([]byte)
284286
if !ok {
285287
return nil, status.Errorf(codes.Internal, "unexpected value found in cache for key [%s]: %v", key, value)
286288
}
287289

290+
dec := gob.NewDecoder(bytes.NewReader(b))
288291
var charts []models.Chart
289-
err := json.Unmarshal(bytes, &charts)
290-
if err != nil {
292+
if err := dec.Decode(&charts); err != nil {
291293
return nil, err
292294
}
295+
293296
return charts, nil
294297
}
295298

cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/server.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type Server struct {
5555
// NewServer returns a Server automatically configured with a function to obtain
5656
// the k8s client config.
5757
func NewServer(configGetter server.KubernetesConfigGetter, kubeappsCluster string) (*Server, error) {
58+
log.Infof("+fluxv2 NewServer(kubeappsCluster: [%v])", kubeappsCluster)
5859
repositoriesGvr := schema.GroupVersionResource{
5960
Group: fluxGroup,
6061
Version: fluxVersion,
@@ -72,8 +73,8 @@ func NewServer(configGetter server.KubernetesConfigGetter, kubeappsCluster strin
7273
return nil, err
7374
} else {
7475
return &Server{
75-
clientGetter: newClientGetter(configGetter),
76-
actionConfigGetter: newHelmActionConfigGetter(configGetter),
76+
clientGetter: newClientGetter(configGetter, kubeappsCluster),
77+
actionConfigGetter: newHelmActionConfigGetter(configGetter, kubeappsCluster),
7778
cache: cache,
7879
kubeappsCluster: kubeappsCluster,
7980
}, nil
@@ -113,7 +114,8 @@ func (s *Server) GetPackageRepositories(ctx context.Context, request *v1alpha1.G
113114
return nil, status.Errorf(codes.InvalidArgument, "no context provided")
114115
}
115116

116-
if request.Context.Cluster != "" {
117+
cluster := request.GetContext().GetCluster()
118+
if cluster != "" && cluster != s.kubeappsCluster {
117119
return nil, status.Errorf(
118120
codes.Unimplemented,
119121
"not supported yet: request.Context.Cluster: [%v]",
@@ -191,10 +193,14 @@ func (s *Server) GetAvailablePackageSummaries(ctx context.Context, request *core
191193
if pageSize > 0 && len(packageSummaries) == int(pageSize) {
192194
nextPageToken = fmt.Sprintf("%d", pageOffset+1)
193195
}
196+
194197
return &corev1.GetAvailablePackageSummariesResponse{
195198
AvailablePackageSummaries: packageSummaries,
196199
NextPageToken: nextPageToken,
197200
// TODO (gfichtenholt) Categories?
201+
// Just happened to notice that helm plug-in returning this.
202+
// Never discussed this and the design doc appears to have a lot of back-and-forth comments
203+
// about this, semantics aren't very clear
198204
}, nil
199205
}
200206

@@ -366,7 +372,8 @@ func (s *Server) CreateInstalledPackage(ctx context.Context, request *corev1.Cre
366372
if request.TargetContext == nil || request.TargetContext.Namespace == "" {
367373
return nil, status.Errorf(codes.InvalidArgument, "no request TargetContext namespace provided")
368374
}
369-
if request.TargetContext.Cluster != "" {
375+
cluster := request.GetTargetContext().GetCluster()
376+
if cluster != "" && cluster != s.kubeappsCluster {
370377
return nil, status.Errorf(
371378
codes.Unimplemented,
372379
"not supported yet: request.TargetContext.Cluster: [%v]",

0 commit comments

Comments
 (0)