Skip to content

Commit

Permalink
Fixes for issues.
Browse files Browse the repository at this point in the history
- Fix for integration test issues
- Improve logging.
- User lower case for some fields in VPC object(follow VM CRD format).

Signed-off-by: Archana Holla <[email protected]>
  • Loading branch information
archanapholla committed Jan 11, 2023
1 parent 4a9e491 commit 1430a5a
Show file tree
Hide file tree
Showing 17 changed files with 559 additions and 132 deletions.
5 changes: 3 additions & 2 deletions apis/runtime/v1alpha1/vpc_types.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 Antrea Authors.
// 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.
Expand Down Expand Up @@ -42,5 +42,6 @@ type Vpc struct {
type VpcList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Vpc `json:"items"`

Items []Vpc `json:"items"`
}
5 changes: 2 additions & 3 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,8 @@ spec:
EOF
```

After a `CloudProviderAccount` CR is added, VPCs are polled from cloud for the
configured region. From this VPC inventory, VPC ID or VPC Name can be used in
`CloudEntitySelector` configuration to onboard vms belonging to the VPC of interest.
Also, after a `CloudProviderAccount` CR is added, VPCs are automatically polled
for the configured region. Invoke kubectl commands to get the details of imported VPCs.

```bash
kubectl get vpc -A
Expand Down
Binary file removed docs/img.png
Binary file not shown.
Binary file removed docs/img_1.png
Binary file not shown.
Binary file removed docs/img_2.png
Binary file not shown.
184 changes: 184 additions & 0 deletions pkg/apiserver/registry/inventory/rest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// 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 inventory

import (
"context"
"strings"

logger "github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metatable "k8s.io/apimachinery/pkg/api/meta/table"
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"

runtimev1alpha1 "antrea.io/nephe/apis/runtime/v1alpha1"
"antrea.io/nephe/pkg/controllers/inventory"
)

// REST implements rest.Storage for VPC Inventory.
type REST struct {
cloudInventory *inventory.Inventory
logger logger.Logger
}

var (
_ rest.Scoper = &REST{}
_ rest.Getter = &REST{}
_ rest.Lister = &REST{}
)

// NewREST returns a REST object that will work against API services.
func NewREST(cloudInventory *inventory.Inventory, l logger.Logger) *REST {
return &REST{
cloudInventory: cloudInventory,
logger: l,
}
}

func (r *REST) New() runtime.Object {
return &runtimev1alpha1.Vpc{}
}

func (r *REST) NewList() runtime.Object {
return &runtimev1alpha1.VpcList{}
}

func (r *REST) Get(ctx context.Context, name string, _ *metav1.GetOptions) (runtime.Object, error) {
ns, ok := request.NamespaceFrom(ctx)
if !ok || len(ns) == 0 {
return nil, errors.NewBadRequest("Namespace cannot be empty.")
}
namespacedName := ns + "/" + name

objs, err := r.cloudInventory.GetVpcsFromIndexer(inventory.VpcIndexerByVpcNamespacedName, namespacedName)
if err != nil {
return nil, err
}

if len(objs) == 0 {
return nil, errors.NewNotFound(runtimev1alpha1.Resource("vpc"), name)
}
vpc := objs[0].(*runtimev1alpha1.Vpc)
return vpc, nil
}

func (r *REST) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
// List only supports four types of input options
// 1. All namespace
// 2. Labelselector with only the specific namespace, the only valid labelselectors are "account-name=<accountname>" and "region=<region>"
// 3. Fieldselector with only the specific namespace, the only valid fieldselectors is "metadata.name=<metadata.name>"
// 4. Specific Namespace
accountName := ""
region := ""
if options != nil && options.LabelSelector != nil && options.LabelSelector.String() != "" {
labelSelectorStrings := strings.Split(options.LabelSelector.String(), ",")
for _, labelSelectorString := range labelSelectorStrings {
labelKeyAndValue := strings.Split(labelSelectorString, "=")
if labelKeyAndValue[0] == "account-name" {
accountName = labelKeyAndValue[1]
} else if labelKeyAndValue[0] == "region" {
region = strings.ToLower(labelKeyAndValue[1])
} else {
return nil, errors.NewBadRequest("unsupported label selector, supported labels are: account-name and region")
}
}
}

name := ""
if options != nil && options.FieldSelector != nil && options.FieldSelector.String() != "" {
fieldSelectorStrings := strings.Split(options.FieldSelector.String(), ",")
for _, fieldSelectorString := range fieldSelectorStrings {
fieldKeyAndValue := strings.Split(fieldSelectorString, "=")
if fieldKeyAndValue[0] == "metadata.name" {
name = fieldKeyAndValue[1]
} else {
return nil, errors.NewBadRequest("unsupported field selector, supported labels is: metadata.name")
}
}
}

ns, _ := request.NamespaceFrom(ctx)
var objs []interface{}
if ns == "" && (accountName != "" || region != "" || name != "") {
return nil, errors.NewBadRequest("cannot query filter with all namepsace. Namespace should be specified")
}

if ns == "" {
objs = r.cloudInventory.GetAllVpcs()
} else if accountName != "" {
accountNameSpace := types.NamespacedName{
Name: accountName,
Namespace: ns,
}
objs, _ = r.cloudInventory.GetVpcsFromIndexer(inventory.VpcIndexerByAccountNameSpacedName, accountNameSpace.String())
} else if name != "" {
namespacedName := types.NamespacedName{
Name: name,
Namespace: ns,
}
objs, _ = r.cloudInventory.GetVpcsFromIndexer(inventory.VpcIndexerByVpcNamespacedName, namespacedName.String())
} else if region != "" {
namespacedRegion := types.NamespacedName{
Name: region,
Namespace: ns,
}
objs, _ = r.cloudInventory.GetVpcsFromIndexer(inventory.VpcIndexerByNamespacedRegion, namespacedRegion.String())
} else {
objs, _ = r.cloudInventory.GetVpcsFromIndexer(inventory.VpcIndexerByNamespace, ns)
}
vpcList := &runtimev1alpha1.VpcList{}
for _, obj := range objs {
vpc := obj.(*runtimev1alpha1.Vpc)
vpcList.Items = append(vpcList.Items, *vpc)
}

return vpcList, nil
}

func (r *REST) NamespaceScoped() bool {
return true
}

func (r *REST) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
table := &metav1.Table{
ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "NAME", Type: "string", Description: "Name"},
{Name: "CLOUD PROVIDER", Type: "string", Description: "Cloud Provider"},
{Name: "REGION", Type: "string", Description: "Region"},
},
}
if m, err := meta.ListAccessor(obj); err == nil {
table.ResourceVersion = m.GetResourceVersion()
table.Continue = m.GetContinue()
table.RemainingItemCount = m.GetRemainingItemCount()
} else {
if m, err := meta.CommonAccessor(obj); err == nil {
table.ResourceVersion = m.GetResourceVersion()
}
}
var err error
table.Rows, err = metatable.MetaToTableRow(obj,
func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) {
vpc := obj.(*runtimev1alpha1.Vpc)
return []interface{}{vpc.Name, vpc.Info.CloudProvider, vpc.Info.Region}, nil
})
return table, err
}
29 changes: 29 additions & 0 deletions pkg/apiserver/registry/inventory/vpc_suite_test.go
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 inventory_test

import (
"testing"

"antrea.io/nephe/pkg/logging"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestVpc(t *testing.T) {
logging.SetDebugLog(true)
RegisterFailHandler(Fail)
RunSpecs(t, "Vpc Suite")
}
Loading

0 comments on commit 1430a5a

Please sign in to comment.