Skip to content

Commit

Permalink
Merge pull request #2 from swisscom/interface
Browse files Browse the repository at this point in the history
add client interfaces
  • Loading branch information
janwillies authored Sep 13, 2023
2 parents 1a5fac2 + 85a454d commit e440996
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 61 deletions.
26 changes: 26 additions & 0 deletions internal/clients/alertmanager/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Copyright 2023 The Crossplane 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 alertmanager

import (
"context"
)

type AlertManagerClient interface {
GetAlertmanagerConfig(ctx context.Context) (string, map[string]string, error)
CreateAlertmanagerConfig(ctx context.Context, cfg string, templates map[string]string) error
DeleteAlermanagerConfig(ctx context.Context) error
}
18 changes: 13 additions & 5 deletions internal/clients/cortex.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ import (
"github.com/crossplane/provider-cortex/apis/v1alpha1"
)

type Config struct {
cortexClient.Config
}

// NewClient creates new Cortex Client with provided Cortex Configurations.
func NewClient(config cortexClient.Config) *cortexClient.CortexClient {
client, err := cortexClient.New(config)
func NewClient(config Config) *cortexClient.CortexClient {
client, err := cortexClient.New(cortexClient.Config{
Address: config.Address,
ID: config.ID,
})

if err != nil {
fmt.Printf("Could not initialize cortex client: %v", err)
Expand All @@ -24,7 +31,7 @@ func NewClient(config cortexClient.Config) *cortexClient.CortexClient {
}

// GetConfig constructs a Config that can be used to authenticate to Cortex
func GetConfig(ctx context.Context, c client.Client, mg resource.Managed) (*cortexClient.Config, error) {
func GetConfig(ctx context.Context, c client.Client, mg resource.Managed) (*Config, error) {
switch {
case mg.GetProviderConfigReference() != nil:
return UseProviderConfig(ctx, c, mg)
Expand All @@ -34,7 +41,7 @@ func GetConfig(ctx context.Context, c client.Client, mg resource.Managed) (*cort
}

// UseProviderConfig to produce a config that can be used to authenticate to Cortex.
func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed) (*cortexClient.Config, error) {
func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed) (*Config, error) {
pc := &v1alpha1.ProviderConfig{}
if err := c.Get(ctx, types.NamespacedName{Name: mg.GetProviderConfigReference().Name}, pc); err != nil {
return nil, errors.Wrap(err, "cannot get referenced Provider")
Expand All @@ -45,7 +52,8 @@ func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed
return nil, errors.Wrap(err, "cannot track ProviderConfig usage")
}

return &cortexClient.Config{ID: pc.Spec.TenantID, Address: pc.Spec.Address}, nil
// return &Config{}, nil
return &Config{cortexClient.Config{ID: pc.Spec.TenantID, Address: pc.Spec.Address}}, nil

// switch s := pc.Spec.Credentials.Source; s { //nolint:exhaustive
// case xpv1.CredentialsSourceSecret:
Expand Down
28 changes: 28 additions & 0 deletions internal/clients/rulegroups/rulegroup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright 2023 The Crossplane 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 rulegroups

import (
"context"

"github.com/cortexproject/cortex-tools/pkg/rules/rwrulefmt"
)

type RuleGroupClient interface {
GetRuleGroup(ctx context.Context, namespace string, groupName string) (*rwrulefmt.RuleGroup, error)
CreateRuleGroup(ctx context.Context, namespace string, rg rwrulefmt.RuleGroup) error
DeleteRuleGroup(ctx context.Context, namespace string, groupName string) error
}
12 changes: 8 additions & 4 deletions internal/controller/alertmanager/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

cortexClient "github.com/cortexproject/cortex-tools/pkg/client"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
"github.com/crossplane/crossplane-runtime/pkg/connection"
"github.com/crossplane/crossplane-runtime/pkg/controller"
Expand All @@ -37,6 +36,7 @@ import (
"github.com/crossplane/provider-cortex/apis/alerts/v1alpha1"
apisv1alpha1 "github.com/crossplane/provider-cortex/apis/v1alpha1"
xpClient "github.com/crossplane/provider-cortex/internal/clients"
"github.com/crossplane/provider-cortex/internal/clients/alertmanager"
"github.com/crossplane/provider-cortex/internal/features"
)

Expand Down Expand Up @@ -64,7 +64,7 @@ func Setup(mgr ctrl.Manager, o controller.Options) error {
managed.WithExternalConnecter(&connector{
kube: mgr.GetClient(),
usage: resource.NewProviderConfigUsageTracker(mgr.GetClient(), &apisv1alpha1.ProviderConfigUsage{}),
newServiceFn: xpClient.NewClient}),
newServiceFn: newAlertManagerClient}),
// managed.NewNameAsExternalName(c)
managed.WithLogger(o.Logger.WithValues("controller", name)),
managed.WithPollInterval(o.PollInterval),
Expand All @@ -84,7 +84,11 @@ func Setup(mgr ctrl.Manager, o controller.Options) error {
type connector struct {
kube client.Client
usage resource.Tracker
newServiceFn func(config cortexClient.Config) *cortexClient.CortexClient
newServiceFn func(config xpClient.Config) alertmanager.AlertManagerClient
}

func newAlertManagerClient(config xpClient.Config) alertmanager.AlertManagerClient {
return xpClient.NewClient(config)
}

// Connect typically produces an ExternalClient by:
Expand Down Expand Up @@ -119,7 +123,7 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E
// external resource to ensure it reflects the managed resource's desired state.
type external struct {
// A 'client' used to connect to the external resource API
service *cortexClient.CortexClient
service alertmanager.AlertManagerClient
}

func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) {
Expand Down
74 changes: 74 additions & 0 deletions internal/controller/alertmanager/configuration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
Copyright 2022 The Crossplane 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 alertmanager

import (
"context"
"testing"

"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane/crossplane-runtime/pkg/test"
"github.com/crossplane/provider-cortex/internal/clients/alertmanager"
"github.com/google/go-cmp/cmp"
)

// Unlike many Kubernetes projects Crossplane does not use third party testing
// libraries, per the common Go test review comments. Crossplane encourages the
// use of table driven unit tests. The tests of the crossplane-runtime project
// are representative of the testing style Crossplane encourages.
//
// https://github.com/golang/go/wiki/TestComments
// https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md#contributing-code

func TestObserve(t *testing.T) {
type fields struct {
service alertmanager.AlertManagerClient
}

type args struct {
ctx context.Context
mg resource.Managed
}

type want struct {
o managed.ExternalObservation
err error
}

cases := map[string]struct {
reason string
fields fields
args args
want want
}{
// TODO: Add test cases.
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
e := external{service: tc.fields.service}
got, err := e.Observe(tc.args.ctx, tc.args.mg)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\ne.Observe(...): -want error, +got error:\n%s\n", tc.reason, diff)
}
if diff := cmp.Diff(tc.want.o, got); diff != "" {
t.Errorf("\n%s\ne.Observe(...): -want, +got:\n%s\n", tc.reason, diff)
}
})
}
}
20 changes: 10 additions & 10 deletions internal/controller/rulegroup/rulegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

cortexClient "github.com/cortexproject/cortex-tools/pkg/client"
"github.com/cortexproject/cortex-tools/pkg/rules/rwrulefmt"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
"github.com/crossplane/crossplane-runtime/pkg/connection"
Expand All @@ -43,6 +42,7 @@ import (
"github.com/crossplane/provider-cortex/apis/rules/v1alpha1"
apisv1alpha1 "github.com/crossplane/provider-cortex/apis/v1alpha1"
xpClient "github.com/crossplane/provider-cortex/internal/clients"
"github.com/crossplane/provider-cortex/internal/clients/rulegroups"
"github.com/crossplane/provider-cortex/internal/features"
)

Expand Down Expand Up @@ -70,7 +70,8 @@ func Setup(mgr ctrl.Manager, o controller.Options) error {
managed.WithExternalConnecter(&connector{
kube: mgr.GetClient(),
usage: resource.NewProviderConfigUsageTracker(mgr.GetClient(), &apisv1alpha1.ProviderConfigUsage{}),
newServiceFn: xpClient.NewClient}),
newServiceFn: newRuleGroupClient}),
// newServiceFn: xpClient.NewClient}),
// managed.NewNameAsExternalName(c)
managed.WithLogger(o.Logger.WithValues("controller", name)),
managed.WithPollInterval(o.PollInterval),
Expand All @@ -90,7 +91,11 @@ func Setup(mgr ctrl.Manager, o controller.Options) error {
type connector struct {
kube client.Client
usage resource.Tracker
newServiceFn func(config cortexClient.Config) *cortexClient.CortexClient
newServiceFn func(config xpClient.Config) rulegroups.RuleGroupClient
}

func newRuleGroupClient(config xpClient.Config) rulegroups.RuleGroupClient {
return xpClient.NewClient(config)
}

// Connect typically produces an ExternalClient by:
Expand Down Expand Up @@ -125,7 +130,7 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E
// external resource to ensure it reflects the managed resource's desired state.
type external struct {
// A 'client' used to connect to the external resource API
service *cortexClient.CortexClient
service rulegroups.RuleGroupClient
}

func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) {
Expand All @@ -134,12 +139,6 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex
return managed.ExternalObservation{}, errors.New(errNotRuleGroup)
}

// if meta.GetExternalName(cr) == "" {
// return managed.ExternalObservation{
// ResourceExists: false,
// }, nil
// }

observedRuleGroup, err := c.service.GetRuleGroup(ctx, cr.Spec.ForProvider.Namespace, meta.GetExternalName(cr))
if err != nil {
switch {
Expand Down Expand Up @@ -280,6 +279,7 @@ func (c *external) Delete(ctx context.Context, mg resource.Managed) error {
return errors.Wrap(err, "")
}

//gocyclo:ignore
func isUpToDate(cr *v1alpha1.RuleGroup, observedRuleGroup *rwrulefmt.RuleGroup) bool {
if cr == nil || observedRuleGroup == nil {
return false
Expand Down
85 changes: 48 additions & 37 deletions internal/controller/rulegroup/rulegroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ limitations under the License.

package rulegroup

import (
"context"
"testing"

"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane/crossplane-runtime/pkg/test"
"github.com/crossplane/provider-cortex/internal/clients/rulegroups"
"github.com/google/go-cmp/cmp"
)

// Unlike many Kubernetes projects Crossplane does not use third party testing
// libraries, per the common Go test review comments. Crossplane encourages the
// use of table driven unit tests. The tests of the crossplane-runtime project
Expand All @@ -24,40 +35,40 @@ package rulegroup
// https://github.com/golang/go/wiki/TestComments
// https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md#contributing-code

// func TestObserve(t *testing.T) {
// type fields struct {
// service interface{}
// }

// type args struct {
// ctx context.Context
// mg resource.Managed
// }

// type want struct {
// o managed.ExternalObservation
// err error
// }

// cases := map[string]struct {
// reason string
// fields fields
// args args
// want want
// }{
// // TODO: Add test cases.
// }

// for name, tc := range cases {
// t.Run(name, func(t *testing.T) {
// e := external{service: tc.fields.service}
// got, err := e.Observe(tc.args.ctx, tc.args.mg)
// if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
// t.Errorf("\n%s\ne.Observe(...): -want error, +got error:\n%s\n", tc.reason, diff)
// }
// if diff := cmp.Diff(tc.want.o, got); diff != "" {
// t.Errorf("\n%s\ne.Observe(...): -want, +got:\n%s\n", tc.reason, diff)
// }
// })
// }
// }
func TestObserve(t *testing.T) {
type fields struct {
service rulegroups.RuleGroupClient
}

type args struct {
ctx context.Context
mg resource.Managed
}

type want struct {
o managed.ExternalObservation
err error
}

cases := map[string]struct {
reason string
fields fields
args args
want want
}{
// TODO: Add test cases.
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
e := external{service: tc.fields.service}
got, err := e.Observe(tc.args.ctx, tc.args.mg)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\ne.Observe(...): -want error, +got error:\n%s\n", tc.reason, diff)
}
if diff := cmp.Diff(tc.want.o, got); diff != "" {
t.Errorf("\n%s\ne.Observe(...): -want, +got:\n%s\n", tc.reason, diff)
}
})
}
}
Loading

0 comments on commit e440996

Please sign in to comment.