Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

Commit

Permalink
fix: Use resourceHandler from apiv2 package instead of newly creating…
Browse files Browse the repository at this point in the history
… an internal-only, unauthenticated client (#535)

* fix: Use resourceHandler from apiv2 package which uses to pass through proper api authentication

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

* adapted unit tests

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

* updated example

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

* updated readme

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

* handle error

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

* fixed unit test

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

* pr review

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
  • Loading branch information
bacherfl committed Aug 31, 2022
1 parent dc8c096 commit f07eb2f
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 372 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The recommended way of accessing the Keptn API using `GO` is to use the `APISet`
You can use it by importing the following package:

```golang
import api "github.com/keptn/go-utils/pkg/api/utils"
import api "github.com/keptn/go-utils/pkg/api/utils/v2"
```

Then you need to create an `APISet` and provide it the information about
Expand All @@ -64,7 +64,7 @@ log.Fatal(err)
Once you have a handle to the `APISet` you can start using it:

```go
resources, err := keptnAPI.ResourcesV1().GetAllServiceResources("my-project", "my-stage", "my-service")
resources, err := keptnAPI.Resources().GetAllServiceResources(context.TODO(), "my-project", "my-stage", "my-service", api.ResourcesGetAllServiceResourcesOptions{})
if err != nil {
log.Fatal(err)
}
Expand All @@ -78,7 +78,7 @@ there is no need to talk to the Keptn API via the API gateway. In this case one
Import the following package:

```go
import api "github.com/keptn/go-utils/pkg/api/utils"
import api "github.com/keptn/go-utils/pkg/api/utils/v2"
```

Then create an `InternalAPISet`. Note, that this does *not* require you to pass the URL to the keptn API or an API token
Expand Down Expand Up @@ -136,13 +136,13 @@ Events can be retrieved from Keptn by using the event API of the `APISet`.
apiSet, _ := api.New("http://<keptn-url>/api", api.WithAuthToken("<api-token>"))

// Getting all events for a specific project
events, _ := apiSet.EventsV1().GetEvents(&api.EventFilter{Project: "echo-project"})
events, _ := apiSet.Events().GetEvents(context.TODO(), &api.EventFilter{Project: "echo-project"}, api.EventsGetEventsOptions{})

// Getting all event matching a specific keptn context
events, _ = apiSet.EventsV1().GetEvents(&api.EventFilter{KeptnContext: "7d4ca79a-6f38-4b88-9139-433342e350bf",})
events, _ = apiSet.Events().GetEvents(context.TODO(), &api.EventFilter{KeptnContext: "7d4ca79a-6f38-4b88-9139-433342e350bf"}, api.EventsGetEventsOptions{})

// Getting all .triggered events that are "not yet processed" by a keptn integration for a specific project
events, _ = apiSet.ShipyardControlV1().GetOpenTriggeredEvents(api.EventFilter{Project: "echo-project"})
events, _ = apiSet.ShipyardControl().GetOpenTriggeredEvents(context.TODO(), api.EventFilter{Project: "echo-project"}, api.ShipyardControlGetOpenTriggeredEventsOptions{})
```

## Ingesting Keptn events
Expand All @@ -164,7 +164,7 @@ eventToSend, _ := lib.KeptnEvent(lib.GetStartedEventType("echo-task"), "my-servi
}).Build()

