Skip to content

Commit

Permalink
feat: adds support for API Observability (#505)
Browse files Browse the repository at this point in the history
* WIP: adds support for api observability

* add api observability cmd

* fix: commands

* bug: multiple fixes #505

---------

Co-authored-by: Sai Saran Vaidyanathan <ssvaidyanathan@google.com>
  • Loading branch information
srinandan and ssvaidyanathan authored Oct 30, 2024
1 parent 24fe7f2 commit b6740e3
Show file tree
Hide file tree
Showing 16 changed files with 764 additions and 0 deletions.
11 changes: 11 additions & 0 deletions internal/apiclient/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const (
// registryBaseURL is the Apigee API Hub control plane endpoint
const registryBaseURL = "https://apihub.googleapis.com/v1/projects/%s/locations/%s"

// API Observability control plane endpoint
const apiObserveBaseURL = "https://apim.googleapis.com/v1alpha/projects/%s/locations/%s"

// baseDRZURL is the Apigee control plane endpoint
const baseDRZURL = "https://%s-apigee.googleapis.com/v1/organizations/"

Expand Down Expand Up @@ -336,6 +339,14 @@ func GetApigeeRegistryURL() (registryURL string) {
return fmt.Sprintf(registryBaseURL, options.ProjectID, options.Region)
}

// GetAPIObserveURL
func GetAPIObserveURL() (apiObserveURL string) {
if options.ProjectID == "" {
options.ProjectID = options.Org
}
return fmt.Sprintf(apiObserveBaseURL, options.ProjectID, options.Region)
}

// GetApigeeBaseURL
func GetApigeeBaseURL() string {
if options.Region != "" {
Expand Down
163 changes: 163 additions & 0 deletions internal/client/observe/observe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright 2024 Google LLC
//
// 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 observe

import (
"encoding/json"
"net/url"
"path"
"strconv"
"strings"

"internal/apiclient"
)

type Action uint8

const (
ENABLE Action = iota
DISABLE
)

func CreateObservationJob(observationJobId string, sources []string) (respBody []byte, err error) {
var payload string

u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationJobs")
q := u.Query()
q.Set("observationJobId", observationJobId)
u.RawQuery = q.Encode()

if len(sources) != 0 {
payload = "{ \"sources\":[\"" + strings.Join(sources, "\", \"") + "\"]}"
}
respBody, err = apiclient.HttpClient(u.String(), payload, "POST")
return respBody, err
}

func GetObservationJob(observationJobId string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationJobs", observationJobId)
respBody, err = apiclient.HttpClient(u.String())
return respBody, err
}

func DeleteObservationJob(observationJobId string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationJobs", observationJobId)
respBody, err = apiclient.HttpClient(u.String(), "", "DELETE")
return respBody, err
}

func ListObservationJobs(pageSize int, pageToken string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationJobs")
q := u.Query()
if pageSize != -1 {
q.Set("pageSize", strconv.Itoa(pageSize))
}
if pageToken != "" {
q.Set("pageToken", pageToken)
}
u.RawQuery = q.Encode()
respBody, err = apiclient.HttpClient(u.String())
return respBody, err
}

func EnableObservationJob(observationJob string) (respBody []byte, err error) {
return controlObservation(observationJob, ENABLE)
}

func DisableObservationJob(observationJob string) (respBody []byte, err error) {
return controlObservation(observationJob, DISABLE)
}

func GetApiObservation(name string, observationJob string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationJobs", observationJob, "apiObservations", name)
respBody, err = apiclient.HttpClient(u.String())
return respBody, err
}

func ListApiObservations(observationJob string, pageSize int, pageToken string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationJobs", observationJob, "apiObservations")
q := u.Query()
if pageSize != -1 {
q.Set("pageSize", strconv.Itoa(pageSize))
}
if pageToken != "" {
q.Set("pageToken", pageToken)
}
u.RawQuery = q.Encode()
respBody, err = apiclient.HttpClient(u.String())
return respBody, err
}

func CreateObservationSource(observationSourceId string, pscNetworkConfigs map[string]string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationSources")
q := u.Query()
q.Set("observationSourceId", observationSourceId)
u.RawQuery = q.Encode()

networkConfig, err := json.Marshal(pscNetworkConfigs)
if err != nil {
return nil, err
}
payload := "{ \"gclbObservationSource\":{\"pscNetworkConfigs\":" + string(networkConfig) + "}}"
respBody, err = apiclient.HttpClient(u.String(), payload, "POST")
return respBody, err
}

func GetObservationSource(observationSourceId string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationSources", observationSourceId)
respBody, err = apiclient.HttpClient(u.String())
return respBody, err
}

func DeleteObservationSource(observationSourceId string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationSources", observationSourceId)
respBody, err = apiclient.HttpClient(u.String(), "", "DELETE")
return respBody, err
}

func ListObservationSources(pageSize int, pageToken string) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
u.Path = path.Join(u.Path, "observationSources")
q := u.Query()
if pageSize != -1 {
q.Set("pageSize", strconv.Itoa(pageSize))
}
if pageToken != "" {
q.Set("pageToken", pageToken)
}
u.RawQuery = q.Encode()
respBody, err = apiclient.HttpClient(u.String())
return respBody, err
}

func controlObservation(observationJob string, action Action) (respBody []byte, err error) {
u, _ := url.Parse(apiclient.GetAPIObserveURL())
if action == ENABLE {
u.Path = path.Join(u.Path, "observationJobs", observationJob+":enable")
} else {
u.Path = path.Join(u.Path, "observationJobs", observationJob+":disable")
}
respBody, err = apiclient.HttpClient(u.String(), "", "POST")
return respBody, err
}
53 changes: 53 additions & 0 deletions internal/cmd/observe/jobs/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 Google LLC
//
// 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 jobs

import (
"internal/apiclient"
"internal/client/observe"

"github.com/spf13/cobra"
)

// CrtCmd
var CrtCmd = &cobra.Command{
Use: "create",
Short: "Create a new Observation Job",
Long: "Create a new Observation Job",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetRegion(region)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
cmd.SilenceUsage = true
_, err = observe.CreateObservationJob(observationJobId, sources)
return
},
}

var (
observationJobId string
sources []string
)

func init() {
CrtCmd.Flags().StringVarP(&observationJobId, "id", "i",
"", "Observation Job")
CrtCmd.Flags().StringArrayVarP(&sources, "sources", "s",
nil, "The full path to source (repeat for multiple)")

_ = CrtCmd.MarkFlagRequired("id")
_ = CrtCmd.MarkFlagRequired("sources")
}
45 changes: 45 additions & 0 deletions internal/cmd/observe/jobs/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2024 Google LLC
//
// 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 jobs

import (
"internal/apiclient"
"internal/client/observe"

"github.com/spf13/cobra"
)

// DeleteCmd to get a catalog items
var DeleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete an Observation Job",
Long: "Delete an Observation Job",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetRegion(region)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
cmd.SilenceUsage = true
_, err = observe.DeleteObservationJob(observationJobId)
return
},
}

