Skip to content

Commit

Permalink
[ExternalNode] Implement support bundle collection status on Controller
Browse files Browse the repository at this point in the history
Signed-off-by: wenyingd <wenyingd@vmware.com>
  • Loading branch information
wenyingd committed Oct 18, 2022
1 parent 930fd5d commit c9ed12e
Show file tree
Hide file tree
Showing 11 changed files with 1,292 additions and 37 deletions.
11 changes: 8 additions & 3 deletions cmd/antrea-controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ func run(o *Options) error {
}

var bundleCollectionController *supportbundlecollection.Controller
var bundleCollectionStatusController *supportbundlecollection.StatusController
bundleCollectionStore := supportbundlecollectionstore.NewSupportBundleCollectionStore()
if features.DefaultFeatureGate.Enabled(features.SupportBundleCollection) {
bundleCollectionInformer := crdInformerFactory.Crd().V1alpha1().SupportBundleCollections()
bundleCollectionController = supportbundlecollection.NewSupportBundleCollectionController(client, crdClient, bundleCollectionInformer, nodeInformer, externalNodeInformer, bundleCollectionStore)
bundleCollectionStatusController = supportbundlecollection.NewStatusController(crdClient, bundleCollectionInformer, bundleCollectionStore)
bundleCollectionController = supportbundlecollection.NewSupportBundleCollectionController(client, crdClient, bundleCollectionInformer, nodeInformer, externalNodeInformer, bundleCollectionStore, bundleCollectionStatusController)
}

