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
49 changes: 39 additions & 10 deletions src/cmd/accessgraph/get/get-accessgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"context"
"fmt"
"github.com/otterize/otterize-cli/src/pkg/cli"
cloudclientgql "github.com/otterize/otterize-cli/src/pkg/cloudclient/graphql"
cloudclient "github.com/otterize/otterize-cli/src/pkg/cloudclient/restapi"
"github.com/otterize/otterize-cli/src/pkg/cloudclient/restapi/cloudapi"
"github.com/otterize/otterize-cli/src/pkg/cloudclient/restapi/resources"
"github.com/otterize/otterize-cli/src/pkg/config"
"github.com/otterize/otterize-cli/src/pkg/output"
"github.com/otterize/otterize-cli/src/pkg/resourcesresolver"
"github.com/otterize/otterize-cli/src/pkg/utils/must"
"github.com/samber/lo"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -53,7 +54,7 @@ var GetAccessGraph = &cobra.Command{
return err
}

filter, err := accessGraphFilterFromFlags(ctxTimeout, c)
filter, err := accessGraphFilterFromFlags(ctxTimeout)
if err != nil {
return err
}
Expand All @@ -68,38 +69,66 @@ var GetAccessGraph = &cobra.Command{
},
}

func accessGraphFilterFromFlags(ctx context.Context, c *cloudclient.Client) (cloudapi.InputAccessGraphFilter, error) {
resolver := resources.NewResolver(c).WithContext(ctx)
func toIncludeFilterIfNonEmpty(items []string) *map[string]any {
if len(items) == 0 {
return nil
}
return &map[string]any{
"include": lo.ToPtr(items),
}
}

func accessGraphFilterFromFlags(ctx context.Context) (cloudapi.InputAccessGraphFilter, error) {
gqlClient, err := cloudclientgql.NewClient(ctx)
if err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}

resolver := resourcesresolver.NewResolver(gqlClient)
if err := resolver.LoadOrgResources(ctx); err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}

filter := cloudapi.InputAccessGraphFilter{}
if viper.IsSet(cli.ClustersKey) || viper.IsSet(clustersIdsKey) {
clusters := slices.Concat(viper.GetStringSlice(cli.ClustersKey), viper.GetStringSlice(clustersIdsKey))
if err := resolver.LoadClusters(clusters); err != nil {
clusterIds, err := resolver.ResolveClusters(clusters)
if err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}
filter.ClusterIds = toIncludeFilterIfNonEmpty(clusterIds)
}

if viper.IsSet(cli.EnvironmentsKey) || viper.IsSet(envIdsKey) {
envs := slices.Concat(viper.GetStringSlice(cli.EnvironmentsKey), viper.GetStringSlice(envIdsKey))
if err := resolver.LoadEnvironments(envs); err != nil {
envIds, err := resolver.ResolveEnvironments(envs)
if err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}
filter.EnvironmentIds = toIncludeFilterIfNonEmpty(envIds)
}

if viper.IsSet(cli.NamespacesKey) || viper.IsSet(namespacesIdsKey) {
namespaces := slices.Concat(viper.GetStringSlice(cli.NamespacesKey), viper.GetStringSlice(namespacesIdsKey))
if err := resolver.LoadNamespaces(namespaces); err != nil {
namespaceIds, err := resolver.ResolveNamespaces(namespaces)
if err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}
filter.NamespaceIds = toIncludeFilterIfNonEmpty(namespaceIds)
}

if viper.IsSet(cli.ServicesKey) || viper.IsSet(servicesIdsKey) {
if err := resolver.LoadServices(ctx); err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}
services := slices.Concat(viper.GetStringSlice(cli.ServicesKey), viper.GetStringSlice(servicesIdsKey))
if err := resolver.LoadServices(services); err != nil {
serviceIds, err := resolver.ResolveServices(services)
if err != nil {
return cloudapi.InputAccessGraphFilter{}, err
}
filter.ServiceIds = toIncludeFilterIfNonEmpty(serviceIds)
}

filter := resolver.BuildAccessGraphFilter()

