Skip to content
This repository has been archived by the owner on Oct 11, 2019. It is now read-only.

Commit

Permalink
VYGR-391: Create OpsGenie integrations secret during sync
Browse files Browse the repository at this point in the history
  • Loading branch information
fraser-atlassian committed Feb 13, 2019
1 parent ba30f9d commit 005de8c
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 14 deletions.
1 change: 1 addition & 0 deletions cmd/synchronization/app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_library(
"//pkg/composition/client:go_default_library",
"//pkg/k8s:go_default_library",
"//pkg/k8s/updater:go_default_library",
"//pkg/opsgenie:go_default_library",
"//pkg/options:go_default_library",
"//pkg/releases:go_default_library",
"//pkg/releases/deployinator/client:go_default_library",
Expand Down
6 changes: 6 additions & 0 deletions cmd/synchronization/app/controller_constructor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
comp_v1_client "github.com/atlassian/voyager/pkg/composition/client"
"github.com/atlassian/voyager/pkg/k8s"
"github.com/atlassian/voyager/pkg/k8s/updater"
"github.com/atlassian/voyager/pkg/opsgenie"
"github.com/atlassian/voyager/pkg/releases"
"github.com/atlassian/voyager/pkg/releases/deployinator/client"
"github.com/atlassian/voyager/pkg/servicecentral"
Expand Down Expand Up @@ -79,6 +80,10 @@ func (cc *ControllerConstructor) New(config *ctrl.Config, cctx *ctrl.Context) (*
scHTTPClient := util.HTTPClient()
scClient := servicecentral.NewServiceCentralClient(config.Logger, scHTTPClient, opts.ASAPClientConfig, opts.Providers.ServiceCentralURL)

// create a client for talking to OpsGenie Integration Manager
ogHTTPClient := util.HTTPClient()
ogClient := opsgenie.New(config.Logger, ogHTTPClient, opts.ASAPClientConfig, opts.Providers.OpsgenieIntegrationsManagerURL)

scErrorCounter := prometheus.NewCounter(
prometheus.CounterOpts{
Namespace: config.AppName,
Expand Down Expand Up @@ -133,6 +138,7 @@ func (cc *ControllerConstructor) New(config *ctrl.Config, cctx *ctrl.Context) (*
ServiceCentral: servicecentral.NewStore(config.Logger, scClient),
ReleaseManagement: releases.NewReleaseManagement(deployinatorHTTPClient, config.Logger),
ClusterLocation: opts.Location.ClusterLocation(),
OpsGenie: ogClient,

ConfigMapUpdater: configMapObjectUpdater,
RoleBindingUpdater: roleBindingObjectUpdater,
Expand Down
26 changes: 21 additions & 5 deletions cmd/synchronization/app/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ type Options struct {
}

type Providers struct {
ServiceCentralURL *url.URL // we use custom json marshalling to read it
DeployinatorURL *url.URL
ServiceCentralURL *url.URL // we use custom json marshalling to read it
DeployinatorURL *url.URL
OpsgenieIntegrationsManagerURL *url.URL
}

// UnmarshalJSON unmarshals our untyped config file into a typed struct including URLs
func (p *Providers) UnmarshalJSON(data []byte) error {
var rawProviders struct {
ServiceCentral string `json:"serviceCentral"`
Deployinator string `json:"deployinator"`
ServiceCentral string `json:"serviceCentral"`
Deployinator string `json:"deployinator"`
OpsgenieIntegrationsManager string `json:"opsgenieIntegrationsManager"`
}

if err := json.Unmarshal(data, &rawProviders); err != nil {
Expand All @@ -43,7 +45,17 @@ func (p *Providers) UnmarshalJSON(data []byte) error {
}
depURL, err := url.Parse(rawProviders.Deployinator)
p.DeployinatorURL = depURL
return errors.Wrap(err, "unable to parse Deployinator URL")
if err != nil {
return errors.Wrap(err, "unable to parse Deployinator URL")
}

ogUrl, err := url.Parse(rawProviders.OpsgenieIntegrationsManager)
if err != nil {
return errors.Wrap(err, "unable to parse OpsGenie Integrations Manager URL")
}
p.OpsgenieIntegrationsManagerURL = ogUrl

return nil
}

func (o *Options) DefaultAndValidate() []error {
Expand All @@ -54,6 +66,10 @@ func (o *Options) DefaultAndValidate() []error {
allErrors = append(allErrors, errors.New("providers.serviceCentral must be a valid URL"))
}

if o.Providers.OpsgenieIntegrationsManagerURL == nil {
allErrors = append(allErrors, errors.New("providers.OpsgenieIntegrationsManagerURL must be a valid URL"))
}

return allErrors
}

Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/creator/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func (ss *ServiceSpec) EmailAddress() string {
// +k8s:deepcopy-gen=true
type ServiceMetadata struct {
PagerDuty *PagerDutyMetadata `json:"pagerDuty,omitempty"`
OpsGenie *OpsGenieMetadata `json:"opsGenie,omitempty"`
Bamboo *BambooMetadata `json:"bamboo,omitempty"`
}

Expand Down Expand Up @@ -100,6 +101,10 @@ type PagerDutyIntegrationMetadata struct {
IntegrationKey string `json:"integrationKey,omitempty"`
}

type OpsGenieMetadata struct {
Team string `json:"team,omitempty"`
}

// +k8s:deepcopy-gen=true
type Compliance struct {
PRGBControl *bool `json:"prgbControl,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion pkg/opsgenie/it/client_manual_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/atlassian/voyager/pkg/util/pkiutil"
"github.com/atlassian/voyager/pkg/util/testutil"
"github.com/stretchr/testify/require"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes/scheme"
)

Expand Down
1 change: 1 addition & 0 deletions pkg/synchronization/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ go_library(
"//pkg/composition/client:go_default_library",
"//pkg/k8s:go_default_library",
"//pkg/k8s/updater:go_default_library",
"//pkg/opsgenie:go_default_library",
"//pkg/orchestration/wiring/k8scompute/api:go_default_library",
"//pkg/pagerduty:go_default_library",
"//pkg/releases:go_default_library",
Expand Down
61 changes: 54 additions & 7 deletions pkg/synchronization/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
compClient "github.com/atlassian/voyager/pkg/composition/client"
"github.com/atlassian/voyager/pkg/k8s"
"github.com/atlassian/voyager/pkg/k8s/updater"
"github.com/atlassian/voyager/pkg/opsgenie"
apik8scompute "github.com/atlassian/voyager/pkg/orchestration/wiring/k8scompute/api"
"github.com/atlassian/voyager/pkg/pagerduty"
"github.com/atlassian/voyager/pkg/releases"
Expand Down Expand Up @@ -58,13 +59,15 @@ const (
)

const (
serviceCentralPollPeriod = 30 * time.Second
serviceCentralListAllPeriod = 30 * time.Minute
serviceCentralListDriftCompensation = 5 * time.Second
releaseManagementPollPeriod = 5 * time.Second
releaseManagementSyncAllPeriod = 30 * time.Minute
baseDelayProcSec = 15
rmsPollJitterFactor = 1.2
serviceCentralPollPeriod = 30 * time.Second
serviceCentralListAllPeriod = 30 * time.Minute
serviceCentralListDriftCompensation = 5 * time.Second
releaseManagementPollPeriod = 5 * time.Second
releaseManagementSyncAllPeriod = 30 * time.Minute
baseDelayProcSec = 15
rmsPollJitterFactor = 1.2
secretTypeOpsGenie core_v1.SecretType = voyager.Domain + "/opsgenie"
secretNameOpsGenie = "opsgenie-integrations"
)

type ServiceMetadataStore interface {
Expand All @@ -73,6 +76,10 @@ type ServiceMetadataStore interface {
ListModifiedServices(ctx context.Context, user auth.OptionalUser, modifiedSince time.Time) ([]creator_v1.Service, error)
}

type OpsGenieIntegrationManagerClient interface {
GetOrCreateIntegrations(ctx context.Context, teamName string) (*opsgenie.IntegrationsResponse, bool /* retriable */, error)
}

type Controller struct {
Logger *zap.Logger
ReadyForWork func()
Expand All @@ -85,6 +92,7 @@ type Controller struct {
ServiceCentral ServiceMetadataStore
ReleaseManagement releases.ReleaseManagementStore
ClusterLocation voyager.ClusterLocation
OpsGenie OpsGenieIntegrationManagerClient

RoleBindingUpdater updater.ObjectUpdater
ConfigMapUpdater updater.ObjectUpdater
Expand Down Expand Up @@ -439,6 +447,22 @@ func (c *Controller) createOrUpdateServiceMetadata(logger *zap.Logger, ns *core_
},
}

// OpsGenie team is currently optional
if serviceData.Spec.Metadata.OpsGenie != nil {
resp, retriable, err := c.OpsGenie.GetOrCreateIntegrations(context.TODO(), serviceData.Spec.Metadata.OpsGenie.Team)
if err != nil {
return retriable, err
}
spec, err := createOpsGenieSecretSpec(resp, ns.Name)
if err != nil {
return false, err // Error indicates json marshalling problem
}
retriable, err = c.createOrUpdateSecret(logger, spec)
if err != nil {
return retriable, nil
}
}

conflict, retriable, _, err := c.ConfigMapUpdater.CreateOrUpdate(
logger,
func(r runtime.Object) error {
Expand All @@ -455,6 +479,29 @@ func (c *Controller) createOrUpdateServiceMetadata(logger *zap.Logger, ns *core_
return false, nil
}

// createOpsGenieSecretSpec creates an OpsGenieIntegrations secret object suitable for Secret creation
func createOpsGenieSecretSpec(ogInt *opsgenie.IntegrationsResponse, ns string) (*core_v1.Secret, error) {
jData, err := json.Marshal(ogInt)
if err != nil {
return &core_v1.Secret{}, err
}

return &core_v1.Secret{
TypeMeta: meta_v1.TypeMeta{
Kind: k8s.SecretKind,
APIVersion: core_v1.SchemeGroupVersion.String(),
},
ObjectMeta: meta_v1.ObjectMeta{
Name: secretNameOpsGenie,
Namespace: ns,
},
Data: map[string][]byte{
secretNameOpsGenie: jData,
},
Type: secretTypeOpsGenie,
}, nil
}

func (c *Controller) getServiceData(user auth.OptionalUser, name voyager.ServiceName) (*creator_v1.Service, error) {
return c.ServiceCentral.GetService(context.Background(), user, servicecentral.ServiceName(name))
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/trebuchet/server/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package apiserver
import (
apis_trebuchet "github.com/atlassian/voyager/pkg/apis/trebuchet"
"github.com/atlassian/voyager/pkg/apis/trebuchet/install"
"github.com/atlassian/voyager/pkg/apis/trebuchet/v1"
v1 "github.com/atlassian/voyager/pkg/apis/trebuchet/v1"
"github.com/atlassian/voyager/pkg/trebuchet"
trebuchetrest "github.com/atlassian/voyager/pkg/trebuchet/server/rest"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down

0 comments on commit 005de8c

Please sign in to comment.