// Sending the event to Keptn
eventContext, _ := apiSet.APIV1().SendEvent(eventToSend)
eventContext, _ := apiSet.API().SendEvent(context.TODO(), eventToSend, api.APISendEventOptions{})
fmt.Println(*eventContext.KeptnContext)
```

Expand Down
8 changes: 4 additions & 4 deletions examples/go-sdk/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.0 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
349 changes: 9 additions & 340 deletions examples/go-sdk/go.sum

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions examples/go-sdk/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package main

import (
"bytes"
api "github.com/keptn/go-utils/pkg/api/utils"
"github.com/keptn/go-utils/pkg/lib/v0_2_0"
"github.com/keptn/go-utils/pkg/sdk"
"github.com/sirupsen/logrus"
"html/template"
)

Expand Down Expand Up @@ -36,10 +38,18 @@ func (g *GreetingsHandler) Execute(k sdk.IKeptn, event sdk.KeptnEvent) (interfac
return nil, &sdk.Error{Err: err, StatusType: v0_2_0.StatusErrored, ResultType: v0_2_0.ResultFailed, Message: "Could not parse greeting message"}
}

resource, err := k.GetResourceHandler().GetResource(*(api.NewResourceScope().Project(greetingsTriggeredData.GetProject()).Resource("my-resource.yaml")))
if err != nil {
return nil, &sdk.Error{Err: err, StatusType: v0_2_0.StatusErrored, ResultType: v0_2_0.ResultFailed, Message: "Could not retrieve resource"}
}

logrus.Infof("Resource content: %s", resource.ResourceContent)

var greetMessage bytes.Buffer
if err = tmpl.Execute(&greetMessage, name); err != nil {
return nil, &sdk.Error{Err: err, StatusType: v0_2_0.StatusErrored, ResultType: v0_2_0.ResultFailed, Message: "Could not parse process greeting message"}
}

finishedEventData := GreetingFinishedData{
EventData: greetingsTriggeredData.EventData,
GreetMessage: greetMessage.String(),
Expand Down
3 changes: 3 additions & 0 deletions examples/go-sdk/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (

func Test_Handler(t *testing.T) {
fakeKeptn := sdk.NewFakeKeptn("test-greeting-svc")
fakeKeptn.SetResourceHandler(&sdk.StringResourceHandler{
ResourceContent: "my-resource",
})
fakeKeptn.AddTaskHandler(greetingsTriggeredEventType, NewGreetingsHandler())
fakeKeptn.NewEvent(newNewGreetingTriggeredEvent("test-assets/events/greeting.triggered-0.json"))
fakeKeptn.AssertNumberOfEventSent(t, 2)
Expand Down
20 changes: 20 additions & 0 deletions pkg/api/utils/resourceUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,26 @@ func (s *ResourceScope) Resource(resource string) *ResourceScope {
return s
}

// GetProject returns the project name
func (s *ResourceScope) GetProject() string {
return s.project
}

// GetStage returns the stage name
func (s *ResourceScope) GetStage() string {
return s.stage
}

// GetService returns the service name
func (s *ResourceScope) GetService() string {
return s.service
}

// GetResource returns the resource name
func (s *ResourceScope) GetResource() string {
return s.resource
}

// GetProjectPath returns a string to construct the url to path eg. /<api-version>/project/<project-name>
//or an empty string if the project is not set
func (s *ResourceScope) GetProjectPath() string {
Expand Down
53 changes: 36 additions & 17 deletions pkg/sdk/internal/api/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/benbjohnson/clock"
keptnapi "github.com/keptn/go-utils/pkg/api/utils"
keptnapiv2 "github.com/keptn/go-utils/pkg/api/utils/v2"
"github.com/keptn/go-utils/pkg/sdk/connector/controlplane"
"github.com/keptn/go-utils/pkg/sdk/connector/eventsource"
eventsourceHttp "github.com/keptn/go-utils/pkg/sdk/connector/eventsource/http"
Expand All @@ -20,9 +21,9 @@ import (

type InitializationResult struct {
KeptnAPI keptnapi.KeptnInterface
KeptnAPIV2 keptnapiv2.KeptnInterface
ControlPlane *controlplane.ControlPlane
EventSenderCallback controlplane.EventSender
ResourceHandler *keptnapi.ResourceHandler
}

// Initialize takes care of creating the API clients and initializing the cp-connector library based
Expand All @@ -43,43 +44,64 @@ func Initialize(env config.EnvConfig, clientFactory HTTPClientGetter, logger log
if err != nil {
return nil, fmt.Errorf("could not initialize control plane client api: %w", err)
}

apiV2, err := apiSetV2(env, httpClient)
if err != nil {
return nil, fmt.Errorf("could not initialize v2 control plane client api: %w", err)
}

// initialize api handlers and cp-connector components
resourceHandler := resourceHandler(env)
ss, es, lf := createCPComponents(api, logger, env)
controlPlane := controlplane.New(ss, es, lf, controlplane.WithLogger(logger))

return &InitializationResult{
KeptnAPI: api,
KeptnAPIV2: apiV2,
ControlPlane: controlPlane,
EventSenderCallback: es.Sender(),
ResourceHandler: resourceHandler,
}, nil

}

func apiSet(env config.EnvConfig, httpClient *http.Client) (keptnapi.KeptnInterface, error) {

if env.PubSubConnectionType() == config.ConnectionTypeHTTP {
scheme := "http"
parsed, err := url.ParseRequestURI(env.KeptnAPIEndpoint)
scheme, err := getHttpScheme(env)
if err != nil {
return nil, fmt.Errorf("could not parse given Keptn API endpoint: %w", err)
return nil, err
}
return keptnapi.New(env.KeptnAPIEndpoint, keptnapi.WithScheme(scheme), keptnapi.WithHTTPClient(httpClient), keptnapi.WithAuthToken(env.KeptnAPIToken))

if parsed.Scheme == "" || !strings.HasPrefix(parsed.Scheme, "http") {
return nil, fmt.Errorf("invalid scheme for keptn endpoint, %s is not http or https", env.KeptnAPIEndpoint)
}
}
return keptnapi.NewInternal(httpClient)

if strings.HasPrefix(parsed.Scheme, "http") {
scheme = parsed.Scheme
}

func apiSetV2(env config.EnvConfig, httpClient *http.Client) (keptnapiv2.KeptnInterface, error) {
if env.PubSubConnectionType() == config.ConnectionTypeHTTP {
scheme, err := getHttpScheme(env)
if err != nil {
return nil, err
}
return keptnapi.New(env.KeptnAPIEndpoint, keptnapi.WithScheme(scheme), keptnapi.WithHTTPClient(httpClient), keptnapi.WithAuthToken(env.KeptnAPIToken))
return keptnapiv2.New(env.KeptnAPIEndpoint, keptnapiv2.WithScheme(scheme), keptnapiv2.WithHTTPClient(httpClient), keptnapiv2.WithAuthToken(env.KeptnAPIToken))

}
return keptnapi.NewInternal(httpClient)
return keptnapiv2.NewInternal(httpClient)

}

func getHttpScheme(env config.EnvConfig) (string, error) {
parsed, err := url.ParseRequestURI(env.KeptnAPIEndpoint)
if err != nil {
return "", fmt.Errorf("could not parse given Keptn API endpoint: %w", err)
}

if !strings.HasPrefix(parsed.Scheme, "http") {
return "", fmt.Errorf("invalid scheme for keptn endpoint, %s is not http or https", env.KeptnAPIEndpoint)
}

return parsed.Scheme, nil
}

func eventSource(apiSet keptnapi.KeptnInterface, logger logger.Logger, env config.EnvConfig) eventsource.EventSource {
if env.PubSubConnectionType() == config.ConnectionTypeHTTP {
return eventsourceHttp.New(clock.New(), eventsourceHttp.NewEventAPI(apiSet.ShipyardControlV1(), apiSet.APIV1()))
Expand All @@ -99,6 +121,3 @@ func logForwarder(apiSet keptnapi.KeptnInterface, logger logger.Logger) logforwa
func createCPComponents(apiSet keptnapi.KeptnInterface, logger logger.Logger, env config.EnvConfig) (subscriptionsource.SubscriptionSource, eventsource.EventSource, logforwarder.LogForwarder) {
return subscriptionSource(apiSet, logger), eventSource(apiSet, logger, env), logForwarder(apiSet, logger)
}
func resourceHandler(env config.EnvConfig) *keptnapi.ResourceHandler {
return keptnapi.NewResourceHandler(env.ConfigurationServiceURL)
}
10 changes: 7 additions & 3 deletions pkg/sdk/internal/api/initializer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"fmt"
keptnapi "github.com/keptn/go-utils/pkg/api/utils"
keptnapiv2 "github.com/keptn/go-utils/pkg/api/utils/v2"
"github.com/keptn/go-utils/pkg/sdk/connector/logger"
"github.com/keptn/go-utils/pkg/sdk/internal/config"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -40,7 +41,8 @@ func Test_Initialize(t *testing.T) {
require.NotNil(t, result.EventSenderCallback)
require.NotNil(t, result.KeptnAPI)
require.IsType(t, &keptnapi.APISet{}, result.KeptnAPI)
require.NotNil(t, result.ResourceHandler)
require.NotNil(t, result.KeptnAPIV2)
require.IsType(t, &keptnapiv2.APISet{}, result.KeptnAPIV2)
})
t.Run("Internal Use case - internal api set is used", func(t *testing.T) {
env := config.EnvConfig{}
Expand All @@ -50,7 +52,8 @@ func Test_Initialize(t *testing.T) {
require.NotNil(t, result.EventSenderCallback)
require.NotNil(t, result.KeptnAPI)
require.IsType(t, &keptnapi.InternalAPISet{}, result.KeptnAPI)
require.NotNil(t, result.ResourceHandler)
require.NotNil(t, result.KeptnAPIV2)
require.IsType(t, &keptnapiv2.InternalAPISet{}, result.KeptnAPIV2)
})
t.Run("HTTP client creation fails", func(t *testing.T) {
env := config.EnvConfig{KeptnAPIEndpoint: "http://endpoint"}
Expand All @@ -66,6 +69,7 @@ func Test_Initialize(t *testing.T) {
require.NotNil(t, result.EventSenderCallback)
require.NotNil(t, result.KeptnAPI)
require.IsType(t, &keptnapi.APISet{}, result.KeptnAPI)
require.NotNil(t, result.ResourceHandler)
require.NotNil(t, result.KeptnAPIV2)
require.IsType(t, &keptnapiv2.APISet{}, result.KeptnAPIV2)
})
}
24 changes: 23 additions & 1 deletion pkg/sdk/keptn.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/kelseyhightower/envconfig"
"github.com/keptn/go-utils/pkg/api/models"
api "github.com/keptn/go-utils/pkg/api/utils"
apiv2 "github.com/keptn/go-utils/pkg/api/utils/v2"
keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0"
"github.com/keptn/go-utils/pkg/sdk/connector/controlplane"
)
Expand Down Expand Up @@ -45,6 +46,8 @@ type IKeptn interface {
Logger() Logger
// APIV1 returns API utils for all Keptn APIs
APIV1() api.KeptnInterface
// APIV2 returns API utils for all v2 Keptn APIs
APIV2() apiv2.KeptnInterface
}

type TaskHandler interface {
Expand Down Expand Up @@ -76,6 +79,16 @@ type ResourceHandler interface {
GetResource(scope api.ResourceScope, options ...api.URIOption) (*models.Resource, error)
}

type resourceHandlerWrapper struct {
resourceHandler apiv2.ResourcesInterface
}

func (rhw *resourceHandlerWrapper) GetResource(scope api.ResourceScope, options ...api.URIOption) (*models.Resource, error) {
v2Scope := apiv2.NewResourceScope().Project(scope.GetProject()).Stage(scope.GetStage()).Service(scope.GetService()).Resource(scope.GetResource())

return rhw.resourceHandler.GetResource(context.Background(), *v2Scope, apiv2.ResourcesGetResourceOptions{})
}

type healthEndpointRunner func(port string, cp *controlplane.ControlPlane)

// Opaque key type used for graceful shutdown context value
Expand Down Expand Up @@ -139,6 +152,7 @@ type Keptn struct {
eventSender controlplane.EventSender
resourceHandler ResourceHandler
api api.KeptnInterface
apiV2 apiv2.KeptnInterface
source string
taskRegistry *taskRegistry
syncProcessing bool
Expand Down Expand Up @@ -178,9 +192,10 @@ func NewKeptn(source string, opts ...KeptnOption) *Keptn {
}

keptn.api = initializationResult.KeptnAPI
keptn.apiV2 = initializationResult.KeptnAPIV2
keptn.controlPlane = initializationResult.ControlPlane
keptn.eventSender = initializationResult.EventSenderCallback
keptn.resourceHandler = initializationResult.ResourceHandler
keptn.resourceHandler = &resourceHandlerWrapper{resourceHandler: initializationResult.KeptnAPIV2.Resources()}

return keptn
}
Expand Down Expand Up @@ -344,10 +359,17 @@ func (k *Keptn) SendFinishedEvent(parentEvent KeptnEvent, newEventData interface
return k.eventSender(*finishedEvent)
}

// APIV1 retrieves the APIV1 client
// Deprecated use APIV2 instead
func (k *Keptn) APIV1() api.KeptnInterface {
return k.api
}

// APIV2 retrieves the APIV2 client
func (k *Keptn) APIV2() apiv2.KeptnInterface {
return k.apiV2
}

func (k *Keptn) Logger() Logger {
return k.logger
}
Expand Down
1 change: 1 addition & 0 deletions pkg/sdk/keptn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func Test_NewKeptn(t *testing.T) {
require.IsType(t, keptnSDK.taskRegistry.Get("event2.type").taskHandler, &TaskHandlerMock{})
require.NotNil(t, keptnSDK.GetResourceHandler())
require.NotNil(t, keptnSDK.APIV1())
require.NotNil(t, keptnSDK.APIV2())

})
}
Expand Down

0 comments on commit f07eb2f

Please sign in to comment.