lastSeenFilter, err := getInputTimeFilterValueFromViper(lastSeenAfterKey)
if err != nil {
return cloudapi.InputAccessGraphFilter{}, err
Expand Down
51 changes: 42 additions & 9 deletions src/cmd/clientintents/export/export-clientintents.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"context"
"fmt"
"github.com/otterize/otterize-cli/src/pkg/cli"
cloudclientgql "github.com/otterize/otterize-cli/src/pkg/cloudclient/graphql"
cloudclient "github.com/otterize/otterize-cli/src/pkg/cloudclient/restapi"
"github.com/otterize/otterize-cli/src/pkg/cloudclient/restapi/cloudapi"
"github.com/otterize/otterize-cli/src/pkg/cloudclient/restapi/resources"
"github.com/otterize/otterize-cli/src/pkg/config"
"github.com/otterize/otterize-cli/src/pkg/errors"
"github.com/otterize/otterize-cli/src/pkg/resourcesresolver"
"github.com/samber/lo"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -43,7 +44,7 @@ var ExportClientIntentsCmd = &cobra.Command{
return errors.Wrap(err)
}

filter, err := servicesFilterFromFlags(ctxTimeout, c)
filter, err := servicesFilterFromFlags(ctxTimeout)
if err != nil {
return errors.Wrap(err)
}
Expand Down Expand Up @@ -85,29 +86,61 @@ var ExportClientIntentsCmd = &cobra.Command{
},
}