func init() {
DeleteCmd.Flags().StringVarP(&observationJobId, "id", "i",
"", "Observation Job Id")

_ = DeleteCmd.MarkFlagRequired("id")
}
45 changes: 45 additions & 0 deletions internal/cmd/observe/jobs/disable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2024 Google LLC
//
// 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 jobs

import (
"internal/apiclient"
"internal/client/observe"

"github.com/spf13/cobra"
)

// DisableCmd to get a catalog items
var DisableCmd = &cobra.Command{
Use: "disable",
Short: "Disable an Observation Job",
Long: "Disable an Observation Job",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetRegion(region)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
cmd.SilenceUsage = true
_, err = observe.DisableObservationJob(observationJobId)
return
},
}

func init() {
DisableCmd.Flags().StringVarP(&observationJobId, "id", "i",
"", "Observation Job Id")

_ = DisableCmd.MarkFlagRequired("id")
}
45 changes: 45 additions & 0 deletions internal/cmd/observe/jobs/enable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2024 Google LLC
//
// 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 jobs

import (
"internal/apiclient"
"internal/client/observe"

"github.com/spf13/cobra"
)

// EnableCmd to get a catalog items
var EnableCmd = &cobra.Command{
Use: "enable",
Short: "Enable an Observation Job",
Long: "Enable an Observation Job",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetRegion(region)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
cmd.SilenceUsage = true
_, err = observe.EnableObservationJob(observationJobId)
return
},
}

func init() {
EnableCmd.Flags().StringVarP(&observationJobId, "id", "i",
"", "Observation Job Id")

_ = EnableCmd.MarkFlagRequired("id")
}
Loading

0 comments on commit b6740e3

Please sign in to comment.