Skip to content

Commit

Permalink
Merge branch 'master' into e2eImprovements
Browse files Browse the repository at this point in the history
  • Loading branch information
lahabana authored Jan 12, 2024
2 parents ea2142f + dc66648 commit 0e58037
Show file tree
Hide file tree
Showing 11 changed files with 241 additions and 66 deletions.
6 changes: 3 additions & 3 deletions api/openapi/specs/common/resource.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ components:
ResourceTypeDescription:
description: Description of a resource type, this is useful for dynamically generated clients and the gui
type: object
required: [name, scope, readOnly, path, singularDisplayName, pluralDisplayName, includeInDump]
required: [name, scope, readOnly, path, singularDisplayName, pluralDisplayName, includeInFederationWithPolicies]
properties:
name:
description: the name of the resource type
Expand All @@ -20,8 +20,8 @@ components:
type: string
pluralDisplayName:
type: string
includeInDump:
description: description resources of this type should be included in dump (especially useful for moving from non-federated to federated or migrating to a new global).
includeInFederationWithPolicies:
description: description resources of this type should be included in federetion-with-policies export profile (especially useful for moving from non-federated to federated or migrating to a new global).
type: boolean
policy:
$ref: "#/components/schemas/PolicyDescription"
Expand Down
4 changes: 2 additions & 2 deletions api/openapi/types/common/zz_generated.resource.go

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

46 changes: 41 additions & 5 deletions app/kumactl/cmd/export/export.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package export