func servicesFilterFromFlags(ctx context.Context, c *cloudclient.Client) (cloudapi.InputServiceFilter, error) {
resolver := resources.NewResolver(c).WithContext(ctx)
func toPtrIfNonEmpty(items []string) *[]string {
if len(items) == 0 {
return nil
}
return lo.ToPtr(items)
}

func servicesFilterFromFlags(ctx context.Context) (cloudapi.InputServiceFilter, error) {
gqlClient, err := cloudclientgql.NewClient(ctx)
if err != nil {
return cloudapi.InputServiceFilter{}, err
}

resolver := resourcesresolver.NewResolver(gqlClient)
if err := resolver.LoadOrgResources(ctx); err != nil {
return cloudapi.InputServiceFilter{}, err
}

filter := cloudapi.InputServiceFilter{}
if viper.IsSet(cli.ClustersKey) {
if err := resolver.LoadClusters(viper.GetStringSlice(cli.ClustersKey)); err != nil {
clusterIds, err := resolver.ResolveClusters(viper.GetStringSlice(cli.ClustersKey))
if err != nil {
return cloudapi.InputServiceFilter{}, err
}
filter.ClusterIds = toPtrIfNonEmpty(clusterIds)
}

if viper.IsSet(cli.EnvironmentsKey) {
if err := resolver.LoadEnvironments(viper.GetStringSlice(cli.EnvironmentsKey)); err != nil {
environmentIds, err := resolver.ResolveEnvironments(viper.GetStringSlice(cli.EnvironmentsKey))
if err != nil {
return cloudapi.InputServiceFilter{}, err
}
filter.EnvironmentIds = toPtrIfNonEmpty(environmentIds)
}

if viper.IsSet(cli.NamespacesKey) {
if err := resolver.LoadNamespaces(viper.GetStringSlice(cli.NamespacesKey)); err != nil {
namespaceIds, err := resolver.ResolveNamespaces(viper.GetStringSlice(cli.NamespacesKey))
if err != nil {
return cloudapi.InputServiceFilter{}, err
}
filter.NamespaceIds = toPtrIfNonEmpty(namespaceIds)
}

if viper.IsSet(cli.ServicesKey) {
if err := resolver.LoadServices(viper.GetStringSlice(cli.ServicesKey)); err != nil {
if err := resolver.LoadServices(ctx); err != nil {
return cloudapi.InputServiceFilter{}, err
}

serviceIds, err := resolver.ResolveServices(viper.GetStringSlice(cli.ServicesKey))
if err != nil {
return cloudapi.InputServiceFilter{}, err
}
filter.ServiceIds = toPtrIfNonEmpty(serviceIds)
}
return resolver.BuildServicesFilter(), nil
return filter, nil
}

func init() {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var LoginCmd = &cobra.Command{
prints.PrintCliStderr("Login completed successfully! logged in as: %s", authResult.Profile["email"])

apiAddress := viper.GetString(config.OtterizeAPIAddressKey)
loginCtx, err := userlogin.NewContext(apiAddress, authResult.AccessToken)
loginCtx, err := userlogin.NewContext(getConfCtxTimeout, apiAddress, authResult.AccessToken)
if err != nil {
return err
}
Expand Down
73 changes: 65 additions & 8 deletions src/pkg/cloudclient/graphql/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package graphql
import (
"context"
genqlientgraphql "github.com/Khan/genqlient/graphql"
"github.com/otterize/otterize-cli/src/pkg/cloudclient/auth"
"github.com/otterize/otterize-cli/src/pkg/cloudclient/graphql/cloudapi"
"github.com/otterize/otterize-cli/src/pkg/config"
"github.com/samber/lo"
"github.com/spf13/viper"
"golang.org/x/oauth2"
)

Expand All @@ -11,24 +16,76 @@ type Client struct {
Client genqlientgraphql.Client
}

func NewClientFromToken(address string, token string) *Client {
oauth2Token := &oauth2.Token{AccessToken: token}
return NewClient(address, oauth2.StaticTokenSource(oauth2Token))
func NewClient(ctx context.Context) (*Client, error) {
orgID, err := config.ResolveOrgID()
if err != nil {
return nil, err
}

token := auth.GetAPIToken(ctx)

return NewClientFromToken(ctx, viper.GetString(config.OtterizeAPIAddressKey), token, orgID), nil
}

func NewClientFromToken(ctx context.Context, address string, token string, organizationID string) *Client {
tokenSrc := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
return NewClientFromTokenSourceAndOrgID(ctx, address, tokenSrc, organizationID)
}

func NewClient(address string, tokenSrc oauth2.TokenSource) *Client {
func NewClientFromTokenSourceAndOrgID(ctx context.Context, address string, tokenSrc oauth2.TokenSource, orgID string) *Client {
address = address + "/graphql/v1beta"
oauth2client := oauth2.NewClient(ctx, tokenSrc)
client := HTTPClientWithSetOrgHeaderDoer{orgID: orgID, client: oauth2client}

return &Client{
Address: address,
Client: genqlientgraphql.NewClient(address, oauth2.NewClient(context.Background(), tokenSrc)),
Client: genqlientgraphql.NewClient(address, &client),
}
}

func (c *Client) RegisterAuth0User(ctx context.Context) (MeFields, error) {
createUserResponse, err := CreateUserFromAuth0User(ctx, c.Client)
func (c *Client) RegisterAuth0User(ctx context.Context) (cloudapi.MeFields, error) {
createUserResponse, err := cloudapi.CreateUserFromAuth0User(ctx, c.Client)
if err != nil {
return MeFields{}, err
return cloudapi.MeFields{}, err
}

return createUserResponse.Me.RegisterUser.MeFields, nil
}

type OrgResources struct {
Environments []cloudapi.MinimalEnvironmentFields
Clusters []cloudapi.MinimalClusterFields
Namespaces []cloudapi.MinimalNamespaceFields
}

func (c *Client) LoadOrgResources(ctx context.Context) (OrgResources, error) {
r := OrgResources{}

response, err := cloudapi.LoadOrgResources(ctx, c.Client)
if err != nil {
return r, err
}

r.Environments = lo.Map(response.Environments, func(e cloudapi.LoadOrgResourcesEnvironmentsEnvironment, _ int) cloudapi.MinimalEnvironmentFields {
return e.MinimalEnvironmentFields
})
r.Clusters = lo.Map(response.Clusters, func(c cloudapi.LoadOrgResourcesClustersCluster, _ int) cloudapi.MinimalClusterFields {
return c.MinimalClusterFields
})
r.Namespaces = lo.Map(response.Namespaces, func(ns cloudapi.LoadOrgResourcesNamespacesNamespace, _ int) cloudapi.MinimalNamespaceFields {
return ns.MinimalNamespaceFields
})

return r, nil
}

func (c *Client) ListServices(ctx context.Context) ([]cloudapi.MinimalServiceFields, error) {
response, err := cloudapi.ListServices(ctx, c.Client)
if err != nil {
return nil, err
}

return lo.Map(response.Services, func(s cloudapi.ListServicesServicesService, _ int) cloudapi.MinimalServiceFields {
return s.MinimalServiceFields
}), nil
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package graphql
package cloudapi

import _ "github.com/suessflorian/gqlfetch"

Expand Down
Loading
Loading