var networkPolicyStatusController *networkpolicy.StatusController
Expand Down Expand Up @@ -270,6 +272,7 @@ func run(o *Options) error {
egressController,
statsAggregator,
bundleCollectionController,
bundleCollectionStatusController,
*o.config.EnablePrometheusMetrics,
cipherSuites,
cipher.TLSVersionMap[o.config.TLSMinVersion])
Expand Down Expand Up @@ -443,6 +446,7 @@ func createAPIServerConfig(kubeconfig string,
egressController *egress.EgressController,
statsAggregator *stats.Aggregator,
bundleCollectionStore *supportbundlecollection.Controller,
bundleCollectionStatusController *supportbundlecollection.StatusController,
enableMetrics bool,
cipherSuites []uint16,
tlsMinVersion uint16) (*apiserver.Config, error) {
Expand All @@ -457,7 +461,7 @@ func createAPIServerConfig(kubeconfig string,

secureServing.BindPort = bindPort
secureServing.BindAddress = net.IPv4zero
// kubeconfig file is useful when antrea-controller isn't not running as a pod, like during development.
// kubeconfig file is useful when antrea-controller is not running as a pod, like during development.
if len(kubeconfig) > 0 {
authentication.RemoteKubeConfigFile = kubeconfig
authorization.RemoteKubeConfigFile = kubeconfig
Expand Down Expand Up @@ -505,5 +509,6 @@ func createAPIServerConfig(kubeconfig string,
endpointQuerier,
npController,
egressController,
bundleCollectionStore), nil
bundleCollectionStore,
bundleCollectionStatusController), nil
}
65 changes: 35 additions & 30 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,22 @@ func init() {

// ExtraConfig holds custom apiserver config.
type ExtraConfig struct {
k8sClient kubernetes.Interface
addressGroupStore storage.Interface
appliedToGroupStore storage.Interface
networkPolicyStore storage.Interface
egressGroupStore storage.Interface
bundleCollectionStore storage.Interface
controllerQuerier querier.ControllerQuerier
endpointQuerier controllernetworkpolicy.EndpointQuerier
networkPolicyController *controllernetworkpolicy.NetworkPolicyController
egressController *egress.EgressController
externalIPPoolController *externalippool.ExternalIPPoolController
caCertController *certificate.CACertController
statsAggregator *stats.Aggregator
networkPolicyStatusController *controllernetworkpolicy.StatusController
bundleCollectionController *controllerbundlecollection.Controller
k8sClient kubernetes.Interface
addressGroupStore storage.Interface
appliedToGroupStore storage.Interface
networkPolicyStore storage.Interface
egressGroupStore storage.Interface
bundleCollectionStore storage.Interface
controllerQuerier querier.ControllerQuerier
endpointQuerier controllernetworkpolicy.EndpointQuerier
networkPolicyController *controllernetworkpolicy.NetworkPolicyController
egressController *egress.EgressController
externalIPPoolController *externalippool.ExternalIPPoolController
caCertController *certificate.CACertController
statsAggregator *stats.Aggregator
networkPolicyStatusController *controllernetworkpolicy.StatusController
bundleCollectionController *controllerbundlecollection.Controller
bundleCollectionStatusController *controllerbundlecollection.StatusController
}

// Config defines the config for Antrea apiserver.
Expand Down Expand Up @@ -145,24 +146,26 @@ func NewConfig(
endpointQuerier controllernetworkpolicy.EndpointQuerier,
npController *controllernetworkpolicy.NetworkPolicyController,
egressController *egress.EgressController,
bundleCollectionController *controllerbundlecollection.Controller) *Config {
bundleCollectionController *controllerbundlecollection.Controller,
bundleCollectionStatusController *controllerbundlecollection.StatusController) *Config {
return &Config{
genericConfig: genericConfig,
extraConfig: ExtraConfig{
k8sClient: k8sClient,
addressGroupStore: addressGroupStore,
appliedToGroupStore: appliedToGroupStore,
networkPolicyStore: networkPolicyStore,
egressGroupStore: egressGroupStore,
bundleCollectionStore: supportBundleCollectionStore,
caCertController: caCertController,
statsAggregator: statsAggregator,
controllerQuerier: controllerQuerier,
endpointQuerier: endpointQuerier,
networkPolicyController: npController,
networkPolicyStatusController: networkPolicyStatusController,
egressController: egressController,
bundleCollectionController: bundleCollectionController,
k8sClient: k8sClient,
addressGroupStore: addressGroupStore,
appliedToGroupStore: appliedToGroupStore,
networkPolicyStore: networkPolicyStore,
egressGroupStore: egressGroupStore,
bundleCollectionStore: supportBundleCollectionStore,
caCertController: caCertController,
statsAggregator: statsAggregator,
controllerQuerier: controllerQuerier,
endpointQuerier: endpointQuerier,
networkPolicyController: npController,
networkPolicyStatusController: networkPolicyStatusController,
egressController: egressController,
bundleCollectionController: bundleCollectionController,
bundleCollectionStatusController: bundleCollectionStatusController,
},
}
}
Expand All @@ -181,6 +184,7 @@ func installAPIGroup(s *APIServer, c completedConfig) error {
nodeStatsSummaryStorage := nodestatssummary.NewREST(c.extraConfig.statsAggregator)
egressGroupStorage := egressgroup.NewREST(c.extraConfig.egressGroupStore)
bundleCollectionStorage := supportbundlecollection.NewREST(c.extraConfig.bundleCollectionStore)
bundleCollectionStatusStorage := supportbundlecollection.NewStatusREST(c.extraConfig.bundleCollectionStatusController)
cpGroup := genericapiserver.NewDefaultAPIGroupInfo(controlplane.GroupName, Scheme, parameterCodec, Codecs)
cpv1beta2Storage := map[string]rest.Storage{}
cpv1beta2Storage["addressgroups"] = addressGroupStorage
Expand All @@ -192,6 +196,7 @@ func installAPIGroup(s *APIServer, c completedConfig) error {
cpv1beta2Storage["clustergroupmembers"] = clusterGroupMembershipStorage
cpv1beta2Storage["egressgroups"] = egressGroupStorage
cpv1beta2Storage["supportbundlecollections"] = bundleCollectionStorage
cpv1beta2Storage["supportbundlecollections/status"] = bundleCollectionStatusStorage
cpGroup.VersionedResourcesStorageMap["v1beta2"] = cpv1beta2Storage

systemGroup := genericapiserver.NewDefaultAPIGroupInfo(system.GroupName, Scheme, metav1.ParameterCodec, Codecs)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2022 Antrea Authors
//
// 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 supportbundlecollection

import (
"context"
"fmt"

"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"

"antrea.io/antrea/pkg/apis/controlplane"
)

// StatusREST implements the REST endpoint for getting NetworkPolicy's obj.
type StatusREST struct {
collector statusCollector
}

// NewStatusREST returns a REST object that will work against API services.
func NewStatusREST(collector statusCollector) *StatusREST {
return &StatusREST{collector}
}

// statusCollector is the interface required by the handler.
type statusCollector interface {
UpdateStatus(status *controlplane.SupportBundleCollectionStatus) error
}

var _ rest.NamedCreater = &StatusREST{}

func (s StatusREST) New() runtime.Object {
return &controlplane.SupportBundleCollectionStatus{}
}

func (s StatusREST) Create(ctx context.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
status, ok := obj.(*controlplane.SupportBundleCollectionStatus)
if !ok {
return nil, errors.NewBadRequest(fmt.Sprintf("not a SupportBundleCollectionStatus object: %T", obj))
}
if name != status.Name {
return nil, errors.NewBadRequest("name in URL does not match name in SupportBundleCollectionStatus object")
}
err := s.collector.UpdateStatus(status)
if err != nil {
return nil, err
}
return &metav1.Status{Status: metav1.StatusSuccess}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2022 Antrea Authors
//
// 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 supportbundlecollection

import (
"context"
"fmt"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"

"antrea.io/antrea/pkg/apis/controlplane"
)

func TestCreate(t *testing.T) {
for _, tc := range []struct {
name string
obj runtime.Object
expError error
}{
{
name: "invalid-status-type",
obj: runtime.Object(&controlplane.SupportBundleCollection{
ObjectMeta: metav1.ObjectMeta{
Name: "invalid-status-type",
},
}),
expError: errors.NewBadRequest("not a SupportBundleCollectionStatus object"),
},
{
name: "invalid-status-name",
obj: runtime.Object(&controlplane.SupportBundleCollectionStatus{
ObjectMeta: metav1.ObjectMeta{
Name: "invalid-name",
},
}),
expError: errors.NewBadRequest("name in URL does not match name in SupportBundleCollectionStatus object"),
},
{
name: "unable-update",
obj: runtime.Object(&controlplane.SupportBundleCollectionStatus{
ObjectMeta: metav1.ObjectMeta{
Name: "unable-update",
},
}),
expError: fmt.Errorf("no Nodes status is updated"),
},
{
name: "valid-status-update",
obj: runtime.Object(&controlplane.SupportBundleCollectionStatus{
ObjectMeta: metav1.ObjectMeta{
Name: "valid-status-update",
},
Nodes: []controlplane.SupportBundleCollectionNodeStatus{
{
NodeName: "n1",
NodeType: "Node",
},
},
}),
expError: nil,
},
} {
statusController := &fakeStatusCollector{
bundleCollectionStatuses: make(map[string]*controlplane.SupportBundleCollectionStatus),
}
r := NewStatusREST(statusController)
rsp, err := r.Create(context.TODO(), tc.name, tc.obj, nil, &metav1.CreateOptions{})
if tc.expError == nil {
assert.NoError(t, err)
assert.Equal(t, &metav1.Status{Status: metav1.StatusSuccess}, rsp)
expStatus := tc.obj.(*controlplane.SupportBundleCollectionStatus)
status := statusController.bundleCollectionStatuses[tc.name]
assert.Equal(t, expStatus, status)
} else {
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), tc.expError.Error()))
}
}
}

type fakeStatusCollector struct {
bundleCollectionStatuses map[string]*controlplane.SupportBundleCollectionStatus
}

func (c *fakeStatusCollector) UpdateStatus(status *controlplane.SupportBundleCollectionStatus) error {
bundleCollectionName := status.Name
if len(status.Nodes) == 0 {
return fmt.Errorf("no Nodes status is updated")
}
c.bundleCollectionStatuses[bundleCollectionName] = status
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2022 Antrea Authors
//
// 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 fake

import (
"context"

"antrea.io/antrea/pkg/apis/controlplane/v1beta2"
)

func (c *FakeSupportBundleCollections) UpdateStatus(ctx context.Context, name string, status *v1beta2.SupportBundleCollectionStatus) error {
return nil
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2022 Antrea Authors
//
// 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 v1beta2

import (
"context"

"antrea.io/antrea/pkg/apis/controlplane/v1beta2"
)

type SupportBundleCollectionExpansion interface {
UpdateStatus(ctx context.Context, name string, status *v1beta2.SupportBundleCollectionStatus) error
}

func (c *supportBundleCollections) UpdateStatus(ctx context.Context, name string, status *v1beta2.SupportBundleCollectionStatus) error {
return c.client.Post().Resource("supportbundlecollections").Name(name).SubResource("status").Body(status).Do(ctx).Error()
}
Loading

0 comments on commit c9ed12e

Please sign in to comment.