import (
"context"
"fmt"

"github.com/pkg/errors"
Expand All @@ -27,13 +28,15 @@ type exportContext struct {
}

const (
profileFederation = "federation"
profileFederation = "federation"
profileFederationWithPolicies = "federation-with-policies"
profileAll = "all"

formatUniversal = "universal"
formatKubernetes = "kubernetes"
)

var profiles = map[string][]model.ResourceType{
var staticProfiles = map[string][]model.ResourceType{
profileFederation: {
core_mesh.MeshType,
core_system.GlobalSecretType,
Expand All @@ -57,11 +60,15 @@ $ kumactl export --profile federation --format universal > policies.yaml
cmd.PrintErrln(err)
}

resTypes, ok := profiles[ctx.args.profile]
if !ok {
if ctx.args.profile != profileAll && ctx.args.profile != profileFederation && ctx.args.profile != profileFederationWithPolicies {
return errors.New("invalid profile")
}

resTypes, err := resourcesTypesToDump(cmd.Context(), ctx)
if err != nil {
return err
}

if ctx.args.format != formatUniversal && ctx.args.format != formatKubernetes {
return errors.New("invalid format")
}
Expand Down Expand Up @@ -130,7 +137,7 @@ $ kumactl export --profile federation --format universal > policies.yaml
return nil
},
}
cmd.Flags().StringVarP(&ctx.args.profile, "profile", "p", profileFederation, fmt.Sprintf(`Profile. Available values: %q`, profileFederation))
cmd.Flags().StringVarP(&ctx.args.profile, "profile", "p", profileFederation, fmt.Sprintf(`Profile. Available values: %q, %q, %q`, profileFederation, profileAll, profileFederationWithPolicies))
cmd.Flags().StringVarP(&ctx.args.format, "format", "f", formatUniversal, fmt.Sprintf(`Policy format output. Available values: %q, %q`, formatUniversal, formatKubernetes))
return cmd
}
Expand All @@ -144,3 +151,32 @@ func cleanKubeObject(obj map[string]interface{}) {
delete(meta, "generation")
delete(meta, "managedFields")
}

func resourcesTypesToDump(ctx context.Context, ectx *exportContext) ([]model.ResourceType, error) {
rt, ok := staticProfiles[ectx.args.profile]
if ok {
return rt, nil
}
client, err := ectx.CurrentResourcesListClient()
if err != nil {
return nil, err
}
list, err := client.List(ctx)
if err != nil {
return nil, err
}
var resTypes []model.ResourceType
for _, res := range list.Resources {
switch ectx.args.profile {
case profileAll:
resTypes = append(resTypes, model.ResourceType(res.Name))
case profileFederationWithPolicies:
if res.IncludeInFederationWithPolicies {
resTypes = append(resTypes, model.ResourceType(res.Name))
}
default:
return nil, errors.New("invalid profile")
}
}
return resTypes, nil
}
12 changes: 12 additions & 0 deletions app/kumactl/cmd/export/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
. "github.com/onsi/gomega"
"github.com/spf13/cobra"

api_types "github.com/kumahq/kuma/api/openapi/types"
"github.com/kumahq/kuma/app/kumactl/cmd"
"github.com/kumahq/kuma/app/kumactl/pkg/client"
"github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
Expand Down Expand Up @@ -40,6 +41,9 @@ var _ = Describe("kumactl export", func() {
rootCtx.Runtime.NewKubernetesResourcesClient = func(client util_http.Client) client.KubernetesResourcesClient {
return fileBasedKubernetesResourcesClient{}
}
rootCtx.Runtime.NewResourcesListClient = func(u util_http.Client) client.ResourcesListClient {
return staticResourcesListClient{}
}

rootCmd = cmd.NewRootCmd(rootCtx)
buf = &bytes.Buffer{}
Expand Down Expand Up @@ -149,3 +153,11 @@ func (f fileBasedKubernetesResourcesClient) Get(_ context.Context, descriptor mo
}
return res, nil
}

type staticResourcesListClient struct{}

var _ client.ResourcesListClient = &staticResourcesListClient{}

func (s staticResourcesListClient) List(ctx context.Context) (api_types.ResourceTypeDescriptionList, error) {
return api_types.ResourceTypeDescriptionList{}, nil
}
54 changes: 54 additions & 0 deletions app/kumactl/pkg/client/resources_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package client

import (
"context"
"encoding/json"
"io"
"net/http"

"github.com/pkg/errors"

api_types "github.com/kumahq/kuma/api/openapi/types"
util_http "github.com/kumahq/kuma/pkg/util/http"
)

type ResourcesListClient interface {
List(ctx context.Context) (api_types.ResourceTypeDescriptionList, error)
}

var _ ResourcesListClient = &HTTPResourcesListClient{}

type HTTPResourcesListClient struct {
client util_http.Client
}

func NewHTTPResourcesListClient(client util_http.Client) ResourcesListClient {
return &HTTPResourcesListClient{
client: client,
}
}

func (h HTTPResourcesListClient) List(ctx context.Context) (api_types.ResourceTypeDescriptionList, error) {
req, err := http.NewRequest("GET", "/_resources", nil)
if err != nil {
return api_types.ResourceTypeDescriptionList{}, err
}
req.Header.Set("Accept", "application/json")
resp, err := h.client.Do(req.WithContext(ctx))
if err != nil {
return api_types.ResourceTypeDescriptionList{}, err
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return api_types.ResourceTypeDescriptionList{}, err
}
if resp.StatusCode != 200 {
return api_types.ResourceTypeDescriptionList{}, errors.Errorf("unexpected status code: %d %s", resp.StatusCode, b)
}
list := api_types.ResourceTypeDescriptionList{}
if err := json.Unmarshal(b, &list); err != nil {
return api_types.ResourceTypeDescriptionList{}, err
}
return list, nil
}
62 changes: 62 additions & 0 deletions app/kumactl/pkg/client/resources_client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package client

import (
"context"
"net/http"
"net/http/httptest"
"net/url"

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

util_http "github.com/kumahq/kuma/pkg/util/http"
)

var _ = Describe("Resources Client", func() {
It("should return resources list", func() {
// given
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
mux.HandleFunc("/_resources", func(writer http.ResponseWriter, req *http.Request) {
defer GinkgoRecover()
Expect(req.Header.Get("accept")).To(Equal("application/json"))

resp := `{
"resources": [
{
"includeInDump": true,
"name": "CircuitBreaker",
"path": "circuit-breakers",
"pluralDisplayName": "Circuit Breakers",
"policy": {
"hasFromTargetRef": false,
"hasToTargetRef": false,
"isTargetRef": false
},
"readOnly": false,
"scope": "Mesh",
"singularDisplayName": "Circuit Breaker"
}
]
}`

_, err := writer.Write([]byte(resp))
Expect(err).ToNot(HaveOccurred())
})
serverURL, err := url.Parse(server.URL)
Expect(err).ToNot(HaveOccurred())

resListClient := NewHTTPResourcesListClient(
util_http.ClientWithBaseURL(http.DefaultClient, serverURL, nil),
)

// when
obj, err := resListClient.List(context.Background())

// then
Expect(err).ToNot(HaveOccurred())
Expect(obj.Resources).To(HaveLen(1))
Expect(obj.Resources[0].Name).To(Equal("CircuitBreaker"))
})
})
10 changes: 10 additions & 0 deletions app/kumactl/pkg/cmd/root_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type RootRuntime struct {
NewZoneTokenClient func(util_http.Client) tokens.ZoneTokenClient
NewAPIServerClient func(util_http.Client) kumactl_resources.ApiServerClient
NewKubernetesResourcesClient func(util_http.Client) client.KubernetesResourcesClient
NewResourcesListClient func(util_http.Client) client.ResourcesListClient
Registry registry.TypeRegistry
}

Expand Down Expand Up @@ -118,6 +119,7 @@ func DefaultRootContext() *RootContext {
NewKubernetesResourcesClient: func(c util_http.Client) client.KubernetesResourcesClient {
return client.NewHTTPKubernetesResourcesClient(c, registry.Global().ObjectDescriptors())
},
NewResourcesListClient: client.NewHTTPResourcesListClient,
},
InstallCpContext: install_context.DefaultInstallCpContext(),
InstallCRDContext: install_context.DefaultInstallCrdsContext(),
Expand Down Expand Up @@ -222,6 +224,14 @@ func (rc *RootContext) CurrentKubernetesResourcesClient() (client.KubernetesReso
return rc.Runtime.NewKubernetesResourcesClient(client), nil
}

func (rc *RootContext) CurrentResourcesListClient() (client.ResourcesListClient, error) {
client, err := rc.BaseAPIServerClient()
if err != nil {
return nil, err
}
return rc.Runtime.NewResourcesListClient(client), nil
}

func (rc *RootContext) CurrentDataplaneOverviewClient() (kumactl_resources.DataplaneOverviewClient, error) {
client, err := rc.BaseAPIServerClient()
if err != nil {
Expand Down
11 changes: 6 additions & 5 deletions docs/generated/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1555,7 +1555,7 @@ components:
- path
- singularDisplayName
- pluralDisplayName
- includeInDump
- includeInFederationWithPolicies
properties:
name:
description: the name of the resource type
Expand All @@ -1576,11 +1576,12 @@ components:
type: string
pluralDisplayName:
type: string
includeInDump:
includeInFederationWithPolicies:
description: >-
description resources of this type should be included in dump
(especially useful for moving from non-federated to federated or
migrating to a new global).
description resources of this type should be included in
federetion-with-policies export profile (especially useful for
moving from non-federated to federated or migrating to a new
global).
type: boolean
policy:
$ref: '#/components/schemas/PolicyDescription'
Expand Down
16 changes: 8 additions & 8 deletions pkg/api-server/policies_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/kumahq/kuma/pkg/core/resources/model"
)

func addPoliciesWsEndpoints(ws *restful.WebService, isGlobal bool, federatedZone bool, readOnly bool, defs []model.ResourceTypeDescriptor) {
func addPoliciesWsEndpoints(ws *restful.WebService, federatedZone bool, readOnly bool, defs []model.ResourceTypeDescriptor) {
ws.Route(ws.GET("/policies").To(func(req *restful.Request, resp *restful.Response) {
response := types.PoliciesResponse{}
for _, def := range defs {
Expand Down Expand Up @@ -42,13 +42,13 @@ func addPoliciesWsEndpoints(ws *restful.WebService, isGlobal bool, federatedZone
response := api_types.ResourceTypeDescriptionList{}
for _, def := range defs {
td := api_common.ResourceTypeDescription{
Name: string(def.Name),
ReadOnly: readOnly || federatedZone || def.ReadOnly,
Path: def.WsPath,
SingularDisplayName: def.SingularDisplayName,
PluralDisplayName: def.PluralDisplayName,
Scope: api_common.ResourceTypeDescriptionScope(def.Scope),
IncludeInDump: isGlobal || def.DumpForGlobal,
Name: string(def.Name),
ReadOnly: readOnly || federatedZone || def.ReadOnly,
Path: def.WsPath,
SingularDisplayName: def.SingularDisplayName,
PluralDisplayName: def.PluralDisplayName,
Scope: api_common.ResourceTypeDescriptionScope(def.Scope),
IncludeInFederationWithPolicies: (def.KDSFlags & model.GlobalToAllZonesFlag) != 0,
}
if def.IsPolicy {
td.Policy = &api_common.PolicyDescription{
Expand Down
2 changes: 1 addition & 1 deletion pkg/api-server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func NewApiServer(
Produces(restful.MIME_JSON)

addResourcesEndpoints(ws, defs, resManager, cfg, access.ResourceAccess, globalInsightService, meshContextBuilder)
addPoliciesWsEndpoints(ws, cfg.Mode == config_core.Global, cfg.IsFederatedZoneCP(), cfg.ApiServer.ReadOnly, defs)
addPoliciesWsEndpoints(ws, cfg.IsFederatedZoneCP(), cfg.ApiServer.ReadOnly, defs)
addInspectEndpoints(ws, cfg, meshContextBuilder, resManager)
addInspectEnvoyAdminEndpoints(ws, cfg, resManager, access.EnvoyAdminAccess, envoyAdminClient)
addZoneEndpoints(ws, resManager)
Expand Down
Loading

0 comments on commit 0e58037

Please sign in to comment.