From a1314a0b6930a44af3e6c498e6441b60840c04cf Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Fri, 17 May 2024 11:50:33 -0700 Subject: [PATCH 01/25] feat: add support for api hub #461 --- internal/apiclient/options.go | 2 +- internal/client/hub/hub.go | 105 ++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 internal/client/hub/hub.go diff --git a/internal/apiclient/options.go b/internal/apiclient/options.go index 859b997e4..1cb390f32 100644 --- a/internal/apiclient/options.go +++ b/internal/apiclient/options.go @@ -26,7 +26,7 @@ import ( const baseURL = "https://apigee.googleapis.com/v1/organizations/" // registryBaseURL is the Apigee API Hub control plane endpoint -const registryBaseURL = "https://apigeeregistry.googleapis.com/v1/projects/%s/locations/%s" +const registryBaseURL = "https://apihub.googleapis.com/v1/projects/%s/locations/%s" // baseDRZURL is the Apigee control plane endpoint const baseDRZURL = "https://%s-apigee.googleapis.com/v1/organizations/" diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go new file mode 100644 index 000000000..6c16be90c --- /dev/null +++ b/internal/client/hub/hub.go @@ -0,0 +1,105 @@ +// 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 hub + +import ( + "fmt" + "net/url" + "path" + "strings" + + "internal/apiclient" +) + +func CreateInstance(apiHubInstanceId string, cmekName string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apiHubInstances") + + if apiHubInstanceId != "" { + q := u.Query() + q.Set("apiHubInstanceId", apiHubInstanceId) + u.RawQuery = q.Encode() + } + + instance := []string{} + config := []string{} + + name := fmt.Sprintf("projects/%s/locations/%s/instance", apiclient.GetProjectID(), apiclient.GetRegistryRegion()) + instance = append(instance, "\"name\":"+"\""+name+"\"") + + config = append(config, "\"cmekKeyName\":"+"\""+cmekName+"\"") + configJson := "{" + strings.Join(config, ",") + "}" + instance = append(instance, "\"config\":"+configJson) + + payload := "{" + strings.Join(instance, ",") + "}" + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +func GetInstance(apiHubInstanceId string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apiHubInstances", apiHubInstanceId) + + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func RegisterHostProject(registrationId string, gcpProjectId string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "hostProjectRegistrations") + + q := u.Query() + q.Set("hostProjectRegistrationId", registrationId) + u.RawQuery = q.Encode() + + payload := fmt.Sprintf("{\"gcpProject\":\"%s\"}", gcpProjectId) + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +func CreateRuntimeProjectAttachment(runtimeProjectAttachmentId string, runtimeProject string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "runtimeProjectAttachments") + + q := u.Query() + q.Set("runtimeProjectAttachmentId", runtimeProjectAttachmentId) + u.RawQuery = q.Encode() + + payload := fmt.Sprintf("{\"runtimeProject\":\"%s\"}", runtimeProject) + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +func DeleteRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "runtimeProjectAttachments", runtimeProjectAttachmentId) + + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func GetRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "runtimeProjectAttachments", runtimeProjectAttachmentId) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func ListRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "runtimeProjectAttachments") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} From 1768a15b96ae7384bdbf6334edbf5f2efb4b0a8d Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Wed, 22 May 2024 14:11:10 -0700 Subject: [PATCH 02/25] WIP: add api hubs apis #461 --- internal/client/hub/hub.go | 160 +++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index 6c16be90c..c3d4c3240 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -15,6 +15,7 @@ package hub import ( + "encoding/base64" "fmt" "net/url" "path" @@ -69,6 +70,13 @@ func RegisterHostProject(registrationId string, gcpProjectId string) (respBody [ return respBody, err } +func ListHostProjects() (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "hostProjectRegistrations") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + func CreateRuntimeProjectAttachment(runtimeProjectAttachmentId string, runtimeProject string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "runtimeProjectAttachments") @@ -103,3 +111,155 @@ func ListRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody [ respBody, err = apiclient.HttpClient(u.String()) return respBody, err } + +func CreateApi(apiID string, contents byte[]) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis") + + q := u.Query() + q.Set("apiId", apiID) + u.RawQuery = q.Encode() + + respBody, err = apiclient.HttpClient(u.String(), contents) + return respBody, err +} + +func DeleteApi(apiID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID) + + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func GetApi(apiID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID) + + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func ListApi(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID) + q := u.Query() + if filter != "" { + q.Set("filter", filter) + } + if pageSize != -1 { + q.Set("pageSize", pageSize) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func CreateApiVersion(versionID string, apiID string, contents byte[]) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID) + q := u.Query() + if filter != "" { + q.Set("versionId", filter) + } + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String(), contents) + return respBody, err +} + +func GetApiVersion(versionID, apiID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func DeleteApiVersion(versionID, apiID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func ListApiVersions(apiID string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions") + q := u.Query() + if filter != "" { + q.Set("filter", filter) + } + if pageSize != -1 { + q.Set("pageSize", pageSize) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func GetApiVersionsDefinitions(apiID string, versionID string, definition string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "definitions", definition) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +//TODO: specType +func CreateApiVersionsSpec(apiID string, versionID string, specID string, displayName string, + contents []byte, mimeType string, attributes map[string]string, sourceURI string, documentation string) (respBody []byte, err error) { + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs") + q := u.Query() + if filter != "" { + q.Set("specId", specID) + } + u.RawQuery = q.Encode() + + spec := []string{} + contentPayload := "" + spec = append(spec, "\"displayName\":"+"\""+displayName+"\"") + if sourceURI != "" { + specContent = append(specContent, "\"sourceUri\":"+"\""+sourceURI+"\"") + } + if documentation != "" { + specContent = append(specContent, "\"documentation\":"+"\""+documentation+"\"") + } + if contents != nil { + contentStr := []string{} + mime := "" + if mimeType != "" { + if strings.Contains(mimeType, "yaml") || strings.Contains(mimeType, "yml") { + mime = "application/yaml" + } else if strings.Contains(mimeType, "json") { + mime = "application/json" + } else if strings.Contains(mimeType, "wsdl") { + mime = "application/wsdl" + } else { + mime = "application/text" + } + } else { + mime = "application/text" + } + contentStr = append(contentStr, "\"mimeType\":"+"\""+mime+"\"") + encContent := base64.StdEncoding.EncodeToString(contents) + contentStr = append(contentStr, "\"contents\":"+"\""+encContent+"\"") + contentPayload := "{" + strings.Join(contentStr, ",") + "}" + specContent = append(specContent, "\"contents\":"+"\""+contentPayload+"\"") + } + if len(attributes) > 0 { + a := []string{} + for key, value := range attributes { + a = append(a, "\""+key+"\":\""+value+"\"") + } + attributesStr := "\"attributes\":{" + strings.Join(a, ",") + "}" + spec = append(spec, attributesStr) + } + + return respBody, err +} From 0bba60a293ae93d87e83d6f49110bfb41daafe3c Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Sat, 25 May 2024 10:29:13 -0700 Subject: [PATCH 03/25] WIP: add api hubs apis #461 --- internal/client/hub/hub.go | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index c3d4c3240..a45725dc2 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -16,14 +16,24 @@ package hub import ( "encoding/base64" + "encoding/json" "fmt" "net/url" "path" "strings" "internal/apiclient" + + enumdeclall "github.com/gogo/protobuf/test/enumdecl_all" ) +type allowedValues struct { + Id string `json:"id,omitempty"` + DisplayName string `json:"dispayName,omitempty"` + Description string `json:"description,omitempty"` + Immutable bool `json:"immutable"` +} + func CreateInstance(apiHubInstanceId string, cmekName string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apiHubInstances") @@ -236,10 +246,13 @@ func CreateApiVersionsSpec(apiID string, versionID string, specID string, displa if mimeType != "" { if strings.Contains(mimeType, "yaml") || strings.Contains(mimeType, "yml") { mime = "application/yaml" + specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) } else if strings.Contains(mimeType, "json") { mime = "application/json" + specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) } else if strings.Contains(mimeType, "wsdl") { mime = "application/wsdl" + specContent = append(specContent, "\"specType\":" + getAllowedValuesWSDL()) } else { mime = "application/text" } @@ -263,3 +276,54 @@ func CreateApiVersionsSpec(apiID string, versionID string, specID string, displa return respBody, err } + +func getAllowedValuesOpenAPI() string { + a := allowedValues( + Id: "openapi", + DisplayName: "OpenAPI Spec", + Description: "OpenAPI Spec", + Immutable: true, + ) + return getSpecType(a) +} + +func getAllowedValuesProto() string { + a := allowedValues( + Id: "proto", + DisplayName: "Proto", + Description: "Proto", + Immutable: true, + ) + return getSpecType(a) +} + +func getAllowedValuesWSDL() string { + a := allowedValues( + Id: "wsdl", + DisplayName: "WSDL", + Description: "WSDL", + Immutable: true, + ) + return getSpecType(a) +} + +func getSpecType(a allowedValues) string { + type specType struct { + EnumValues enumValues `json:"enumValues,omitempty"` + } + + type enumValues struct { + Values []allowedValues `json:"values,omitempty"` + } + l := []allowedValues{} + l = append(l, a) + e := enumValues{} + e.Values = l + + s := specType{} + s.EnumValues := enumValues{} + s.EnumValues = e + + specTypeStr, _ := json.Marshall(&s) + return specTypeStr +} From ef193e0605cf0da393907639e94c0dfdf7224f82 Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Thu, 30 May 2024 16:41:57 -0700 Subject: [PATCH 04/25] WIP: add api hubs apis #461 --- internal/client/hub/hub.go | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index a45725dc2..3d77ca340 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -219,7 +219,6 @@ func GetApiVersionsDefinitions(apiID string, versionID string, definition string return respBody, err } -//TODO: specType func CreateApiVersionsSpec(apiID string, versionID string, specID string, displayName string, contents []byte, mimeType string, attributes map[string]string, sourceURI string, documentation string) (respBody []byte, err error) { @@ -255,15 +254,18 @@ func CreateApiVersionsSpec(apiID string, versionID string, specID string, displa specContent = append(specContent, "\"specType\":" + getAllowedValuesWSDL()) } else { mime = "application/text" + specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) } } else { mime = "application/text" + specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) } contentStr = append(contentStr, "\"mimeType\":"+"\""+mime+"\"") encContent := base64.StdEncoding.EncodeToString(contents) contentStr = append(contentStr, "\"contents\":"+"\""+encContent+"\"") contentPayload := "{" + strings.Join(contentStr, ",") + "}" specContent = append(specContent, "\"contents\":"+"\""+contentPayload+"\"") + spec = append(spec, specContent) } if len(attributes) > 0 { a := []string{} @@ -274,6 +276,40 @@ func CreateApiVersionsSpec(apiID string, versionID string, specID string, displa spec = append(spec, attributesStr) } + payload := "{" + strings.Join(spec, ",") + "}" + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +func GetApiVersionsSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func GetApiVersionsSpecContent(apiID string, versionID string, specID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID, ":contents") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func ListApiVersionsSpec(apiID string, versionID string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs") + q := u.Query() + if filter != "" { + q.Set("filter", filter) + } + if pageSize != -1 { + q.Set("pageSize", pageSize) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) return respBody, err } From 1870a898f65fc7aae8185fd20973c3bfe7de3fda Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 21 Jun 2024 02:56:18 +0000 Subject: [PATCH 05/25] feat: enable api hub apis --- internal/apiclient/options.go | 2 +- internal/client/hub/hub.go | 485 ++++++++++++++---- internal/cmd/apihub/apihub.go | 40 ++ internal/cmd/apihub/apis/apis.go | 46 ++ internal/cmd/apihub/apis/create.go | 56 ++ internal/cmd/apihub/apis/delete.go | 45 ++ internal/cmd/apihub/apis/get.go | 47 ++ internal/cmd/apihub/apis/list.go | 52 ++ internal/cmd/apihub/apis/versions/create.go | 58 +++ internal/cmd/apihub/apis/versions/delete.go | 49 ++ internal/cmd/apihub/apis/versions/get.go | 51 ++ internal/cmd/apihub/apis/versions/list.go | 56 ++ .../cmd/apihub/apis/versions/specs/create.go | 71 +++ .../cmd/apihub/apis/versions/specs/delete.go | 51 ++ .../cmd/apihub/apis/versions/specs/get.go | 51 ++ .../cmd/apihub/apis/versions/specs/list.go | 59 +++ .../cmd/apihub/apis/versions/specs/specs.go | 43 ++ internal/cmd/apihub/apis/versions/versions.go | 46 ++ internal/cmd/apihub/dependencies/create.go | 90 ++++ internal/cmd/apihub/dependencies/delete.go | 45 ++ .../cmd/apihub/dependencies/dependencies.go | 43 ++ internal/cmd/apihub/dependencies/get.go | 45 ++ internal/cmd/apihub/dependencies/list.go | 52 ++ internal/cmd/apihub/deployments/create.go | 61 +++ internal/cmd/apihub/deployments/delete.go | 45 ++ internal/cmd/apihub/deployments/depoyments.go | 43 ++ internal/cmd/apihub/deployments/get.go | 45 ++ internal/cmd/apihub/deployments/list.go | 52 ++ internal/cmd/apihub/externalapis/create.go | 60 +++ internal/cmd/apihub/externalapis/delete.go | 45 ++ .../cmd/apihub/externalapis/externalapis.go | 43 ++ internal/cmd/apihub/externalapis/get.go | 47 ++ internal/cmd/apihub/externalapis/list.go | 52 ++ internal/cmd/apihub/instances/get.go | 45 ++ internal/cmd/apihub/instances/instances.go | 41 ++ internal/cmd/apihub/instances/list.go | 38 ++ internal/cmd/root.go | 2 + test/api-ver.json | 7 + test/api.json | 11 + 39 files changed, 2128 insertions(+), 92 deletions(-) create mode 100644 internal/cmd/apihub/apihub.go create mode 100644 internal/cmd/apihub/apis/apis.go create mode 100644 internal/cmd/apihub/apis/create.go create mode 100644 internal/cmd/apihub/apis/delete.go create mode 100644 internal/cmd/apihub/apis/get.go create mode 100644 internal/cmd/apihub/apis/list.go create mode 100644 internal/cmd/apihub/apis/versions/create.go create mode 100644 internal/cmd/apihub/apis/versions/delete.go create mode 100644 internal/cmd/apihub/apis/versions/get.go create mode 100644 internal/cmd/apihub/apis/versions/list.go create mode 100644 internal/cmd/apihub/apis/versions/specs/create.go create mode 100644 internal/cmd/apihub/apis/versions/specs/delete.go create mode 100644 internal/cmd/apihub/apis/versions/specs/get.go create mode 100644 internal/cmd/apihub/apis/versions/specs/list.go create mode 100644 internal/cmd/apihub/apis/versions/specs/specs.go create mode 100644 internal/cmd/apihub/apis/versions/versions.go create mode 100644 internal/cmd/apihub/dependencies/create.go create mode 100644 internal/cmd/apihub/dependencies/delete.go create mode 100644 internal/cmd/apihub/dependencies/dependencies.go create mode 100644 internal/cmd/apihub/dependencies/get.go create mode 100644 internal/cmd/apihub/dependencies/list.go create mode 100644 internal/cmd/apihub/deployments/create.go create mode 100644 internal/cmd/apihub/deployments/delete.go create mode 100644 internal/cmd/apihub/deployments/depoyments.go create mode 100644 internal/cmd/apihub/deployments/get.go create mode 100644 internal/cmd/apihub/deployments/list.go create mode 100644 internal/cmd/apihub/externalapis/create.go create mode 100644 internal/cmd/apihub/externalapis/delete.go create mode 100644 internal/cmd/apihub/externalapis/externalapis.go create mode 100644 internal/cmd/apihub/externalapis/get.go create mode 100644 internal/cmd/apihub/externalapis/list.go create mode 100644 internal/cmd/apihub/instances/get.go create mode 100644 internal/cmd/apihub/instances/instances.go create mode 100644 internal/cmd/apihub/instances/list.go create mode 100644 test/api-ver.json create mode 100644 test/api.json diff --git a/internal/apiclient/options.go b/internal/apiclient/options.go index 7844f9a7f..e427b1839 100644 --- a/internal/apiclient/options.go +++ b/internal/apiclient/options.go @@ -334,7 +334,7 @@ func GetApigeeRegistryURL() (registryURL string) { if options.ProjectID == "" { options.ProjectID = options.Org } - return fmt.Sprintf(registryBaseURL, options.ProjectID, registryRegion) + return fmt.Sprintf(registryBaseURL, options.ProjectID, options.Region) } // GetApigeeBaseURL diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index 3d77ca340..5e3ebb46a 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -20,18 +20,57 @@ import ( "fmt" "net/url" "path" + "strconv" "strings" "internal/apiclient" +) - enumdeclall "github.com/gogo/protobuf/test/enumdecl_all" +type DeploymentType string + +const ( + APIGEE DeploymentType = "apigee" + APIGEE_HYBRID DeploymentType = "apigee-hybrid" + APIGEE_EDGE_PRIVATE DeploymentType = "apigee-edge-private" + APIGEE_EDGE_PUBLIC DeploymentType = "apigee-edge-public" + MOCK_SERVER DeploymentType = "mock-server" + CLOUD_API_GATEWAY DeploymentType = "cloud-api-gateway" + CLOUD_ENDPOINTS DeploymentType = "cloud-endpoints" + UNMANAGED DeploymentType = "unmanaged" + OTHERS DeploymentType = "others" ) +type spec struct { + DisplayName string `json:"displayName,omitempty"` + SpecType specType `json:"specType,omitempty"` + SourceURI string `json:"sourceUri,omitempty"` + Contents content `json:"contents,omitempty"` + Documentation documentation `json:"documentation,omitempty"` + ParsingMode string `json:"parsingMode,omitempty"` +} + +type documentation struct { + ExternalUri string `json:"externalUri,omitempty"` +} + +type content struct { + Contents string `json:"contents,omitempty"` + MimeType string `json:"mimeType,omitempty"` +} + type allowedValues struct { - Id string `json:"id,omitempty"` - DisplayName string `json:"dispayName,omitempty"` + Id string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` Description string `json:"description,omitempty"` - Immutable bool `json:"immutable"` + Immutable bool `json:"immutable"` +} + +type enumValues struct { + Values []allowedValues `json:"values,omitempty"` +} + +type specType struct { + EnumValues enumValues `json:"enumValues,omitempty"` } func CreateInstance(apiHubInstanceId string, cmekName string) (respBody []byte, err error) { @@ -67,6 +106,14 @@ func GetInstance(apiHubInstanceId string) (respBody []byte, err error) { return respBody, err } +func LookupInstance() (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apiHubInstances:lookup") + + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + func RegisterHostProject(registrationId string, gcpProjectId string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "hostProjectRegistrations") @@ -122,7 +169,7 @@ func ListRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody [ return respBody, err } -func CreateApi(apiID string, contents byte[]) (respBody []byte, err error) { +func CreateApi(apiID string, contents []byte) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis") @@ -130,7 +177,7 @@ func CreateApi(apiID string, contents byte[]) (respBody []byte, err error) { q.Set("apiId", apiID) u.RawQuery = q.Encode() - respBody, err = apiclient.HttpClient(u.String(), contents) + respBody, err = apiclient.HttpClient(u.String(), string(contents)) return respBody, err } @@ -152,13 +199,13 @@ func GetApi(apiID string) (respBody []byte, err error) { func ListApi(filter string, pageSize int, pageToken string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "apis", apiID) + u.Path = path.Join(u.Path, "apis") q := u.Query() if filter != "" { q.Set("filter", filter) } if pageSize != -1 { - q.Set("pageSize", pageSize) + q.Set("pageSize", strconv.Itoa(pageSize)) } if pageToken != "" { q.Set("pageToken", pageToken) @@ -168,15 +215,15 @@ func ListApi(filter string, pageSize int, pageToken string) (respBody []byte, er return respBody, err } -func CreateApiVersion(versionID string, apiID string, contents byte[]) (respBody []byte, err error) { +func CreateApiVersion(versionID string, apiID string, contents []byte) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID) + u.Path = path.Join(u.Path, "apis", apiID, "versions") q := u.Query() - if filter != "" { - q.Set("versionId", filter) + if versionID != "" { + q.Set("versionId", versionID) } u.RawQuery = q.Encode() - respBody, err = apiclient.HttpClient(u.String(), contents) + respBody, err = apiclient.HttpClient(u.String(), string(contents)) return respBody, err } @@ -202,7 +249,7 @@ func ListApiVersions(apiID string, filter string, pageSize int, pageToken string q.Set("filter", filter) } if pageSize != -1 { - q.Set("pageSize", pageSize) + q.Set("pageSize", strconv.Itoa(pageSize)) } if pageToken != "" { q.Set("pageToken", pageToken) @@ -220,64 +267,44 @@ func GetApiVersionsDefinitions(apiID string, versionID string, definition string } func CreateApiVersionsSpec(apiID string, versionID string, specID string, displayName string, - contents []byte, mimeType string, attributes map[string]string, sourceURI string, documentation string) (respBody []byte, err error) { + contents []byte, mimeType string, sourceURI string, documentation string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs") q := u.Query() - if filter != "" { + if specID != "" { q.Set("specId", specID) } u.RawQuery = q.Encode() - spec := []string{} - contentPayload := "" - spec = append(spec, "\"displayName\":"+"\""+displayName+"\"") - if sourceURI != "" { - specContent = append(specContent, "\"sourceUri\":"+"\""+sourceURI+"\"") - } - if documentation != "" { - specContent = append(specContent, "\"documentation\":"+"\""+documentation+"\"") - } - if contents != nil { - contentStr := []string{} - mime := "" - if mimeType != "" { - if strings.Contains(mimeType, "yaml") || strings.Contains(mimeType, "yml") { - mime = "application/yaml" - specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) - } else if strings.Contains(mimeType, "json") { - mime = "application/json" - specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) - } else if strings.Contains(mimeType, "wsdl") { - mime = "application/wsdl" - specContent = append(specContent, "\"specType\":" + getAllowedValuesWSDL()) - } else { - mime = "application/text" - specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) - } - } else { - mime = "application/text" - specContent = append(specContent, "\"specType\":" + getAllowedValuesOpenAPI()) - } - contentStr = append(contentStr, "\"mimeType\":"+"\""+mime+"\"") - encContent := base64.StdEncoding.EncodeToString(contents) - contentStr = append(contentStr, "\"contents\":"+"\""+encContent+"\"") - contentPayload := "{" + strings.Join(contentStr, ",") + "}" - specContent = append(specContent, "\"contents\":"+"\""+contentPayload+"\"") - spec = append(spec, specContent) - } - if len(attributes) > 0 { - a := []string{} - for key, value := range attributes { - a = append(a, "\""+key+"\":\""+value+"\"") - } - attributesStr := "\"attributes\":{" + strings.Join(a, ",") + "}" - spec = append(spec, attributesStr) - } - - payload := "{" + strings.Join(spec, ",") + "}" - respBody, err = apiclient.HttpClient(u.String(), payload) + s := spec{} + s.DisplayName = displayName + s.Documentation.ExternalUri = documentation + s.Contents.Contents = base64.StdEncoding.EncodeToString(contents) + + if strings.Contains(mimeType, "yaml") || strings.Contains(mimeType, "yml") { + s.Contents.MimeType = "application/yaml" + s.SpecType = getAllowedValuesOpenAPI() + } else if strings.Contains(mimeType, "json") { + s.Contents.MimeType = "application/json" + s.SpecType = getAllowedValuesOpenAPI() + } else if strings.Contains(mimeType, "wsdl") { + s.Contents.MimeType = "application/wsdl" + s.SpecType = getAllowedValuesWSDL() + } else if strings.Contains(mimeType, "proto") { + s.Contents.MimeType = "application/text" + s.SpecType = getAllowedValuesProto() + } else { + s.Contents.MimeType = "application/text" + } + s.SourceURI = sourceURI + + payload, err := json.Marshal(s) + if err != nil { + return nil, err + } + + respBody, err = apiclient.HttpClient(u.String(), string(payload)) return respBody, err } @@ -288,6 +315,13 @@ func GetApiVersionsSpec(apiID string, versionID string, specID string) (respBody return respBody, err } +func DeleteApiVersionsSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + func GetApiVersionsSpecContent(apiID string, versionID string, specID string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID, ":contents") @@ -303,7 +337,7 @@ func ListApiVersionsSpec(apiID string, versionID string, filter string, pageSize q.Set("filter", filter) } if pageSize != -1 { - q.Set("pageSize", pageSize) + q.Set("pageSize", strconv.Itoa(pageSize)) } if pageToken != "" { q.Set("pageToken", pageToken) @@ -313,53 +347,322 @@ func ListApiVersionsSpec(apiID string, versionID string, filter string, pageSize return respBody, err } -func getAllowedValuesOpenAPI() string { - a := allowedValues( - Id: "openapi", +func CreateDependency(dependencyID string, description string, consumerDisplayName string, + consumerOperationResourceName string, consumerExternalApiResourceName string, supplierDisplayName string, + supplierOperationResourceName string, supplierExternalApiResourceName string) (respBody []byte, err error) { + + type consumer struct { + DisplayName string `json:"displayName,omitempty"` + OperationResourceName *string `json:"operationResourceName,omitempty"` + ExternalApiResourceName *string `json:"externalApiResourceName,omitempty"` + } + + type supplier struct { + DisplayName string `json:"displayName,omitempty"` + OperationResourceName *string `json:"operationResourceName,omitempty"` + ExternalApiResourceName *string `json:"externalApiResourceName,omitempty"` + } + + type dependency struct { + Description string `json:"description,omitempty"` + Consumer consumer `json:"consumer,omitempty"` + Supplier supplier `json:"supplier,omitempty"` + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "dependencies") + q := u.Query() + q.Set("dependencyId", dependencyID) + u.RawQuery = q.Encode() + + c := dependency{} + c.Description = description + c.Consumer.DisplayName = consumerDisplayName + if consumerOperationResourceName != "" && consumerExternalApiResourceName != "" { + return nil, fmt.Errorf("consumerOperationResourceName and consumerExternalApiResourceName cannot be set together") + } + if consumerOperationResourceName != "" { + c.Consumer.OperationResourceName = new(string) + *c.Consumer.OperationResourceName = consumerOperationResourceName + } + if consumerExternalApiResourceName != "" { + c.Consumer.ExternalApiResourceName = new(string) + *c.Consumer.ExternalApiResourceName = consumerExternalApiResourceName + } + + c.Supplier.DisplayName = supplierDisplayName + if supplierOperationResourceName != "" && supplierExternalApiResourceName != "" { + return nil, fmt.Errorf("supplierOperationResourceName and supplierExternalApiResourceName cannot be set together") + } + if supplierOperationResourceName != "" { + c.Supplier.OperationResourceName = new(string) + *c.Supplier.OperationResourceName = supplierOperationResourceName + } + if supplierExternalApiResourceName != "" { + c.Supplier.ExternalApiResourceName = new(string) + *c.Supplier.ExternalApiResourceName = supplierExternalApiResourceName + } + + payload, err := json.Marshal(&c) + if err != nil { + return nil, err + } + respBody, err = apiclient.HttpClient(u.String(), string(payload)) + return respBody, err +} + +func GetDependency(dependencyID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "dependencies", dependencyID) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func DeleteDependency(dependencyID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "dependencies", dependencyID) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func ListDependencies(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "dependencies") + q := u.Query() + if filter != "" { + q.Set("filter", filter) + } + 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 CreateDeployment(deploymentID string, displayName string, description string, + externalURI string, resourceURI string, endpoints []string, dep DeploymentType) (respBody []byte, err error) { + + type documentation struct { + ExternalURI string `json:"externalUri,omitempty"` + } + + type deploymentType struct { + EnumValues enumValues `json:"enumValues,omitempty"` + } + + type deployment struct { + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + DeploymentType deploymentType `json:"deploymentType,omitempty"` + Documentation documentation `json:"documentation,omitempty"` + ResourceURI string `json:"resourceUri,omitempty"` + Endpoints []string `json:"endpoints,omitempty"` + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "deployments") + q := u.Query() + q.Set("deploymentId", deploymentID) + u.RawQuery = q.Encode() + + d := deployment{} + d.DisplayName = displayName + d.Description = description + d.Documentation.ExternalURI = externalURI + d.ResourceURI = resourceURI + d.Endpoints = endpoints + + payload, err := json.Marshal(&d) + if err != nil { + return nil, err + } + respBody, err = apiclient.HttpClient(u.String(), string(payload)) + return respBody, err +} + +func GetDeployment(deploymentID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "deployments", deploymentID) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func DeleteDeployment(deploymentID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "deployments", deploymentID) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func ListDeployments(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "dependencies") + q := u.Query() + if filter != "" { + q.Set("filter", filter) + } + 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 CreateExternalAPI(externalApiId string, displayName string, description string, + endpoints []string, paths []string, externalUri string) (respBody []byte, err error) { + + type documentation struct { + ExternalURI string `json:"externalUri,omitempty"` + } + + type extapi struct { + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Documentation documentation `json:"documentation,omitempty"` + Paths []string `json:"paths,omitempty"` + Endpoints []string `json:"endpoints,omitempty"` + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "externalApi") + q := u.Query() + q.Set("externalApiId", externalApiId) + u.RawQuery = q.Encode() + + e := extapi{} + e.DisplayName = displayName + e.Description = description + e.Documentation.ExternalURI = externalUri + e.Paths = paths + e.Endpoints = endpoints + + payload, err := json.Marshal(&e) + if err != nil { + return nil, err + } + respBody, err = apiclient.HttpClient(u.String(), string(payload)) + return respBody, err +} + +func GetExternalAPI(externalApiId string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "externalApis", externalApiId) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func DeleteExternalAPI(externalApiID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "externalApis", externalApiID) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func ListExternalAPIs(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "externalApis") + q := u.Query() + if filter != "" { + q.Set("filter", filter) + } + 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 getAllowedValuesOpenAPI() specType { + a := allowedValues{ + Id: "openapi", DisplayName: "OpenAPI Spec", Description: "OpenAPI Spec", - Immutable: true, - ) + Immutable: true, + } return getSpecType(a) } -func getAllowedValuesProto() string { - a := allowedValues( - Id: "proto", +func getAllowedValuesProto() specType { + a := allowedValues{ + Id: "proto", DisplayName: "Proto", Description: "Proto", - Immutable: true, - ) + Immutable: true, + } return getSpecType(a) } -func getAllowedValuesWSDL() string { - a := allowedValues( - Id: "wsdl", +func getAllowedValuesWSDL() specType { + a := allowedValues{ + Id: "wsdl", DisplayName: "WSDL", Description: "WSDL", - Immutable: true, - ) + Immutable: true, + } return getSpecType(a) } -func getSpecType(a allowedValues) string { - type specType struct { - EnumValues enumValues `json:"enumValues,omitempty"` - } - - type enumValues struct { - Values []allowedValues `json:"values,omitempty"` - } +func getSpecType(a allowedValues) specType { l := []allowedValues{} l = append(l, a) e := enumValues{} e.Values = l s := specType{} - s.EnumValues := enumValues{} + s.EnumValues = enumValues{} s.EnumValues = e - specTypeStr, _ := json.Marshall(&s) - return specTypeStr + return s +} + +func getDeploymentEnum(d DeploymentType) specType { + switch d { + case APIGEE: + return getSpecType(allowedValues{ + Id: "apigee", + DisplayName: "Apigee", + Description: "Apigee", + Immutable: true, + }) + case APIGEE_HYBRID: + return getSpecType(allowedValues{ + Id: "apigee-hybrid", + DisplayName: "Apigee Hybrid", + Description: "Apigee Hybrid", + Immutable: true, + }) + } + + return specType{} +} + +func (d *DeploymentType) String() string { + return string(*d) +} + +func (d *DeploymentType) Set(r string) error { + switch r { + case "apigee", "apigee-hybrid", "apigee-edge-private", "apigee-edge-public", "mock-server", "cloud-api-gateway", "cloud-endpoints", "unmanaged", "others": + *d = DeploymentType(r) + default: + return fmt.Errorf("must be one of %s, %s, %s, %s, %s, %s, %s, %s or %s", + APIGEE, APIGEE_HYBRID, APIGEE_EDGE_PRIVATE, APIGEE_EDGE_PUBLIC, MOCK_SERVER, CLOUD_API_GATEWAY, CLOUD_ENDPOINTS, UNMANAGED, OTHERS) + } + return nil +} + +func (d *DeploymentType) Type() string { + return "deploymentType" } diff --git a/internal/cmd/apihub/apihub.go b/internal/cmd/apihub/apihub.go new file mode 100644 index 000000000..d8f9cb04b --- /dev/null +++ b/internal/cmd/apihub/apihub.go @@ -0,0 +1,40 @@ +// 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 apihub + +import ( + "internal/cmd/apihub/apis" + "internal/cmd/apihub/dependencies" + "internal/cmd/apihub/deployments" + "internal/cmd/apihub/externalapis" + "internal/cmd/apihub/instances" + + "github.com/spf13/cobra" +) + +// Cmd to manage apis +var Cmd = &cobra.Command{ + Use: "apihub", + Short: "Manage Apigee API Hub Resources", + Long: "Manage Apigee API Hub Resources", +} + +func init() { + Cmd.AddCommand(instances.InstanceCmd) + Cmd.AddCommand(apis.ApisCmd) + Cmd.AddCommand(deployments.DeploymentCmd) + Cmd.AddCommand(dependencies.DependencyCmd) + Cmd.AddCommand(externalapis.ExternalAPICmd) +} diff --git a/internal/cmd/apihub/apis/apis.go b/internal/cmd/apihub/apis/apis.go new file mode 100644 index 000000000..45bc0ca41 --- /dev/null +++ b/internal/cmd/apihub/apis/apis.go @@ -0,0 +1,46 @@ +// 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 apis + +import ( + "internal/cmd/apihub/apis/versions" + + "github.com/spf13/cobra" +) + +// ApisCmd to manage apis +var ApisCmd = &cobra.Command{ + Use: "apis", + Short: "Manage Apigee API Hub APIs", + Long: "Manage Apigee API Hub APIs", +} + +var org, region string + +func init() { + ApisCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + ApisCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + ApisCmd.AddCommand(ListCmd) + ApisCmd.AddCommand(CrtCmd) + ApisCmd.AddCommand(GetCmd) + ApisCmd.AddCommand(DelCmd) + ApisCmd.AddCommand(versions.ApiVersionsCmd) + + _ = ApisCmd.MarkFlagRequired("org") + _ = ApisCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/apis/create.go b/internal/cmd/apihub/apis/create.go new file mode 100644 index 000000000..a8a8bccd1 --- /dev/null +++ b/internal/cmd/apihub/apis/create.go @@ -0,0 +1,56 @@ +// 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 apis + +import ( + "internal/apiclient" + "internal/client/hub" + "os" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API Hub API", + Long: "Create a new API Hub API", + 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 + var apiFileBytes []byte + + if apiFileBytes, err = os.ReadFile(apiFilePath); err != nil { + return err + } + _, err = hub.CreateApi(id, apiFileBytes) + return + }, +} + +var id, apiFilePath string + +func init() { + CrtCmd.Flags().StringVarP(&id, "api-id", "", + "", "API ID") + CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API defintion") + + _ = CrtCmd.MarkFlagRequired("api-id") + _ = CrtCmd.MarkFlagRequired("file") +} diff --git a/internal/cmd/apihub/apis/delete.go b/internal/cmd/apihub/apis/delete.go new file mode 100644 index 000000000..a1a30f353 --- /dev/null +++ b/internal/cmd/apihub/apis/delete.go @@ -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 apis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete an API from API Hub", + Long: "Delete an API from API Hub", + 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 = hub.DeleteApi(apiID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + + _ = DelCmd.MarkFlagRequired("api-id") +} diff --git a/internal/cmd/apihub/apis/get.go b/internal/cmd/apihub/apis/get.go new file mode 100644 index 000000000..aba8405f0 --- /dev/null +++ b/internal/cmd/apihub/apis/get.go @@ -0,0 +1,47 @@ +// 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 apis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for an API", + Long: "Get details for an API", + 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 = hub.GetApi(apiID) + return + }, +} + +var apiID string + +func init() { + GetCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + + _ = GetCmd.MarkFlagRequired("api-id") +} diff --git a/internal/cmd/apihub/apis/list.go b/internal/cmd/apihub/apis/list.go new file mode 100644 index 000000000..c6a07d4f8 --- /dev/null +++ b/internal/cmd/apihub/apis/list.go @@ -0,0 +1,52 @@ +// 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 apis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List API Hub APIs", + Long: "List API Hub APIs", + 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 = hub.ListApi(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/apis/versions/create.go b/internal/cmd/apihub/apis/versions/create.go new file mode 100644 index 000000000..3d1224fd4 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/create.go @@ -0,0 +1,58 @@ +// 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 versions + +import ( + "internal/apiclient" + "internal/client/hub" + "os" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API Hub API Version", + Long: "Create a new API Hub API Version", + 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 + var apiFileBytes []byte + + if apiFileBytes, err = os.ReadFile(apiFilePath); err != nil { + return err + } + _, err = hub.CreateApiVersion(id, apiID, apiFileBytes) + return + }, +} + +var apiID, apiFilePath string + +func init() { + CrtCmd.Flags().StringVarP(&id, "id", "i", + "", "API Version ID") + CrtCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API defintion") + + _ = CrtCmd.MarkFlagRequired("api-id") + _ = CrtCmd.MarkFlagRequired("file") +} diff --git a/internal/cmd/apihub/apis/versions/delete.go b/internal/cmd/apihub/apis/versions/delete.go new file mode 100644 index 000000000..e82b3eeca --- /dev/null +++ b/internal/cmd/apihub/apis/versions/delete.go @@ -0,0 +1,49 @@ +// 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 versions + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete an API Version", + Long: "Delete an API Version", + 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 = hub.DeleteApiVersion(versionID, apiID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + DelCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + + _ = DelCmd.MarkFlagRequired("api-id") + _ = DelCmd.MarkFlagRequired("version") + +} diff --git a/internal/cmd/apihub/apis/versions/get.go b/internal/cmd/apihub/apis/versions/get.go new file mode 100644 index 000000000..d47b44273 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/get.go @@ -0,0 +1,51 @@ +// 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 versions + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for an API Version", + Long: "Get details for an API Version", + 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 = hub.GetApiVersion(versionID, apiID) + return + }, +} + +var versionID string + +func init() { + GetCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + GetCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + + _ = GetCmd.MarkFlagRequired("api-id") + _ = GetCmd.MarkFlagRequired("version") + +} diff --git a/internal/cmd/apihub/apis/versions/list.go b/internal/cmd/apihub/apis/versions/list.go new file mode 100644 index 000000000..dc8498dd1 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/list.go @@ -0,0 +1,56 @@ +// 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 versions + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List API Hub API Versions", + Long: "List API Hub API Versions", + 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 = hub.ListApiVersions(id, filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter, id string +) + +func init() { + ListCmd.Flags().StringVarP(&id, "api-id", "i", + "", "API ID") + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") + + _ = ListCmd.MarkFlagRequired("api-id") +} diff --git a/internal/cmd/apihub/apis/versions/specs/create.go b/internal/cmd/apihub/apis/versions/specs/create.go new file mode 100644 index 000000000..fe0da0ff3 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/create.go @@ -0,0 +1,71 @@ +// 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 specs + +import ( + "internal/apiclient" + "internal/client/hub" + "internal/cmd/utils" + "path/filepath" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new Spec for an API Hub API Version", + Long: "Create a new Spec for an API Hub API Version", + 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 + var contents []byte + + if contents, err = utils.ReadFile(apiFilePath); err != nil { + return err + } + _, err = hub.CreateApiVersionsSpec(apiID, versionID, specID, displayName, + contents, filepath.Ext(apiFilePath), sourceURI, documentation) + return + }, +} + +var specID, displayName, mimeType, sourceURI, documentation, apiFilePath string +var attributes map[string]string + +func init() { + CrtCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + CrtCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Spec Display Name") + CrtCmd.Flags().StringToStringVar(&attributes, "attrs", + nil, "API Spec attributes") + CrtCmd.Flags().StringVarP(&sourceURI, "source-uri", "s", + "", "API Spec attributes") + CrtCmd.Flags().StringVarP(&documentation, "documentation", "", + "", "API Spec external documentation") + CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API spec") + + _ = CrtCmd.MarkFlagRequired("api-id") + _ = CrtCmd.MarkFlagRequired("version") + _ = CrtCmd.MarkFlagRequired("display-name") + _ = CrtCmd.MarkFlagRequired("file") +} diff --git a/internal/cmd/apihub/apis/versions/specs/delete.go b/internal/cmd/apihub/apis/versions/specs/delete.go new file mode 100644 index 000000000..34c0b3a6d --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/delete.go @@ -0,0 +1,51 @@ +// 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 specs + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a spec from an API Version", + Long: "Delete a spec from an API Version", + 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 = hub.DeleteApiVersionsSpec(apiID, versionID, specID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + DelCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + DelCmd.Flags().StringVarP(&specID, "spec-id", "s", + "", "Spec ID") + + _ = DelCmd.MarkFlagRequired("api-id") + _ = DelCmd.MarkFlagRequired("version") + _ = DelCmd.MarkFlagRequired("spec-id") +} diff --git a/internal/cmd/apihub/apis/versions/specs/get.go b/internal/cmd/apihub/apis/versions/specs/get.go new file mode 100644 index 000000000..183f6a264 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/get.go @@ -0,0 +1,51 @@ +// 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 specs + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get a spec for an API Version", + Long: "Get a spec for an API Version", + 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 = hub.GetApiVersionsSpec(apiID, versionID, specID) + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + GetCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + GetCmd.Flags().StringVarP(&specID, "spec-id", "s", + "", "Spec ID") + + _ = GetCmd.MarkFlagRequired("api-id") + _ = GetCmd.MarkFlagRequired("version") + _ = GetCmd.MarkFlagRequired("spec-id") +} diff --git a/internal/cmd/apihub/apis/versions/specs/list.go b/internal/cmd/apihub/apis/versions/specs/list.go new file mode 100644 index 000000000..6bc6efccc --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/list.go @@ -0,0 +1,59 @@ +// 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 specs + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List Specs for an API Version", + Long: "List Specs for an API Version", + 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 = hub.ListApiVersionsSpec(apiID, versionID, filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter, apiID, versionID string +) + +func init() { + ListCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + ListCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") + + _ = ListCmd.MarkFlagRequired("api-id") + _ = ListCmd.MarkFlagRequired("version") +} diff --git a/internal/cmd/apihub/apis/versions/specs/specs.go b/internal/cmd/apihub/apis/versions/specs/specs.go new file mode 100644 index 000000000..93a34e3a0 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/specs.go @@ -0,0 +1,43 @@ +// 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 specs + +import ( + "github.com/spf13/cobra" +) + +// SpecsCmd to manage apis +var SpecsCmd = &cobra.Command{ + Use: "specs", + Short: "Manage Specs for an API Version in API Hub", + Long: "Manage Specs for an API Version in API Hub", +} + +var org, region string + +func init() { + SpecsCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + SpecsCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + SpecsCmd.AddCommand(CrtCmd) + SpecsCmd.AddCommand(GetCmd) + SpecsCmd.AddCommand(DelCmd) + SpecsCmd.AddCommand(ListCmd) + + _ = SpecsCmd.MarkFlagRequired("org") + _ = SpecsCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/apis/versions/versions.go b/internal/cmd/apihub/apis/versions/versions.go new file mode 100644 index 000000000..cbb0ae742 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/versions.go @@ -0,0 +1,46 @@ +// 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 versions + +import ( + "internal/cmd/apihub/apis/versions/specs" + + "github.com/spf13/cobra" +) + +// ApiVersionsCmd to manage apis +var ApiVersionsCmd = &cobra.Command{ + Use: "versions", + Short: "Manage Apigee API Hub API Versions", + Long: "Manage Apigee API Hub API Versions", +} + +var org, region string + +func init() { + ApiVersionsCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + ApiVersionsCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + ApiVersionsCmd.AddCommand(CrtCmd) + ApiVersionsCmd.AddCommand(ListCmd) + ApiVersionsCmd.AddCommand(GetCmd) + ApiVersionsCmd.AddCommand(DelCmd) + ApiVersionsCmd.AddCommand(specs.SpecsCmd) + + _ = ApiVersionsCmd.MarkFlagRequired("org") + _ = ApiVersionsCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/dependencies/create.go b/internal/cmd/apihub/dependencies/create.go new file mode 100644 index 000000000..659f3bedf --- /dev/null +++ b/internal/cmd/apihub/dependencies/create.go @@ -0,0 +1,90 @@ +// 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 dependencies + +import ( + "fmt" + "internal/apiclient" + "internal/client/hub" + "regexp" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API Deployment in API Hub", + Long: "Create a new API Deployment in API Hub", + Args: func(cmd *cobra.Command, args []string) (err error) { + extApiPattern := `^projects/[^/]+/locations/[^/]+/apis/[^/]+/externalApis/[^/]+$` + opPattern := `^projects/[^/]+/locations/[^/]+/apis/[^/]+/versions/[^/]+/operations/[^/]+$` + + if consumerExternalApiResouceName != "" && consumerOperationResourceName != "" { + return fmt.Errorf("consumer-ext-api-res-name and consumer-op-res-name cannot be used together") + } + if supplierExternalApiResourceName != "" && supplierOperationResourceName != "" { + return fmt.Errorf("supplier-ext-api-res-name and supplier-op-res-name cannot be used together") + } + + if ok, err := regexp.MatchString(opPattern, consumerOperationResourceName); err != nil || !ok { + return fmt.Errorf("invalid pattern for consumer-op-res-name: %v", err) + } + if ok, err := regexp.MatchString(extApiPattern, consumerExternalApiResouceName); err != nil || !ok { + return fmt.Errorf("invalid pattern for consumer-ext-api-res-name: %v", err) + } + + if ok, err := regexp.MatchString(opPattern, supplierOperationResourceName); err != nil || !ok { + return fmt.Errorf("invalid pattern for supplier-op-res-name: %v", err) + } + if ok, err := regexp.MatchString(extApiPattern, supplierExternalApiResourceName); err != nil || !ok { + return fmt.Errorf("invalid pattern for supplier-ext-api-res-name: %v", err) + } + + apiclient.SetRegion(region) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + cmd.SilenceUsage = true + _, err = hub.CreateDependency(dependencyID, description, consumerDisplayName, + consumerOperationResourceName, consumerExternalApiResouceName, supplierDisplayName, + supplierOperationResourceName, supplierExternalApiResourceName) + return + }, +} + +var dependencyID, description, consumerDisplayName, consumerOperationResourceName string +var consumerExternalApiResouceName, supplierDisplayName, supplierOperationResourceName string +var supplierExternalApiResourceName string + +func init() { + CrtCmd.Flags().StringVarP(&dependencyID, "id", "i", + "", "Dependency Display Name") + CrtCmd.Flags().StringVarP(&description, "description", "", + "", "Dependency Description") + CrtCmd.Flags().StringVarP(&consumerDisplayName, "consumer-display-name", "", + "", "Consumer Display Name") + CrtCmd.Flags().StringVarP(&consumerOperationResourceName, "consumer-op-res-name", "", + "", "Consumer Operation Resource Name") + CrtCmd.Flags().StringVarP(&consumerExternalApiResouceName, "consumer-ext-api-res-name", "", + "", "Consumer External API Resource Name") + CrtCmd.Flags().StringVarP(&supplierDisplayName, "supplier-display-name", "", + "", "Supplier Display Name") + CrtCmd.Flags().StringVarP(&supplierOperationResourceName, "supplier-op-res-name", "", + "", "Supplier Operation Resource Name") + CrtCmd.Flags().StringVarP(&supplierExternalApiResourceName, "supplier-ext-api-res-name", "", + "", "Supplier External API Resource Name") + +} diff --git a/internal/cmd/apihub/dependencies/delete.go b/internal/cmd/apihub/dependencies/delete.go new file mode 100644 index 000000000..6e1e7f106 --- /dev/null +++ b/internal/cmd/apihub/dependencies/delete.go @@ -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 dependencies + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a deployment", + Long: "Delete a deployment", + 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 = hub.DeleteDeployment(dependencyID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&dependencyID, "id", "i", + "", "Dependency ID") + + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/dependencies/dependencies.go b/internal/cmd/apihub/dependencies/dependencies.go new file mode 100644 index 000000000..a0c03a24f --- /dev/null +++ b/internal/cmd/apihub/dependencies/dependencies.go @@ -0,0 +1,43 @@ +// 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 dependencies + +import ( + "github.com/spf13/cobra" +) + +// DependencyCmd to manage apis +var DependencyCmd = &cobra.Command{ + Use: "dependencies", + Short: "Manage dependencies between consumers and suppliers", + Long: "Manage dependencies between consumers and suppliers", +} + +var org, region string + +func init() { + DependencyCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + DependencyCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + DependencyCmd.AddCommand(CrtCmd) + DependencyCmd.AddCommand(GetCmd) + DependencyCmd.AddCommand(DelCmd) + DependencyCmd.AddCommand(ListCmd) + + _ = DependencyCmd.MarkFlagRequired("org") + _ = DependencyCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/dependencies/get.go b/internal/cmd/apihub/dependencies/get.go new file mode 100644 index 000000000..6966505a1 --- /dev/null +++ b/internal/cmd/apihub/dependencies/get.go @@ -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 dependencies + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for a dependency", + Long: "Get details for a dependency", + 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 = hub.GetDependency(dependencyID) + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&dependencyID, "id", "i", + "", "Dependency ID") + + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/dependencies/list.go b/internal/cmd/apihub/dependencies/list.go new file mode 100644 index 000000000..7874b9883 --- /dev/null +++ b/internal/cmd/apihub/dependencies/list.go @@ -0,0 +1,52 @@ +// 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 dependencies + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List dependencies", + Long: "List dependencies", + 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 = hub.ListDependencies(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/deployments/create.go b/internal/cmd/apihub/deployments/create.go new file mode 100644 index 000000000..f2d260102 --- /dev/null +++ b/internal/cmd/apihub/deployments/create.go @@ -0,0 +1,61 @@ +// 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 deployments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API Deployment in API Hub", + Long: "Create a new API Deployment in API Hub", + 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 = hub.CreateDeployment(deploymentID, displayName, description, externalURI, resourceURI, endpoints, d) + return + }, +} + +var deploymentID, displayName, description, externalURI, resourceURI string +var endpoints []string +var d hub.DeploymentType + +func init() { + CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Deployment Display Name") + CrtCmd.Flags().StringVarP(&description, "description", "", + "", "Deployment Description") + CrtCmd.Flags().StringVarP(&externalURI, "external-uri", "", + "", "The uri of the externally hosted documentation") + CrtCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", + "", "A URI to the runtime resource") + CrtCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", + []string{}, " The endpoints at which this deployment resource is listening for API requests") + CrtCmd.Flags().Var(&d, "type", "The type of deployment") + + _ = CrtCmd.MarkFlagRequired("display-name") + _ = CrtCmd.MarkFlagRequired("resource-uri") + _ = CrtCmd.MarkFlagRequired("endpoints") + _ = CrtCmd.MarkFlagRequired("type") +} diff --git a/internal/cmd/apihub/deployments/delete.go b/internal/cmd/apihub/deployments/delete.go new file mode 100644 index 000000000..f809a2c63 --- /dev/null +++ b/internal/cmd/apihub/deployments/delete.go @@ -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 deployments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a deployment", + Long: "Delete a deployment", + 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 = hub.DeleteDeployment(deploymentID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&deploymentID, "id", "i", + "", "Deployment ID") + + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/deployments/depoyments.go b/internal/cmd/apihub/deployments/depoyments.go new file mode 100644 index 000000000..41756da71 --- /dev/null +++ b/internal/cmd/apihub/deployments/depoyments.go @@ -0,0 +1,43 @@ +// 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 deployments + +import ( + "github.com/spf13/cobra" +) + +// DeploymentCmd to manage apis +var DeploymentCmd = &cobra.Command{ + Use: "deployments", + Short: "Manage details of the deployment where APIs are hosted", + Long: "Manage details of the deployment where APIs are hosted", +} + +var org, region string + +func init() { + DeploymentCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + DeploymentCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + DeploymentCmd.AddCommand(CrtCmd) + DeploymentCmd.AddCommand(GetCmd) + DeploymentCmd.AddCommand(DelCmd) + DeploymentCmd.AddCommand(ListCmd) + + _ = DeploymentCmd.MarkFlagRequired("org") + _ = DeploymentCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/deployments/get.go b/internal/cmd/apihub/deployments/get.go new file mode 100644 index 000000000..1448f5670 --- /dev/null +++ b/internal/cmd/apihub/deployments/get.go @@ -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 deployments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for a deployment", + Long: "Get details for a deployment", + 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 = hub.GetDeployment(deploymentID) + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&deploymentID, "id", "i", + "", "Dependency ID") + + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/deployments/list.go b/internal/cmd/apihub/deployments/list.go new file mode 100644 index 000000000..1074f7db2 --- /dev/null +++ b/internal/cmd/apihub/deployments/list.go @@ -0,0 +1,52 @@ +// 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 deployments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List deployments", + Long: "List deployments", + 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 = hub.ListDeployments(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/externalapis/create.go b/internal/cmd/apihub/externalapis/create.go new file mode 100644 index 000000000..2f8d21abb --- /dev/null +++ b/internal/cmd/apihub/externalapis/create.go @@ -0,0 +1,60 @@ +// 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 externalapis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API External API", + Long: "Create a new API External API", + 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 = hub.CreateExternalAPI(externalApiId, displayName, description, endpoints, paths, externalURI) + return + }, +} + +var externalApiId, displayName, description, externalURI, resourceURI string +var endpoints, paths []string + +func init() { + CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Deployment Display Name") + CrtCmd.Flags().StringVarP(&description, "description", "", + "", "Deployment Description") + CrtCmd.Flags().StringVarP(&externalURI, "external-uri", "", + "", "The uri of the externally hosted documentation") + CrtCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", + "", "A URI to the runtime resource") + CrtCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", + []string{}, " The endpoints at which this deployment resource is listening for API requests") + CrtCmd.Flags().StringArrayVarP(&paths, "paths", "", + []string{}, " API base paths") + + _ = CrtCmd.MarkFlagRequired("display-name") + _ = CrtCmd.MarkFlagRequired("resource-uri") + _ = CrtCmd.MarkFlagRequired("endpoints") +} diff --git a/internal/cmd/apihub/externalapis/delete.go b/internal/cmd/apihub/externalapis/delete.go new file mode 100644 index 000000000..5654aae60 --- /dev/null +++ b/internal/cmd/apihub/externalapis/delete.go @@ -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 externalapis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete an External API", + Long: "Delete an an External API", + 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 = hub.DeleteExternalAPI(externalApiID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&externalApiID, "id", "i", + "", "External API ID") + + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/externalapis/externalapis.go b/internal/cmd/apihub/externalapis/externalapis.go new file mode 100644 index 000000000..16af4c6fd --- /dev/null +++ b/internal/cmd/apihub/externalapis/externalapis.go @@ -0,0 +1,43 @@ +// 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 externalapis + +import ( + "github.com/spf13/cobra" +) + +// ExternalAPICmd to manage apis +var ExternalAPICmd = &cobra.Command{ + Use: "externalapis", + Short: "Manage APIs provided by external sources", + Long: "Manage APIs provided by external sources", +} + +var org, region string + +func init() { + ExternalAPICmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + ExternalAPICmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + ExternalAPICmd.AddCommand(CrtCmd) + ExternalAPICmd.AddCommand(GetCmd) + ExternalAPICmd.AddCommand(DelCmd) + ExternalAPICmd.AddCommand(ListCmd) + + _ = ExternalAPICmd.MarkFlagRequired("org") + _ = ExternalAPICmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/externalapis/get.go b/internal/cmd/apihub/externalapis/get.go new file mode 100644 index 000000000..71c8a7ef9 --- /dev/null +++ b/internal/cmd/apihub/externalapis/get.go @@ -0,0 +1,47 @@ +// 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 externalapis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for an External API", + Long: "Get details for an External API", + 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 = hub.GetExternalAPI(externalApiID) + return + }, +} + +var externalApiID string + +func init() { + GetCmd.Flags().StringVarP(&externalApiID, "id", "i", + "", "External API ID") + + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/externalapis/list.go b/internal/cmd/apihub/externalapis/list.go new file mode 100644 index 000000000..dbd9a8411 --- /dev/null +++ b/internal/cmd/apihub/externalapis/list.go @@ -0,0 +1,52 @@ +// 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 externalapis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List External APIs", + Long: "List External APIs", + 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 = hub.ListExternalAPIs(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/instances/get.go b/internal/cmd/apihub/instances/get.go new file mode 100644 index 000000000..aebf687fa --- /dev/null +++ b/internal/cmd/apihub/instances/get.go @@ -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 instances + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Gets an API Hub Instance", + Long: "Gets an API Hub Instance", + 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 = hub.GetInstance(id) + return + }, +} + +var id string + +func init() { + GetCmd.Flags().StringVarP(&id, "id", "i", + "", "API Hub Intance Id") +} diff --git a/internal/cmd/apihub/instances/instances.go b/internal/cmd/apihub/instances/instances.go new file mode 100644 index 000000000..ee041c667 --- /dev/null +++ b/internal/cmd/apihub/instances/instances.go @@ -0,0 +1,41 @@ +// 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 instances + +import ( + "github.com/spf13/cobra" +) + +// InstanceCmd to manage apis +var InstanceCmd = &cobra.Command{ + Use: "instances", + Short: "Manage Apigee API Hub Instances", + Long: "Manage Apigee API Hub Instances", +} + +var org, region string + +func init() { + InstanceCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + InstanceCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + InstanceCmd.AddCommand(GetCmd) + InstanceCmd.AddCommand(ListCmd) + + _ = InstanceCmd.MarkFlagRequired("org") + _ = InstanceCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/instances/list.go b/internal/cmd/apihub/instances/list.go new file mode 100644 index 000000000..52177a9fe --- /dev/null +++ b/internal/cmd/apihub/instances/list.go @@ -0,0 +1,38 @@ +// 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 instances + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List API Hub Instances", + Long: "List API Hub Instances", + 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 = hub.LookupInstance() + return + }, +} diff --git a/internal/cmd/root.go b/internal/cmd/root.go index bf5e2f9a4..1e2b1a581 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -29,6 +29,7 @@ import ( "internal/cmd/apicategories" "internal/cmd/apidocs" + "internal/cmd/apihub" "internal/cmd/apis" "internal/cmd/appgroups" "internal/cmd/apps" @@ -192,6 +193,7 @@ func init() { RootCmd.AddCommand(datastores.Cmd) RootCmd.AddCommand(securityprofiles.Cmd) RootCmd.AddCommand(sites.Cmd) + RootCmd.AddCommand(apihub.Cmd) } func initConfig() { diff --git a/test/api-ver.json b/test/api-ver.json new file mode 100644 index 000000000..dee95602b --- /dev/null +++ b/test/api-ver.json @@ -0,0 +1,7 @@ +{ + "displayName": "test version", + "description": "test version description", + "documentation": { + "externalUri": "https://httpbin.org" + } +} diff --git a/test/api.json b/test/api.json new file mode 100644 index 000000000..401748666 --- /dev/null +++ b/test/api.json @@ -0,0 +1,11 @@ +{ + "displayName": "test", + "description": "test description", + "documentation": { + "externalUri": "https://httpbin.org" + }, + "owner": { + "displayName": "Test User", + "email": "user@example.com" + } +} From b0648d2abf54ef537011da9dd0b8b7233ba369d8 Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 21 Jun 2024 16:57:26 +0000 Subject: [PATCH 06/25] feat: enable other apis for API Hub --- internal/client/hub/hub.go | 147 +++++++++--------- internal/cmd/apihub/apihub.go | 2 + internal/cmd/apihub/apis/versions/get.go | 8 +- .../cmd/apihub/apis/versions/specs/get.go | 8 + internal/cmd/apihub/attributes/attributes.go | 43 +++++ internal/cmd/apihub/attributes/create.go | 70 +++++++++ internal/cmd/apihub/attributes/delete.go | 45 ++++++ internal/cmd/apihub/attributes/get.go | 45 ++++++ internal/cmd/apihub/attributes/list.go | 52 +++++++ internal/cmd/apihub/dependencies/create.go | 7 + internal/cmd/apihub/deployments/create.go | 2 + internal/cmd/apihub/externalapis/create.go | 7 +- 12 files changed, 356 insertions(+), 80 deletions(-) create mode 100644 internal/cmd/apihub/attributes/attributes.go create mode 100644 internal/cmd/apihub/attributes/create.go create mode 100644 internal/cmd/apihub/attributes/delete.go create mode 100644 internal/cmd/apihub/attributes/get.go create mode 100644 internal/cmd/apihub/attributes/list.go diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index 5e3ebb46a..14eaae515 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -198,21 +198,7 @@ func GetApi(apiID string) (respBody []byte, err error) { } func ListApi(filter string, pageSize int, pageToken string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "apis") - q := u.Query() - if filter != "" { - q.Set("filter", filter) - } - 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 + return list("apis", filter, pageSize, pageToken) } func CreateApiVersion(versionID string, apiID string, contents []byte) (respBody []byte, err error) { @@ -242,21 +228,7 @@ func DeleteApiVersion(versionID, apiID string) (respBody []byte, err error) { } func ListApiVersions(apiID string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "apis", apiID, "versions") - q := u.Query() - if filter != "" { - q.Set("filter", filter) - } - 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 + return list(path.Join("apis", apiID, "versions"), filter, pageSize, pageToken) } func GetApiVersionsDefinitions(apiID string, versionID string, definition string) (respBody []byte, err error) { @@ -322,7 +294,7 @@ func DeleteApiVersionsSpec(apiID string, versionID string, specID string) (respB return respBody, err } -func GetApiVersionsSpecContent(apiID string, versionID string, specID string) (respBody []byte, err error) { +func GetApiVersionsSpecContents(apiID string, versionID string, specID string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID, ":contents") respBody, err = apiclient.HttpClient(u.String()) @@ -330,21 +302,7 @@ func GetApiVersionsSpecContent(apiID string, versionID string, specID string) (r } func ListApiVersionsSpec(apiID string, versionID string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs") - q := u.Query() - if filter != "" { - q.Set("filter", filter) - } - 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 + return list(path.Join("apis", apiID, "versions", versionID, "specs"), filter, pageSize, pageToken) } func CreateDependency(dependencyID string, description string, consumerDisplayName string, @@ -426,21 +384,7 @@ func DeleteDependency(dependencyID string) (respBody []byte, err error) { } func ListDependencies(filter string, pageSize int, pageToken string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "dependencies") - q := u.Query() - if filter != "" { - q.Set("filter", filter) - } - 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 + return list("dependencies", filter, pageSize, pageToken) } func CreateDeployment(deploymentID string, displayName string, description string, @@ -499,21 +443,7 @@ func DeleteDeployment(deploymentID string) (respBody []byte, err error) { } func ListDeployments(filter string, pageSize int, pageToken string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "dependencies") - q := u.Query() - if filter != "" { - q.Set("filter", filter) - } - 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 + return list("deployments", filter, pageSize, pageToken) } func CreateExternalAPI(externalApiId string, displayName string, description string, @@ -567,8 +497,71 @@ func DeleteExternalAPI(externalApiID string) (respBody []byte, err error) { } func ListExternalAPIs(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + return list("externalApis", filter, pageSize, pageToken) +} + +func CreateAttribute(attributeID string, displayName string, description string, scope string, + dataType string, aValues []byte, cardinality int) (respBody []byte, err error) { + + type attribute struct { + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Scope string `json:"scope,omitempty"` + DataType string `json:"dataType,omitempty"` + AllowedValues []allowedValues `json:"allowedValues,omitempty"` + Cardinality int `json:"cardinality,omitempty"` + } + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "attributes") + q := u.Query() + q.Set("attributeId", attributeID) + u.RawQuery = q.Encode() + + a := attribute{} + a.DisplayName = displayName + a.Description = description + a.Scope = scope + a.DataType = dataType + a.Cardinality = cardinality + + if aValues != nil { + var av []allowedValues + err = json.Unmarshal(aValues, &av) + if err != nil { + return nil, err + } + a.AllowedValues = av + } + + payload, err := json.Marshal(&a) + if err != nil { + return nil, err + } + respBody, err = apiclient.HttpClient(u.String(), string(payload)) + return respBody, err +} + +func GetAttribute(attributeID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "attributes", attributeID) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func DeleteAttribute(attributeID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "attributes", attributeID) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +func ListAttributes(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + return list("attributes", filter, pageSize, pageToken) +} + +func list(resource string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "externalApis") + u.Path = path.Join(u.Path, resource) q := u.Query() if filter != "" { q.Set("filter", filter) diff --git a/internal/cmd/apihub/apihub.go b/internal/cmd/apihub/apihub.go index d8f9cb04b..a23d8be91 100644 --- a/internal/cmd/apihub/apihub.go +++ b/internal/cmd/apihub/apihub.go @@ -16,6 +16,7 @@ package apihub import ( "internal/cmd/apihub/apis" + "internal/cmd/apihub/attributes" "internal/cmd/apihub/dependencies" "internal/cmd/apihub/deployments" "internal/cmd/apihub/externalapis" @@ -37,4 +38,5 @@ func init() { Cmd.AddCommand(deployments.DeploymentCmd) Cmd.AddCommand(dependencies.DependencyCmd) Cmd.AddCommand(externalapis.ExternalAPICmd) + Cmd.AddCommand(attributes.AttributeCmd) } diff --git a/internal/cmd/apihub/apis/versions/get.go b/internal/cmd/apihub/apis/versions/get.go index d47b44273..d0721070b 100644 --- a/internal/cmd/apihub/apis/versions/get.go +++ b/internal/cmd/apihub/apis/versions/get.go @@ -32,18 +32,24 @@ var GetCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true + if definition != "" { + _, err = hub.GetApiVersionsDefinitions(versionID, apiID, definition) + return + } _, err = hub.GetApiVersion(versionID, apiID) return }, } -var versionID string +var versionID, definition string func init() { GetCmd.Flags().StringVarP(&versionID, "version", "v", "", "API Version ID") GetCmd.Flags().StringVarP(&apiID, "api-id", "", "", "API ID") + GetCmd.Flags().StringVarP(&definition, "definition", "d", + "", "Get API Version definition") _ = GetCmd.MarkFlagRequired("api-id") _ = GetCmd.MarkFlagRequired("version") diff --git a/internal/cmd/apihub/apis/versions/specs/get.go b/internal/cmd/apihub/apis/versions/specs/get.go index 183f6a264..b82c5c945 100644 --- a/internal/cmd/apihub/apis/versions/specs/get.go +++ b/internal/cmd/apihub/apis/versions/specs/get.go @@ -32,11 +32,17 @@ var GetCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true + if contents { + _, err = hub.GetApiVersionsSpecContents(apiID, versionID, specID) + return + } _, err = hub.GetApiVersionsSpec(apiID, versionID, specID) return }, } +var contents bool + func init() { GetCmd.Flags().StringVarP(&versionID, "version", "v", "", "API Version ID") @@ -44,6 +50,8 @@ func init() { "", "API ID") GetCmd.Flags().StringVarP(&specID, "spec-id", "s", "", "Spec ID") + GetCmd.Flags().BoolVarP(&contents, "contents", "c", + false, "Get contents") _ = GetCmd.MarkFlagRequired("api-id") _ = GetCmd.MarkFlagRequired("version") diff --git a/internal/cmd/apihub/attributes/attributes.go b/internal/cmd/apihub/attributes/attributes.go new file mode 100644 index 000000000..4c9b0ddf1 --- /dev/null +++ b/internal/cmd/apihub/attributes/attributes.go @@ -0,0 +1,43 @@ +// 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 attributes + +import ( + "github.com/spf13/cobra" +) + +// AttributeCmd to manage apis +var AttributeCmd = &cobra.Command{ + Use: "attributes", + Short: "Manage attributes in API Hub", + Long: "Manage attributes in API Hub", +} + +var org, region string + +func init() { + AttributeCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + AttributeCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + //AttributeCmd.AddCommand(CrtCmd) + AttributeCmd.AddCommand(GetCmd) + AttributeCmd.AddCommand(DelCmd) + AttributeCmd.AddCommand(ListCmd) + + _ = AttributeCmd.MarkFlagRequired("org") + _ = AttributeCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/attributes/create.go b/internal/cmd/apihub/attributes/create.go new file mode 100644 index 000000000..af5b62f4e --- /dev/null +++ b/internal/cmd/apihub/attributes/create.go @@ -0,0 +1,70 @@ +// 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 attributes + +import ( + "internal/apiclient" + "internal/client/hub" + "os" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new Attribute in API Hub", + Long: "Create a new Attribute in API Hub", + 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 + var aValues []byte + + if aValues, err = os.ReadFile(aValuesPath); err != nil { + return err + } + _, err = hub.CreateAttribute(attributeID, displayName, description, scope, dataType, aValues, cardinality) + return + }, +} + +var attributeID, displayName, description, scope, dataType, aValuesPath string +var cardinality int + +func init() { + CrtCmd.Flags().StringVarP(&attributeID, "id", "i", + "", "Attribute ID") + CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Attribute Display Name") + CrtCmd.Flags().StringVarP(&description, "description", "", + "", "Attribute Description") + CrtCmd.Flags().StringVarP(&scope, "scope", "s", + "", "Attribute scope") + CrtCmd.Flags().StringVarP(&dataType, "data-type", "", + "", "Attribute data type") + CrtCmd.Flags().IntVarP(&cardinality, "cardinality", "c", + 1, "Attribute cardinality") + CrtCmd.Flags().StringVarP(&aValuesPath, "allowed-values", "", + "", "Path to a file containing allowed values") + + _ = CrtCmd.MarkFlagRequired("id") + _ = CrtCmd.MarkFlagRequired("display-name") + _ = CrtCmd.MarkFlagRequired("scope") + _ = CrtCmd.MarkFlagRequired("data-type") + +} diff --git a/internal/cmd/apihub/attributes/delete.go b/internal/cmd/apihub/attributes/delete.go new file mode 100644 index 000000000..f254cfcbf --- /dev/null +++ b/internal/cmd/apihub/attributes/delete.go @@ -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 attributes + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete an Attribute", + Long: "Delete an Attribute", + 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 = hub.DeleteAttribute(attributeID) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&attributeID, "id", "i", + "", "Attribute ID") + + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/attributes/get.go b/internal/cmd/apihub/attributes/get.go new file mode 100644 index 000000000..398cd15ff --- /dev/null +++ b/internal/cmd/apihub/attributes/get.go @@ -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 attributes + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for an Attribute", + Long: "Get details for an Attribute", + 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 = hub.GetAttribute(attributeID) + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&attributeID, "id", "i", + "", "Dependency ID") + + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/attributes/list.go b/internal/cmd/apihub/attributes/list.go new file mode 100644 index 000000000..7495bb5b8 --- /dev/null +++ b/internal/cmd/apihub/attributes/list.go @@ -0,0 +1,52 @@ +// 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 attributes + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List attributes", + Long: "List attributes", + 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 = hub.ListAttributes(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/dependencies/create.go b/internal/cmd/apihub/dependencies/create.go index 659f3bedf..36c163d43 100644 --- a/internal/cmd/apihub/dependencies/create.go +++ b/internal/cmd/apihub/dependencies/create.go @@ -32,9 +32,15 @@ var CrtCmd = &cobra.Command{ extApiPattern := `^projects/[^/]+/locations/[^/]+/apis/[^/]+/externalApis/[^/]+$` opPattern := `^projects/[^/]+/locations/[^/]+/apis/[^/]+/versions/[^/]+/operations/[^/]+$` + if consumerExternalApiResouceName == "" && consumerOperationResourceName == "" { + return fmt.Errorf("at least one of consumer-ext-api-res-name or consumer-op-res-name must be set") + } if consumerExternalApiResouceName != "" && consumerOperationResourceName != "" { return fmt.Errorf("consumer-ext-api-res-name and consumer-op-res-name cannot be used together") } + if supplierExternalApiResourceName == "" && supplierOperationResourceName == "" { + return fmt.Errorf("at least one of supplier-ext-api-res-name and supplier-op-res-name must be set") + } if supplierExternalApiResourceName != "" && supplierOperationResourceName != "" { return fmt.Errorf("supplier-ext-api-res-name and supplier-op-res-name cannot be used together") } @@ -87,4 +93,5 @@ func init() { CrtCmd.Flags().StringVarP(&supplierExternalApiResourceName, "supplier-ext-api-res-name", "", "", "Supplier External API Resource Name") + _ = CrtCmd.MarkFlagRequired("id") } diff --git a/internal/cmd/apihub/deployments/create.go b/internal/cmd/apihub/deployments/create.go index f2d260102..fa6f58e61 100644 --- a/internal/cmd/apihub/deployments/create.go +++ b/internal/cmd/apihub/deployments/create.go @@ -42,6 +42,8 @@ var endpoints []string var d hub.DeploymentType func init() { + CrtCmd.Flags().StringVarP(&deploymentID, "id", "i", + "", "Deployment ID") CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", "", "Deployment Display Name") CrtCmd.Flags().StringVarP(&description, "description", "", diff --git a/internal/cmd/apihub/externalapis/create.go b/internal/cmd/apihub/externalapis/create.go index 2f8d21abb..63e3a2c06 100644 --- a/internal/cmd/apihub/externalapis/create.go +++ b/internal/cmd/apihub/externalapis/create.go @@ -41,10 +41,12 @@ var externalApiId, displayName, description, externalURI, resourceURI string var endpoints, paths []string func init() { + CrtCmd.Flags().StringVarP(&externalApiID, "id", "i", + "", "External API ID") CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", - "", "Deployment Display Name") + "", "Exernal API Display Name") CrtCmd.Flags().StringVarP(&description, "description", "", - "", "Deployment Description") + "", "External API Description") CrtCmd.Flags().StringVarP(&externalURI, "external-uri", "", "", "The uri of the externally hosted documentation") CrtCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", @@ -54,6 +56,7 @@ func init() { CrtCmd.Flags().StringArrayVarP(&paths, "paths", "", []string{}, " API base paths") + _ = CrtCmd.MarkFlagRequired("id") _ = CrtCmd.MarkFlagRequired("display-name") _ = CrtCmd.MarkFlagRequired("resource-uri") _ = CrtCmd.MarkFlagRequired("endpoints") From b9c4f96a90295158a9bb3e4a3290bf65dbfc9f8a Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 21 Jun 2024 18:34:43 +0000 Subject: [PATCH 07/25] feat: enable runtime attachments to API Hub --- internal/client/hub/hub.go | 72 +++++++++++++++++-- internal/cmd/apihub/apihub.go | 2 + .../cmd/apihub/apis/versions/specs/lint.go | 51 +++++++++++++ .../cmd/apihub/apis/versions/specs/specs.go | 1 + .../cmd/apihub/projectattachments/create.go | 50 +++++++++++++ .../cmd/apihub/projectattachments/delete.go | 45 ++++++++++++ internal/cmd/apihub/projectattachments/get.go | 47 ++++++++++++ .../cmd/apihub/projectattachments/list.go | 52 ++++++++++++++ .../projectattachments/projectattachments.go | 43 +++++++++++ 9 files changed, 356 insertions(+), 7 deletions(-) create mode 100644 internal/cmd/apihub/apis/versions/specs/lint.go create mode 100644 internal/cmd/apihub/projectattachments/create.go create mode 100644 internal/cmd/apihub/projectattachments/delete.go create mode 100644 internal/cmd/apihub/projectattachments/get.go create mode 100644 internal/cmd/apihub/projectattachments/list.go create mode 100644 internal/cmd/apihub/projectattachments/projectattachments.go diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index 14eaae515..f6eb4ad8a 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -162,11 +162,8 @@ func GetRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody [] return respBody, err } -func ListRuntimeProjectAttachment(runtimeProjectAttachmentId string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "runtimeProjectAttachments") - respBody, err = apiclient.HttpClient(u.String()) - return respBody, err +func ListRuntimeProjectAttachments(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + return list("runtimeProjectAttachments", filter, pageSize, pageToken) } func CreateApi(apiID string, contents []byte) (respBody []byte, err error) { @@ -305,6 +302,13 @@ func ListApiVersionsSpec(apiID string, versionID string, filter string, pageSize return list(path.Join("apis", apiID, "versions", versionID, "specs"), filter, pageSize, pageToken) } +func LintApiVersionSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID, ":lint") + respBody, err = apiclient.HttpClient(u.String(), "") + return respBody, err +} + func CreateDependency(dependencyID string, description string, consumerDisplayName string, consumerOperationResourceName string, consumerExternalApiResourceName string, supplierDisplayName string, supplierOperationResourceName string, supplierExternalApiResourceName string) (respBody []byte, err error) { @@ -636,9 +640,63 @@ func getDeploymentEnum(d DeploymentType) specType { Description: "Apigee Hybrid", Immutable: true, }) + case APIGEE_EDGE_PRIVATE: + return getSpecType(allowedValues{ + Id: "apigee-edge-private", + DisplayName: "Apigee Edge Private Cloud", + Description: "Apigee Edge Private Cloud", + Immutable: true, + }) + case APIGEE_EDGE_PUBLIC: + return getSpecType(allowedValues{ + Id: "apigee-edge-public", + DisplayName: "Apigee Edge Public Cloud", + Description: "Apigee Edge Public Cloud", + Immutable: true, + }) + case MOCK_SERVER: + return getSpecType(allowedValues{ + Id: "mock-server", + DisplayName: "Mock Server", + Description: "Mock Server", + Immutable: true, + }) + case CLOUD_API_GATEWAY: + return getSpecType(allowedValues{ + Id: "cloud-api-gateway", + DisplayName: "Cloud API Gateway", + Description: "Cloud API Gateway", + Immutable: true, + }) + case CLOUD_ENDPOINTS: + return getSpecType(allowedValues{ + Id: "cloud-endpoints", + DisplayName: "Cloud Endpoints", + Description: "Cloud Endpoints", + Immutable: true, + }) + case UNMANAGED: + return getSpecType(allowedValues{ + Id: "unmanaged", + DisplayName: "Unmanaged", + Description: "Unmanaged", + Immutable: true, + }) + case OTHERS: + return getSpecType(allowedValues{ + Id: "others", + DisplayName: "Others", + Description: "Others", + Immutable: true, + }) + default: + return getSpecType(allowedValues{ + Id: "others", + DisplayName: "Others", + Description: "Others", + Immutable: true, + }) } - - return specType{} } func (d *DeploymentType) String() string { diff --git a/internal/cmd/apihub/apihub.go b/internal/cmd/apihub/apihub.go index a23d8be91..6ec5799bf 100644 --- a/internal/cmd/apihub/apihub.go +++ b/internal/cmd/apihub/apihub.go @@ -21,6 +21,7 @@ import ( "internal/cmd/apihub/deployments" "internal/cmd/apihub/externalapis" "internal/cmd/apihub/instances" + "internal/cmd/apihub/projectattachments" "github.com/spf13/cobra" ) @@ -39,4 +40,5 @@ func init() { Cmd.AddCommand(dependencies.DependencyCmd) Cmd.AddCommand(externalapis.ExternalAPICmd) Cmd.AddCommand(attributes.AttributeCmd) + Cmd.AddCommand(projectattachments.ProjectAttachmentCmd) } diff --git a/internal/cmd/apihub/apis/versions/specs/lint.go b/internal/cmd/apihub/apis/versions/specs/lint.go new file mode 100644 index 000000000..8e45dbda0 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/lint.go @@ -0,0 +1,51 @@ +// 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 specs + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// LintCmd to get a catalog items +var LintCmd = &cobra.Command{ + Use: "lint", + Short: "Lint a spec for an API Version", + Long: "Lint a spec for an API Version", + 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 = hub.LintApiVersionSpec(apiID, versionID, specID) + return + }, +} + +func init() { + LintCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + LintCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + LintCmd.Flags().StringVarP(&specID, "spec-id", "s", + "", "Spec ID") + + _ = LintCmd.MarkFlagRequired("api-id") + _ = LintCmd.MarkFlagRequired("version") + _ = LintCmd.MarkFlagRequired("spec-id") +} diff --git a/internal/cmd/apihub/apis/versions/specs/specs.go b/internal/cmd/apihub/apis/versions/specs/specs.go index 93a34e3a0..636556903 100644 --- a/internal/cmd/apihub/apis/versions/specs/specs.go +++ b/internal/cmd/apihub/apis/versions/specs/specs.go @@ -37,6 +37,7 @@ func init() { SpecsCmd.AddCommand(GetCmd) SpecsCmd.AddCommand(DelCmd) SpecsCmd.AddCommand(ListCmd) + SpecsCmd.AddCommand(LintCmd) _ = SpecsCmd.MarkFlagRequired("org") _ = SpecsCmd.MarkFlagRequired("region") diff --git a/internal/cmd/apihub/projectattachments/create.go b/internal/cmd/apihub/projectattachments/create.go new file mode 100644 index 000000000..9022ba623 --- /dev/null +++ b/internal/cmd/apihub/projectattachments/create.go @@ -0,0 +1,50 @@ +// 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 projectattachments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API External API", + Long: "Create a new API External API", + 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 = hub.CreateRuntimeProjectAttachment(runtimeProjectAttachmentId, runtimeProject) + return + }, +} + +var runtimeProject string + +func init() { + CrtCmd.Flags().StringVarP(&runtimeProjectAttachmentId, "id", "i", + "", "RuntimeProjectAttachment ID") + CrtCmd.Flags().StringVarP(&runtimeProject, "runtime-project", "p", + "", "Runtime Project ID") + + _ = CrtCmd.MarkFlagRequired("id") + _ = CrtCmd.MarkFlagRequired("runtime-project") +} diff --git a/internal/cmd/apihub/projectattachments/delete.go b/internal/cmd/apihub/projectattachments/delete.go new file mode 100644 index 000000000..b7fb544f1 --- /dev/null +++ b/internal/cmd/apihub/projectattachments/delete.go @@ -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 projectattachments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a Runtime Project Attachment", + Long: "Delete a Runtime Project Attachment", + 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 = hub.DeleteRuntimeProjectAttachment(runtimeProjectAttachmentId) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&runtimeProjectAttachmentId, "id", "i", + "", "RuntimeProjectAttachment ID") + + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/projectattachments/get.go b/internal/cmd/apihub/projectattachments/get.go new file mode 100644 index 000000000..b09a7bdc2 --- /dev/null +++ b/internal/cmd/apihub/projectattachments/get.go @@ -0,0 +1,47 @@ +// 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 projectattachments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Get details for a Runtime Project Attachment", + Long: "Get details for a Runtime Project Attachment", + 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 = hub.GetRuntimeProjectAttachment(runtimeProjectAttachmentId) + return + }, +} + +var runtimeProjectAttachmentId string + +func init() { + GetCmd.Flags().StringVarP(&runtimeProjectAttachmentId, "id", "i", + "", "RuntimeProjectAttachment ID") + + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/projectattachments/list.go b/internal/cmd/apihub/projectattachments/list.go new file mode 100644 index 000000000..40d6b2fe7 --- /dev/null +++ b/internal/cmd/apihub/projectattachments/list.go @@ -0,0 +1,52 @@ +// 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 projectattachments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List Runtime Project Attachments", + Long: "List Runtime Project Attachments", + 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 = hub.ListRuntimeProjectAttachments(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/projectattachments/projectattachments.go b/internal/cmd/apihub/projectattachments/projectattachments.go new file mode 100644 index 000000000..b7c264a43 --- /dev/null +++ b/internal/cmd/apihub/projectattachments/projectattachments.go @@ -0,0 +1,43 @@ +// 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 projectattachments + +import ( + "github.com/spf13/cobra" +) + +// ProjectAttachmentCmd to manage apis +var ProjectAttachmentCmd = &cobra.Command{ + Use: "project-attachments", + Short: "Manage Runtime Project Attachments to API Hub", + Long: "Manage Runtime Project Attachments to API Hub", +} + +var org, region string + +func init() { + ProjectAttachmentCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + ProjectAttachmentCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + //ProjectAttachmentCmd.AddCommand(CrtCmd) + ProjectAttachmentCmd.AddCommand(GetCmd) + ProjectAttachmentCmd.AddCommand(DelCmd) + ProjectAttachmentCmd.AddCommand(ListCmd) + + _ = ProjectAttachmentCmd.MarkFlagRequired("org") + _ = ProjectAttachmentCmd.MarkFlagRequired("region") +} From aacd87b6a63ac56d33c22d3bc010d1bfa8d70ea7 Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 21 Jun 2024 19:05:21 +0000 Subject: [PATCH 08/25] feat: enable prj registrations to API Hub --- internal/client/hub/hub.go | 7 +-- internal/cmd/apihub/apihub.go | 2 + .../projectattachments/projectattachments.go | 2 +- .../cmd/apihub/projectregistrations/create.go | 50 ++++++++++++++++++ .../cmd/apihub/projectregistrations/list.go | 52 +++++++++++++++++++ .../projectregistrations.go | 41 +++++++++++++++ 6 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 internal/cmd/apihub/projectregistrations/create.go create mode 100644 internal/cmd/apihub/projectregistrations/list.go create mode 100644 internal/cmd/apihub/projectregistrations/projectregistrations.go diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index f6eb4ad8a..9a42ebe2d 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -127,11 +127,8 @@ func RegisterHostProject(registrationId string, gcpProjectId string) (respBody [ return respBody, err } -func ListHostProjects() (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "hostProjectRegistrations") - respBody, err = apiclient.HttpClient(u.String()) - return respBody, err +func ListHostProjects(filter string, pageSize int, pageToken string) (respBody []byte, err error) { + return list("hostProjectRegistrations", filter, pageSize, pageToken) } func CreateRuntimeProjectAttachment(runtimeProjectAttachmentId string, runtimeProject string) (respBody []byte, err error) { diff --git a/internal/cmd/apihub/apihub.go b/internal/cmd/apihub/apihub.go index 6ec5799bf..919750b74 100644 --- a/internal/cmd/apihub/apihub.go +++ b/internal/cmd/apihub/apihub.go @@ -22,6 +22,7 @@ import ( "internal/cmd/apihub/externalapis" "internal/cmd/apihub/instances" "internal/cmd/apihub/projectattachments" + "internal/cmd/apihub/projectregistrations" "github.com/spf13/cobra" ) @@ -41,4 +42,5 @@ func init() { Cmd.AddCommand(externalapis.ExternalAPICmd) Cmd.AddCommand(attributes.AttributeCmd) Cmd.AddCommand(projectattachments.ProjectAttachmentCmd) + Cmd.AddCommand(projectregistrations.ProjectRegistrationCmd) } diff --git a/internal/cmd/apihub/projectattachments/projectattachments.go b/internal/cmd/apihub/projectattachments/projectattachments.go index b7c264a43..cc2a30257 100644 --- a/internal/cmd/apihub/projectattachments/projectattachments.go +++ b/internal/cmd/apihub/projectattachments/projectattachments.go @@ -33,7 +33,7 @@ func init() { ProjectAttachmentCmd.PersistentFlags().StringVarP(®ion, "region", "r", "", "API Hub region name") - //ProjectAttachmentCmd.AddCommand(CrtCmd) + ProjectAttachmentCmd.AddCommand(CrtCmd) ProjectAttachmentCmd.AddCommand(GetCmd) ProjectAttachmentCmd.AddCommand(DelCmd) ProjectAttachmentCmd.AddCommand(ListCmd) diff --git a/internal/cmd/apihub/projectregistrations/create.go b/internal/cmd/apihub/projectregistrations/create.go new file mode 100644 index 000000000..50da4ad1b --- /dev/null +++ b/internal/cmd/apihub/projectregistrations/create.go @@ -0,0 +1,50 @@ +// 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 projectregistrations + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create a host project registration", + Long: "Create a host project registration", + 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 = hub.RegisterHostProject(registrationId, gcpProjectId) + return + }, +} + +var registrationId, gcpProjectId string + +func init() { + CrtCmd.Flags().StringVarP(®istrationId, "id", "i", + "", "Registration ID") + CrtCmd.Flags().StringVarP(&gcpProjectId, "project-id", "p", + "", "Host Project ID") + + _ = CrtCmd.MarkFlagRequired("id") + _ = CrtCmd.MarkFlagRequired("project-id") +} diff --git a/internal/cmd/apihub/projectregistrations/list.go b/internal/cmd/apihub/projectregistrations/list.go new file mode 100644 index 000000000..563e96ac7 --- /dev/null +++ b/internal/cmd/apihub/projectregistrations/list.go @@ -0,0 +1,52 @@ +// 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 projectregistrations + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ListCmd to get a catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "List Host Project Registrations", + Long: "List Host Project Registrations", + 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 = hub.ListHostProjects(filter, pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken, filter string +) + +func init() { + ListCmd.Flags().StringVarP(&filter, "filter", "f", + "", "filter expression") + ListCmd.Flags().IntVarP(&pageSize, "page-size", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "page-token", "", + "", "A page token, received from a previous call") +} diff --git a/internal/cmd/apihub/projectregistrations/projectregistrations.go b/internal/cmd/apihub/projectregistrations/projectregistrations.go new file mode 100644 index 000000000..239179bf9 --- /dev/null +++ b/internal/cmd/apihub/projectregistrations/projectregistrations.go @@ -0,0 +1,41 @@ +// 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 projectregistrations + +import ( + "github.com/spf13/cobra" +) + +// ProjectRegistrationCmd to manage apis +var ProjectRegistrationCmd = &cobra.Command{ + Use: "project-registrations", + Short: "Manage Host Project Registrations with API Hub", + Long: "Manage Host Project Registrations with API Hub", +} + +var org, region string + +func init() { + ProjectRegistrationCmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + ProjectRegistrationCmd.PersistentFlags().StringVarP(®ion, "region", "r", + "", "API Hub region name") + + ProjectRegistrationCmd.AddCommand(CrtCmd) + ProjectRegistrationCmd.AddCommand(ListCmd) + + _ = ProjectRegistrationCmd.MarkFlagRequired("org") + _ = ProjectRegistrationCmd.MarkFlagRequired("region") +} From 68ba40eca2578b4854f4b594f1fa5ea26c887acc Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 21 Jun 2024 20:50:20 +0000 Subject: [PATCH 09/25] chore: add unit tests for API Hub --- internal/client/apidocs/apidocs_test.go | 2 +- internal/client/hub/hub.go | 43 +- internal/client/hub/hub_test.go | 457 ++++++++++++++++++ internal/cmd/apihub/apis/create.go | 4 +- .../cmd/apihub/apis/versions/specs/create.go | 3 + .../cmd/apihub/apis/versions/specs/delete.go | 2 +- .../cmd/apihub/apis/versions/specs/get.go | 2 +- .../cmd/apihub/apis/versions/specs/list.go | 2 +- 8 files changed, 498 insertions(+), 17 deletions(-) create mode 100644 internal/client/hub/hub_test.go diff --git a/internal/client/apidocs/apidocs_test.go b/internal/client/apidocs/apidocs_test.go index 2109f2b39..fb86e394e 100644 --- a/internal/client/apidocs/apidocs_test.go +++ b/internal/client/apidocs/apidocs_test.go @@ -110,7 +110,7 @@ func TestUpdateDocumentation(t *testing.T) { if openAPIDoc, err = utils.ReadFile(path.Join(cliPath, "test", "openapi.json")); err != nil { t.Fatalf("%v", err) } - if _, err = UpdateDocumentation(siteID, aPIDocID, displayName, string(openAPIDoc), "", ""); err != nil { + if _, err = UpdateDocumentation(siteID, aPIDocID, displayName, openAPIDoc, nil, ""); err != nil { t.Fatalf("%v", err) } } diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index 9a42ebe2d..a7a9bca95 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -274,14 +274,14 @@ func CreateApiVersionsSpec(apiID string, versionID string, specID string, displa return respBody, err } -func GetApiVersionsSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { +func GetApiVersionSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID) respBody, err = apiclient.HttpClient(u.String()) return respBody, err } -func DeleteApiVersionsSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { +func DeleteApiVersionSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID) respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") @@ -295,7 +295,7 @@ func GetApiVersionsSpecContents(apiID string, versionID string, specID string) ( return respBody, err } -func ListApiVersionsSpec(apiID string, versionID string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { +func ListApiVersionSpecs(apiID string, versionID string, filter string, pageSize int, pageToken string) (respBody []byte, err error) { return list(path.Join("apis", apiID, "versions", versionID, "specs"), filter, pageSize, pageToken) } @@ -504,14 +504,35 @@ func ListExternalAPIs(filter string, pageSize int, pageToken string) (respBody [ func CreateAttribute(attributeID string, displayName string, description string, scope string, dataType string, aValues []byte, cardinality int) (respBody []byte, err error) { + type attributeScope string + const ( + API attributeScope = "API" + VERSION attributeScope = "VERSION" + SPEC attributeScope = "SPEC" + API_OPERATION attributeScope = "API_OPERATION" + DEPLOYMENT attributeScope = "DEPLOYMENT" + DEPENDENCY attributeScope = "DEPENDENCY" + DEFINITION attributeScope = "DEFINITION" + EXTERNAL_API attributeScope = "EXTERNAL_API" + PLUGIN attributeScope = "PLUGIN" + ) + + type attributeDataType string + const ( + ENUM attributeDataType = "ENUM" + JSON attributeDataType = "JSON" + STRING attributeDataType = "STRING" + ) + type attribute struct { - DisplayName string `json:"displayName,omitempty"` - Description string `json:"description,omitempty"` - Scope string `json:"scope,omitempty"` - DataType string `json:"dataType,omitempty"` - AllowedValues []allowedValues `json:"allowedValues,omitempty"` - Cardinality int `json:"cardinality,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Scope attributeScope `json:"scope,omitempty"` + DataType attributeDataType `json:"dataType,omitempty"` + AllowedValues []allowedValues `json:"allowedValues,omitempty"` + Cardinality int `json:"cardinality,omitempty"` } + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "attributes") q := u.Query() @@ -521,8 +542,8 @@ func CreateAttribute(attributeID string, displayName string, description string, a := attribute{} a.DisplayName = displayName a.Description = description - a.Scope = scope - a.DataType = dataType + a.Scope = attributeScope(scope) + a.DataType = attributeDataType(dataType) a.Cardinality = cardinality if aValues != nil { diff --git a/internal/client/hub/hub_test.go b/internal/client/hub/hub_test.go new file mode 100644 index 000000000..0f29da4dd --- /dev/null +++ b/internal/client/hub/hub_test.go @@ -0,0 +1,457 @@ +// 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 hub + +import ( + "internal/client/clienttest" + "internal/cmd/utils" + "os" + "path" + "testing" +) + +var ( + cliPath = os.Getenv("APIGEECLI_PATH") +) + +func TestCreateApi(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + var contents []byte + + if contents, err = utils.ReadFile(path.Join(cliPath, "test", "api.json")); err != nil { + t.Errorf("failed to read api.json: %v", err) + } + + if _, err = CreateApi(apiID, contents); err != nil { + t.Errorf("failed to create api: %v", err) + } +} + +func TestGetApi(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + apiID := "test-api" + if _, err = GetApi(apiID); err != nil { + t.Errorf("failed to get api: %v", err) + } +} + +func TestListApi(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + if _, err = ListApi("", -1, ""); err != nil { + t.Errorf("failed to list api: %v", err) + } +} + +func TestCreateApiVersion(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + var contents []byte + + if contents, err = utils.ReadFile(path.Join(cliPath, "test", "api-ver.json")); err != nil { + t.Errorf("failed to read api.json: %v", err) + } + + apiID := "test-api" + versionID := "test-version" + + if _, err = CreateApiVersion(apiID, versionID, contents); err != nil { + t.Errorf("failed to create api version: %v", err) + } +} + +func TestGetApiVersion(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + versionID := "test-version" + + if _, err = GetApiVersion(apiID, versionID); err != nil { + t.Errorf("failed to get api version: %v", err) + } +} + +func TestListApiVersion(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + + if _, err = ListApiVersions(apiID, "", -1, ""); err != nil { + t.Errorf("failed to list api version: %v", err) + } +} + +func TestCreateApiVersionsSpec(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + var contents []byte + + if contents, err = utils.ReadFile(path.Join(cliPath, "test", "petstore-v3.1.json")); err != nil { + t.Errorf("failed to read api.json: %v", err) + } + + apiID := "test-api" + versionID := "test-version" + specID := "test-spec" + displayName := "test-spec" + mimeType := "json" + sourceURI := "" + documentation := "" + + if _, err = CreateApiVersionsSpec(apiID, versionID, specID, displayName, contents, mimeType, sourceURI, documentation); err != nil { + t.Errorf("failed to create api version spec: %v", err) + } +} + +func TestGetApiVersionSpec(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + versionID := "test-version" + specID := "test-spec" + + if _, err = GetApiVersionSpec(apiID, versionID, specID); err != nil { + t.Errorf("failed to get api version spec: %v", err) + } +} + +func TestGetApiVersionsSpecContents(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + versionID := "test-version" + specID := "test-spec" + + if _, err = GetApiVersionsSpecContents(apiID, versionID, specID); err != nil { + t.Errorf("failed to get api version spec contents: %v", err) + } +} + +func TestLintApiVersionSpecs(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + versionID := "test-version" + specID := "test-spec" + + if _, err = LintApiVersionSpec(apiID, versionID, specID); err != nil { + t.Errorf("failed to lint api version spec: %v", err) + } +} + +func TestListApiVersionSpecs(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + apiID := "test-api" + versionID := "test-version" + + if _, err = ListApiVersionSpecs(apiID, versionID, "", -1, ""); err != nil { + t.Errorf("failed to list api version specs: %v", err) + } +} + +func TestDeleteApiVersionSpec(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + apiID := "test-api" + versionID := "test-version" + specID := "test-spec" + + if _, err = DeleteApiVersionSpec(apiID, versionID, specID); err != nil { + t.Errorf("failed to delete api version spec: %v", err) + } +} + +func TestDeleteApiVersion(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + apiID := "test-api" + versionID := "test-version" + + if _, err = DeleteApiVersion(apiID, versionID); err != nil { + t.Errorf("failed to delete api version: %v", err) + } +} + +func TestDeleteApi(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + apiID := "test-api" + + if _, err = DeleteApi(apiID); err != nil { + t.Errorf("failed to delete api: %v", err) + } +} + +func TestCreateAttribute(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + var aValues []byte + attributeID := "test-attribute" + displayName := "test attribute" + description := "test description" + scope := "API" + dataType := "ENUM" + cardinality := 1 + + if _, err := CreateAttribute(attributeID, displayName, description, + scope, dataType, aValues, cardinality); err != nil { + t.Errorf("failed to create attribute %v", err) + } +} + +func TestGetAttribute(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + attributeID := "test-attribute" + + if _, err := GetAttribute(attributeID); err != nil { + t.Errorf("failed to get attribute %v", err) + } +} + +func TestListAttribute(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + if _, err := ListAttributes("", -1, ""); err != nil { + t.Errorf("failed to list attributes %v", err) + } +} + +func TestDeleteAttribute(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + attributeID := "test-attribute" + + if _, err := DeleteAttribute(attributeID); err != nil { + t.Errorf("failed to get attribute %v", err) + } +} + +func TestCreateDependency(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + dependencyID := "test-dependency" + description := "test description" + consumerDisplayName := "test consumer" + supplierDisplayName := "test supplier" + consumerOperationResourceName := "test" + consumerExternalApiResourceName := "" + supplierOperationResourceName := "test" + supplierExternalApiResourceName := "" + + if _, err = CreateDependency(dependencyID, description, consumerDisplayName, + consumerOperationResourceName, consumerExternalApiResourceName, supplierDisplayName, + supplierOperationResourceName, supplierExternalApiResourceName); err != nil { + t.Errorf("failed to create dependency %v", err) + } +} + +func TestGetDependency(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + dependencyID := "test-dependency" + + if _, err := GetDependency(dependencyID); err != nil { + t.Errorf("failed to get attribute %v", err) + } +} + +func TestListDependencies(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + if _, err := ListDependencies("", -1, ""); err != nil { + t.Errorf("failed to list attributes %v", err) + } +} + +func TestDeleteDependency(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + dependencyID := "test-dependency" + + if _, err := DeleteDependency(dependencyID); err != nil { + t.Errorf("failed to get attribute %v", err) + } +} diff --git a/internal/cmd/apihub/apis/create.go b/internal/cmd/apihub/apis/create.go index a8a8bccd1..5d64e0cdc 100644 --- a/internal/cmd/apihub/apis/create.go +++ b/internal/cmd/apihub/apis/create.go @@ -46,11 +46,11 @@ var CrtCmd = &cobra.Command{ var id, apiFilePath string func init() { - CrtCmd.Flags().StringVarP(&id, "api-id", "", + CrtCmd.Flags().StringVarP(&id, "id", "i", "", "API ID") CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", "", "Path to a file containing the API defintion") - _ = CrtCmd.MarkFlagRequired("api-id") + _ = CrtCmd.MarkFlagRequired("id") _ = CrtCmd.MarkFlagRequired("file") } diff --git a/internal/cmd/apihub/apis/versions/specs/create.go b/internal/cmd/apihub/apis/versions/specs/create.go index fe0da0ff3..b04f69f1f 100644 --- a/internal/cmd/apihub/apis/versions/specs/create.go +++ b/internal/cmd/apihub/apis/versions/specs/create.go @@ -49,6 +49,8 @@ var specID, displayName, mimeType, sourceURI, documentation, apiFilePath string var attributes map[string]string func init() { + CrtCmd.Flags().StringVarP(&specID, "id", "i", + "", "Spec ID") CrtCmd.Flags().StringVarP(&versionID, "version", "v", "", "API Version ID") CrtCmd.Flags().StringVarP(&apiID, "api-id", "", @@ -64,6 +66,7 @@ func init() { CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", "", "Path to a file containing the API spec") + _ = CrtCmd.MarkFlagRequired("id") _ = CrtCmd.MarkFlagRequired("api-id") _ = CrtCmd.MarkFlagRequired("version") _ = CrtCmd.MarkFlagRequired("display-name") diff --git a/internal/cmd/apihub/apis/versions/specs/delete.go b/internal/cmd/apihub/apis/versions/specs/delete.go index 34c0b3a6d..78a2afeeb 100644 --- a/internal/cmd/apihub/apis/versions/specs/delete.go +++ b/internal/cmd/apihub/apis/versions/specs/delete.go @@ -32,7 +32,7 @@ var DelCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true - _, err = hub.DeleteApiVersionsSpec(apiID, versionID, specID) + _, err = hub.DeleteApiVersionSpec(apiID, versionID, specID) return }, } diff --git a/internal/cmd/apihub/apis/versions/specs/get.go b/internal/cmd/apihub/apis/versions/specs/get.go index b82c5c945..79cd169cb 100644 --- a/internal/cmd/apihub/apis/versions/specs/get.go +++ b/internal/cmd/apihub/apis/versions/specs/get.go @@ -36,7 +36,7 @@ var GetCmd = &cobra.Command{ _, err = hub.GetApiVersionsSpecContents(apiID, versionID, specID) return } - _, err = hub.GetApiVersionsSpec(apiID, versionID, specID) + _, err = hub.GetApiVersionSpec(apiID, versionID, specID) return }, } diff --git a/internal/cmd/apihub/apis/versions/specs/list.go b/internal/cmd/apihub/apis/versions/specs/list.go index 6bc6efccc..7087caa79 100644 --- a/internal/cmd/apihub/apis/versions/specs/list.go +++ b/internal/cmd/apihub/apis/versions/specs/list.go @@ -32,7 +32,7 @@ var ListCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true - _, err = hub.ListApiVersionsSpec(apiID, versionID, filter, pageSize, pageToken) + _, err = hub.ListApiVersionSpecs(apiID, versionID, filter, pageSize, pageToken) return }, } From 545758ea2d10d6af3249661c3e02461a88a768a5 Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 21 Jun 2024 22:01:37 +0000 Subject: [PATCH 10/25] feat: create apihub instances --- internal/client/hub/hub_test.go | 153 ++++++++++++++++++++- internal/cmd/apihub/instances/create.go | 56 ++++++++ internal/cmd/apihub/instances/get.go | 2 + internal/cmd/apihub/instances/instances.go | 1 + 4 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 internal/cmd/apihub/instances/create.go diff --git a/internal/client/hub/hub_test.go b/internal/client/hub/hub_test.go index 0f29da4dd..58842a2a6 100644 --- a/internal/client/hub/hub_test.go +++ b/internal/client/hub/hub_test.go @@ -419,7 +419,7 @@ func TestGetDependency(t *testing.T) { dependencyID := "test-dependency" if _, err := GetDependency(dependencyID); err != nil { - t.Errorf("failed to get attribute %v", err) + t.Errorf("failed to get dependency %v", err) } } @@ -435,7 +435,7 @@ func TestListDependencies(t *testing.T) { } if _, err := ListDependencies("", -1, ""); err != nil { - t.Errorf("failed to list attributes %v", err) + t.Errorf("failed to list dependencies %v", err) } } @@ -452,6 +452,153 @@ func TestDeleteDependency(t *testing.T) { dependencyID := "test-dependency" if _, err := DeleteDependency(dependencyID); err != nil { - t.Errorf("failed to get attribute %v", err) + t.Errorf("failed to get dependency %v", err) + } +} + +func TestCreateDeployment(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + deploymentID := "test-deployment" + description := "test description" + displayName := "test display name" + externalURI := "https://httpbin.org/get" + resourceURI := "https://httpbin.org/get" + endpoints := []string{"https://httpbin.org/get"} + + if _, err = CreateDeployment(deploymentID, displayName, description, externalURI, + resourceURI, endpoints, APIGEE); err != nil { + t.Errorf("failed to create deployment %v", err) + } +} + +func TestGetDeployment(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + deploymentID := "test-deployment" + + if _, err := GetDeployment(deploymentID); err != nil { + t.Errorf("failed to get deployment %v", err) + } +} + +func TestListDeployment(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + if _, err := ListDeployments("", -1, ""); err != nil { + t.Errorf("failed to list deployments %v", err) + } +} + +func TestDeleteDeployment(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + deploymentID := "test-deployment" + + if _, err := DeleteDeployment(deploymentID); err != nil { + t.Errorf("failed to delete deployment %v", err) + } +} + +func TestCreateExternalApis(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + externalApiId := "test-external-api" + description := "test description" + displayName := "test display name" + externalURI := "https://httpbin.org/get" + paths := []string{"/get"} + endpoints := []string{"https://httpbin.org/get"} + + if _, err = CreateExternalAPI(externalApiId, displayName, description, endpoints, paths, externalURI); err != nil { + t.Errorf("failed to create external api %v", err) + } +} + +func TestGetExternalApi(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + externalApiId := "test-external-api" + + if _, err := GetExternalAPI(externalApiId); err != nil { + t.Errorf("failed to get external api %v", err) + } +} + +func TestGetInstance(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + instanceId := "test-instance" + + if _, err := GetInstance(instanceId); err != nil { + t.Errorf("failed to get instance %v", err) + } +} + +func TestLookupInstance(t *testing.T) { + err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, + clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) + if err != nil { + t.Fatalf("setup failed: %v", err) + } + + if os.Getenv("APIGEE_REGION") == "" { + t.Fatalf("APIGEE_REGION not set") + } + + if _, err := LookupInstance(); err != nil { + t.Errorf("failed to lookup instances %v", err) } } diff --git a/internal/cmd/apihub/instances/create.go b/internal/cmd/apihub/instances/create.go new file mode 100644 index 000000000..2243b8aa3 --- /dev/null +++ b/internal/cmd/apihub/instances/create.go @@ -0,0 +1,56 @@ +// 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 instances + +import ( + "fmt" + "internal/apiclient" + "internal/client/hub" + "regexp" + + "github.com/spf13/cobra" +) + +// CrtCmd to get a catalog items +var CrtCmd = &cobra.Command{ + Use: "create", + Short: "Create an API Hub Instance", + Long: "Create an API Hub Instance", + Args: func(cmd *cobra.Command, args []string) (err error) { + cmekPattern := `^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$` + if ok, err := regexp.MatchString(cmekPattern, cmekKeyName); err != nil || !ok { + return fmt.Errorf("invalid pattern for cmekKeyName: %v", err) + } + apiclient.SetRegion(region) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + cmd.SilenceUsage = true + _, err = hub.CreateInstance(id, cmekKeyName) + return + }, +} + +var cmekKeyName string + +func init() { + CrtCmd.Flags().StringVarP(&id, "id", "i", + "", "API Hub Intance Id") + CrtCmd.Flags().StringVarP(&cmekKeyName, "cmek-key-name", "k", + "", "Cmek Key Name") + + CrtCmd.MarkFlagRequired("id") + CrtCmd.MarkFlagRequired("cmek-key-name") +} diff --git a/internal/cmd/apihub/instances/get.go b/internal/cmd/apihub/instances/get.go index aebf687fa..b4e9fd918 100644 --- a/internal/cmd/apihub/instances/get.go +++ b/internal/cmd/apihub/instances/get.go @@ -42,4 +42,6 @@ var id string func init() { GetCmd.Flags().StringVarP(&id, "id", "i", "", "API Hub Intance Id") + + GetCmd.MarkFlagRequired("id") } diff --git a/internal/cmd/apihub/instances/instances.go b/internal/cmd/apihub/instances/instances.go index ee041c667..5d0a484d7 100644 --- a/internal/cmd/apihub/instances/instances.go +++ b/internal/cmd/apihub/instances/instances.go @@ -33,6 +33,7 @@ func init() { InstanceCmd.PersistentFlags().StringVarP(®ion, "region", "r", "", "API Hub region name") + InstanceCmd.AddCommand(CrtCmd) InstanceCmd.AddCommand(GetCmd) InstanceCmd.AddCommand(ListCmd) From 508f78224a71c496c042f5ea512faa19955d2034 Mon Sep 17 00:00:00 2001 From: srinandan Date: Mon, 24 Jun 2024 23:06:34 +0000 Subject: [PATCH 11/25] feat: adds support for updates --- internal/client/hub/hub.go | 587 ++++++++++++++---- internal/cmd/apihub/apis/apis.go | 1 + internal/cmd/apihub/apis/update.go | 54 ++ .../cmd/apihub/apis/versions/specs/specs.go | 1 + .../cmd/apihub/apis/versions/specs/update.go | 71 +++ internal/cmd/apihub/attributes/get.go | 40 +- internal/cmd/apihub/deployments/create.go | 8 +- internal/cmd/apihub/deployments/update.go | 61 ++ .../cmd/apihub/externalapis/externalapis.go | 1 + internal/cmd/apihub/externalapis/update.go | 60 ++ 10 files changed, 746 insertions(+), 138 deletions(-) create mode 100644 internal/cmd/apihub/apis/update.go create mode 100644 internal/cmd/apihub/apis/versions/specs/update.go create mode 100644 internal/cmd/apihub/deployments/update.go create mode 100644 internal/cmd/apihub/externalapis/update.go diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index a7a9bca95..c7638822b 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -17,6 +17,7 @@ package hub import ( "encoding/base64" "encoding/json" + "errors" "fmt" "net/url" "path" @@ -41,14 +42,33 @@ const ( ) type spec struct { - DisplayName string `json:"displayName,omitempty"` - SpecType specType `json:"specType,omitempty"` - SourceURI string `json:"sourceUri,omitempty"` - Contents content `json:"contents,omitempty"` - Documentation documentation `json:"documentation,omitempty"` - ParsingMode string `json:"parsingMode,omitempty"` + DisplayName string `json:"displayName,omitempty"` + SpecType enumAttributeValue `json:"specType,omitempty"` + SourceURI string `json:"sourceUri,omitempty"` + Contents content `json:"contents,omitempty"` + Documentation documentation `json:"documentation,omitempty"` + ParsingMode string `json:"parsingMode,omitempty"` } +type EnvironmentType string + +const ( + DEVELOPMENT EnvironmentType = "development" + STAGING EnvironmentType = "staging" + TEST EnvironmentType = "test" + PREPRODUCTION EnvironmentType = "pre-prod" + PRODUCTION EnvironmentType = "prod" +) + +type SloType string + +const ( + SLO99_99 SloType = "99.99" + SLO99_95 SloType = "99.95" + SLO99_9 SloType = "99.9" + SLO99_5 SloType = "99.5" +) + type documentation struct { ExternalUri string `json:"externalUri,omitempty"` } @@ -58,7 +78,7 @@ type content struct { MimeType string `json:"mimeType,omitempty"` } -type allowedValues struct { +type allowedValue struct { Id string `json:"id,omitempty"` DisplayName string `json:"displayName,omitempty"` Description string `json:"description,omitempty"` @@ -66,13 +86,20 @@ type allowedValues struct { } type enumValues struct { - Values []allowedValues `json:"values,omitempty"` + Values []allowedValue `json:"values,omitempty"` } -type specType struct { +type enumAttributeValue struct { EnumValues enumValues `json:"enumValues,omitempty"` } +type Action uint8 + +const ( + CREATE Action = iota + UPDATE +) + func CreateInstance(apiHubInstanceId string, cmekName string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apiHubInstances") @@ -195,6 +222,16 @@ func ListApi(filter string, pageSize int, pageToken string) (respBody []byte, er return list("apis", filter, pageSize, pageToken) } +func UpdateApi(apiID string, contents []byte) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID) + q := u.Query() + q.Set("updateMask", "display_name,description,owner,documentation,target_user,team,business_unit,maturity_level,attributes") + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String(), string(contents), "PATCH") + return respBody, err +} + func CreateApiVersion(versionID string, apiID string, contents []byte) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions") @@ -235,43 +272,7 @@ func GetApiVersionsDefinitions(apiID string, versionID string, definition string func CreateApiVersionsSpec(apiID string, versionID string, specID string, displayName string, contents []byte, mimeType string, sourceURI string, documentation string) (respBody []byte, err error) { - u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs") - q := u.Query() - if specID != "" { - q.Set("specId", specID) - } - u.RawQuery = q.Encode() - - s := spec{} - s.DisplayName = displayName - s.Documentation.ExternalUri = documentation - s.Contents.Contents = base64.StdEncoding.EncodeToString(contents) - - if strings.Contains(mimeType, "yaml") || strings.Contains(mimeType, "yml") { - s.Contents.MimeType = "application/yaml" - s.SpecType = getAllowedValuesOpenAPI() - } else if strings.Contains(mimeType, "json") { - s.Contents.MimeType = "application/json" - s.SpecType = getAllowedValuesOpenAPI() - } else if strings.Contains(mimeType, "wsdl") { - s.Contents.MimeType = "application/wsdl" - s.SpecType = getAllowedValuesWSDL() - } else if strings.Contains(mimeType, "proto") { - s.Contents.MimeType = "application/text" - s.SpecType = getAllowedValuesProto() - } else { - s.Contents.MimeType = "application/text" - } - s.SourceURI = sourceURI - - payload, err := json.Marshal(s) - if err != nil { - return nil, err - } - - respBody, err = apiclient.HttpClient(u.String(), string(payload)) - return respBody, err + return createOrUpdateApiVersionSpec(apiID, versionID, specID, displayName, contents, mimeType, sourceURI, documentation, CREATE) } func GetApiVersionSpec(apiID string, versionID string, specID string) (respBody []byte, err error) { @@ -306,6 +307,68 @@ func LintApiVersionSpec(apiID string, versionID string, specID string) (respBody return respBody, err } +func UpdateApiVersionSpec(apiID string, versionID string, specID string, displayName string, + contents []byte, mimeType string, sourceURI string, documentation string) (respBody []byte, err error) { + + return createOrUpdateApiVersionSpec(apiID, versionID, specID, displayName, contents, mimeType, sourceURI, documentation, UPDATE) +} + +func createOrUpdateApiVersionSpec(apiID string, versionID string, specID string, displayName string, + contents []byte, mimeType string, sourceURI string, documentation string, action Action) (respBody []byte, err error) { + + s := spec{} + s.DisplayName = displayName + if documentation != "" { + s.Documentation.ExternalUri = documentation + } + + if contents != nil { + s.Contents.Contents = base64.StdEncoding.EncodeToString(contents) + } + + if strings.Contains(mimeType, "yaml") || strings.Contains(mimeType, "yml") { + s.Contents.MimeType = "application/yaml" + s.SpecType = getSpecType("openapi") + } else if strings.Contains(mimeType, "json") { + s.Contents.MimeType = "application/json" + s.SpecType = getSpecType("openapi") + } else if strings.Contains(mimeType, "wsdl") { + s.Contents.MimeType = "application/wsdl" + s.SpecType = getSpecType("wsdl") + } else if strings.Contains(mimeType, "proto") { + s.Contents.MimeType = "application/text" + s.SpecType = getSpecType("proto") + } else { + s.Contents.MimeType = "application/text" + } + + if sourceURI != "" { + s.SourceURI = sourceURI + } + + payload, err := json.Marshal(s) + if err != nil { + return nil, err + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + + if action == CREATE { + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs") + q := u.Query() + q.Set("specId", specID) + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String(), string(payload)) + } else { + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "specs", specID) + q := u.Query() + q.Set("updateMask", "display_name,source_uri,documentation,contents,spec_type") + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String(), string(payload), "PATCH") + } + return respBody, err +} + func CreateDependency(dependencyID string, description string, consumerDisplayName string, consumerOperationResourceName string, consumerExternalApiResourceName string, supplierDisplayName string, supplierOperationResourceName string, supplierExternalApiResourceName string) (respBody []byte, err error) { @@ -389,24 +452,8 @@ func ListDependencies(filter string, pageSize int, pageToken string) (respBody [ } func CreateDeployment(deploymentID string, displayName string, description string, - externalURI string, resourceURI string, endpoints []string, dep DeploymentType) (respBody []byte, err error) { - - type documentation struct { - ExternalURI string `json:"externalUri,omitempty"` - } - - type deploymentType struct { - EnumValues enumValues `json:"enumValues,omitempty"` - } - - type deployment struct { - DisplayName string `json:"displayName,omitempty"` - Description string `json:"description,omitempty"` - DeploymentType deploymentType `json:"deploymentType,omitempty"` - Documentation documentation `json:"documentation,omitempty"` - ResourceURI string `json:"resourceUri,omitempty"` - Endpoints []string `json:"endpoints,omitempty"` - } + externalURI string, resourceURI string, endpoints []string, dep DeploymentType, + env EnvironmentType, slo SloType) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "deployments") @@ -414,18 +461,12 @@ func CreateDeployment(deploymentID string, displayName string, description strin q.Set("deploymentId", deploymentID) u.RawQuery = q.Encode() - d := deployment{} - d.DisplayName = displayName - d.Description = description - d.Documentation.ExternalURI = externalURI - d.ResourceURI = resourceURI - d.Endpoints = endpoints - - payload, err := json.Marshal(&d) + payload, err := getDeployment(displayName, description, externalURI, resourceURI, endpoints, dep, env, slo) if err != nil { return nil, err } - respBody, err = apiclient.HttpClient(u.String(), string(payload)) + + respBody, err = apiclient.HttpClient(u.String(), payload) return respBody, err } @@ -447,39 +488,125 @@ func ListDeployments(filter string, pageSize int, pageToken string) (respBody [] return list("deployments", filter, pageSize, pageToken) } -func CreateExternalAPI(externalApiId string, displayName string, description string, - endpoints []string, paths []string, externalUri string) (respBody []byte, err error) { +func UpdateDeployment(deploymentID string, displayName string, description string, + externalURI string, resourceURI string, endpoints []string, dep DeploymentType, + env EnvironmentType, slo SloType) (respBody []byte, err error) { + + updateMask := []string{} + + if displayName != "" { + updateMask = append(updateMask, "displayName") + } + if description != "" { + updateMask = append(updateMask, "description") + } + if externalURI != "" { + updateMask = append(updateMask, "documentation") + } + if resourceURI != "" { + updateMask = append(updateMask, "resource_uri") + } + if dep != "" { + updateMask = append(updateMask, "deployment_type") + } + if env != "" { + updateMask = append(updateMask, "environment") + } + if slo != "" { + updateMask = append(updateMask, "slo") + } + if len(endpoints) > 0 { + updateMask = append(updateMask, "endpoints") + } + if len(updateMask) == 0 { + return nil, errors.New("Update mask is empty") + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "deployments", deploymentID) + q := u.Query() + q.Set("updateMask", strings.Join(updateMask, ",")) + u.RawQuery = q.Encode() + + payload, err := getDeployment(displayName, description, externalURI, resourceURI, endpoints, dep, env, slo) + if err != nil { + return nil, err + } + + respBody, err = apiclient.HttpClient(u.String(), payload, "PATCH") + return respBody, err +} + +func getDeployment(displayName string, description string, + externalURI string, resourceURI string, endpoints []string, dep DeploymentType, + env EnvironmentType, slo SloType) (string, error) { type documentation struct { ExternalURI string `json:"externalUri,omitempty"` } - type extapi struct { - DisplayName string `json:"displayName,omitempty"` - Description string `json:"description,omitempty"` - Documentation documentation `json:"documentation,omitempty"` - Paths []string `json:"paths,omitempty"` - Endpoints []string `json:"endpoints,omitempty"` + type attributeType struct { + EnumValues enumValues `json:"enumValues,omitempty"` + } + + type deployment struct { + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + DeploymentType attributeType `json:"deploymentType,omitempty"` + Documentation documentation `json:"documentation,omitempty"` + Environment attributeType `json:"environment,omitempty"` + Slo attributeType `json:"slo,omitempty"` + ResourceURI string `json:"resourceUri,omitempty"` + Endpoints []string `json:"endpoints,omitempty"` } + d := deployment{} + if displayName != "" { + d.DisplayName = displayName + } + if description != "" { + d.Description = description + } + if externalURI != "" { + d.Documentation.ExternalURI = externalURI + } + if dep != "" { + d.DeploymentType.EnumValues = getDeploymentEnum(dep).EnumValues + } + if env != "" { + d.Environment.EnumValues = getEnvironmentEnum(env).EnumValues + } + if slo != "" { + d.Slo.EnumValues = getSloEnum(slo).EnumValues + } + if resourceURI != "" { + d.ResourceURI = resourceURI + } + if len(endpoints) > 0 { + d.Endpoints = endpoints + } + + payload, err := json.Marshal(&d) + if err != nil { + return "", err + } + return string(payload), nil +} + +func CreateExternalAPI(externalApiId string, displayName string, description string, + endpoints []string, paths []string, externalUri string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "externalApi") q := u.Query() q.Set("externalApiId", externalApiId) u.RawQuery = q.Encode() - e := extapi{} - e.DisplayName = displayName - e.Description = description - e.Documentation.ExternalURI = externalUri - e.Paths = paths - e.Endpoints = endpoints - - payload, err := json.Marshal(&e) + payload, err := getExternalApi(displayName, description, endpoints, paths, externalUri) if err != nil { return nil, err } - respBody, err = apiclient.HttpClient(u.String(), string(payload)) + respBody, err = apiclient.HttpClient(u.String(), payload) return respBody, err } @@ -501,6 +628,83 @@ func ListExternalAPIs(filter string, pageSize int, pageToken string) (respBody [ return list("externalApis", filter, pageSize, pageToken) } +func UpdateExternalAPI(externalApiID string, displayName string, description string, + endpoints []string, paths []string, externalUri string) (respBody []byte, err error) { + + updateMask := []string{} + + if displayName != "" { + updateMask = append(updateMask, "displayName") + } + if description != "" { + updateMask = append(updateMask, "description") + } + if externalUri != "" { + updateMask = append(updateMask, "documentation") + } + if len(paths) > 0 { + updateMask = append(updateMask, "paths") + } + if len(endpoints) > 0 { + updateMask = append(updateMask, "endpoints") + } + if len(updateMask) == 0 { + return nil, errors.New("Update mask is empty") + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "externalApi", externalApiID) + q := u.Query() + q.Set("updateMask", strings.Join(updateMask, ",")) + u.RawQuery = q.Encode() + + payload, err := getExternalApi(displayName, description, endpoints, paths, externalUri) + if err != nil { + return nil, err + } + + respBody, err = apiclient.HttpClient(u.String(), payload, "PATCH") + return respBody, err +} + +func getExternalApi(displayName string, description string, + endpoints []string, paths []string, externalUri string) (string, error) { + + type documentation struct { + ExternalURI string `json:"externalUri,omitempty"` + } + + type extapi struct { + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Documentation documentation `json:"documentation,omitempty"` + Paths []string `json:"paths,omitempty"` + Endpoints []string `json:"endpoints,omitempty"` + } + e := extapi{} + if displayName != "" { + e.DisplayName = displayName + } + if description != "" { + e.Description = description + } + if externalUri != "" { + e.Documentation.ExternalURI = externalUri + } + if len(paths) > 0 { + e.Paths = paths + } + if len(endpoints) > 0 { + e.Endpoints = endpoints + } + + payload, err := json.Marshal(&e) + if err != nil { + return "", err + } + return string(payload), nil +} + func CreateAttribute(attributeID string, displayName string, description string, scope string, dataType string, aValues []byte, cardinality int) (respBody []byte, err error) { @@ -529,7 +733,7 @@ func CreateAttribute(attributeID string, displayName string, description string, Description string `json:"description,omitempty"` Scope attributeScope `json:"scope,omitempty"` DataType attributeDataType `json:"dataType,omitempty"` - AllowedValues []allowedValues `json:"allowedValues,omitempty"` + AllowedValues []allowedValue `json:"allowedValues,omitempty"` Cardinality int `json:"cardinality,omitempty"` } @@ -547,7 +751,7 @@ func CreateAttribute(attributeID string, displayName string, description string, a.Cardinality = cardinality if aValues != nil { - var av []allowedValues + var av []allowedValue err = json.Unmarshal(aValues, &av) if err != nil { return nil, err @@ -599,116 +803,119 @@ func list(resource string, filter string, pageSize int, pageToken string) (respB return respBody, err } -func getAllowedValuesOpenAPI() specType { - a := allowedValues{ - Id: "openapi", - DisplayName: "OpenAPI Spec", - Description: "OpenAPI Spec", - Immutable: true, - } - return getSpecType(a) -} - -func getAllowedValuesProto() specType { - a := allowedValues{ - Id: "proto", - DisplayName: "Proto", - Description: "Proto", - Immutable: true, - } - return getSpecType(a) -} - -func getAllowedValuesWSDL() specType { - a := allowedValues{ - Id: "wsdl", - DisplayName: "WSDL", - Description: "WSDL", - Immutable: true, +func getSpecType(id string) enumAttributeValue { + switch id { + case "openapi": + return getAttributeValues(allowedValue{ + Id: "openapi", + DisplayName: "OpenAPI Spec", + Description: "OpenAPI Spec", + Immutable: true, + }) + case "proto": + return getAttributeValues(allowedValue{ + Id: "proto", + DisplayName: "Proto", + Description: "Proto", + Immutable: true, + }) + case "wsdl": + return getAttributeValues(allowedValue{ + Id: "wsdl", + DisplayName: "WSDL", + Description: "WSDL", + Immutable: true, + }) + default: + return getAttributeValues(allowedValue{ + Id: "openapi", + DisplayName: "OpenAPI Spec", + Description: "OpenAPI Spec", + Immutable: true, + }) } - return getSpecType(a) } -func getSpecType(a allowedValues) specType { - l := []allowedValues{} +func getAttributeValues(a allowedValue) enumAttributeValue { + l := []allowedValue{} l = append(l, a) e := enumValues{} e.Values = l - s := specType{} + s := enumAttributeValue{} s.EnumValues = enumValues{} s.EnumValues = e return s } -func getDeploymentEnum(d DeploymentType) specType { +func getDeploymentEnum(d DeploymentType) enumAttributeValue { switch d { case APIGEE: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "apigee", DisplayName: "Apigee", Description: "Apigee", Immutable: true, }) case APIGEE_HYBRID: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "apigee-hybrid", DisplayName: "Apigee Hybrid", Description: "Apigee Hybrid", Immutable: true, }) case APIGEE_EDGE_PRIVATE: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "apigee-edge-private", DisplayName: "Apigee Edge Private Cloud", Description: "Apigee Edge Private Cloud", Immutable: true, }) case APIGEE_EDGE_PUBLIC: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "apigee-edge-public", DisplayName: "Apigee Edge Public Cloud", Description: "Apigee Edge Public Cloud", Immutable: true, }) case MOCK_SERVER: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "mock-server", DisplayName: "Mock Server", Description: "Mock Server", Immutable: true, }) case CLOUD_API_GATEWAY: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "cloud-api-gateway", DisplayName: "Cloud API Gateway", Description: "Cloud API Gateway", Immutable: true, }) case CLOUD_ENDPOINTS: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "cloud-endpoints", DisplayName: "Cloud Endpoints", Description: "Cloud Endpoints", Immutable: true, }) case UNMANAGED: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "unmanaged", DisplayName: "Unmanaged", Description: "Unmanaged", Immutable: true, }) case OTHERS: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "others", DisplayName: "Others", Description: "Others", Immutable: true, }) default: - return getSpecType(allowedValues{ + return getAttributeValues(allowedValue{ Id: "others", DisplayName: "Others", Description: "Others", @@ -717,6 +924,82 @@ func getDeploymentEnum(d DeploymentType) specType { } } +func getEnvironmentEnum(e EnvironmentType) enumAttributeValue { + switch e { + case DEVELOPMENT: + return getAttributeValues(allowedValue{ + Id: "development", + DisplayName: "Development", + Description: "Development", + }) + case STAGING: + return getAttributeValues(allowedValue{ + Id: "staging", + DisplayName: "Staging", + Description: "Staging", + }) + case TEST: + return getAttributeValues(allowedValue{ + Id: "test", + DisplayName: "Test", + Description: "Test", + }) + case PREPRODUCTION: + return getAttributeValues(allowedValue{ + Id: "pre-prod", + DisplayName: "Pre-Production", + Description: "Pre-Production", + }) + case PRODUCTION: + return getAttributeValues(allowedValue{ + Id: "production", + DisplayName: "Production", + Description: "Production", + }) + default: + return getAttributeValues(allowedValue{ + Id: "development", + DisplayName: "Development", + Description: "Development", + }) + } +} + +func getSloEnum(s SloType) enumAttributeValue { + switch s { + case SLO99_99: + return getAttributeValues(allowedValue{ + Id: "99-99", + DisplayName: "99.99%", + Description: "99.99% SLO", + }) + case SLO99_95: + return getAttributeValues(allowedValue{ + Id: "99-95", + DisplayName: "99.95%", + Description: "99.95% SLO", + }) + case SLO99_9: + return getAttributeValues(allowedValue{ + Id: "99-9", + DisplayName: "99.9%", + Description: "99.9% SLO", + }) + case SLO99_5: + return getAttributeValues(allowedValue{ + Id: "99-5", + DisplayName: "99.5%", + Description: "99.5% SLO", + }) + default: + return getAttributeValues(allowedValue{ + Id: "99-90", + DisplayName: "99.90%", + Description: "99.90% SLO", + }) + } +} + func (d *DeploymentType) String() string { return string(*d) } @@ -735,3 +1018,41 @@ func (d *DeploymentType) Set(r string) error { func (d *DeploymentType) Type() string { return "deploymentType" } + +func (e *EnvironmentType) String() string { + return string(*e) +} + +func (e *EnvironmentType) Set(r string) error { + switch r { + case "apigee", "development", "test", "staging", "pre-prod", "prod": + *e = EnvironmentType(r) + default: + return fmt.Errorf("must be one of %s, %s, %s, %s or %s", + DEVELOPMENT, TEST, PRODUCTION, STAGING, PREPRODUCTION) + } + return nil +} + +func (e *EnvironmentType) Type() string { + return "environmentType" +} + +func (s *SloType) String() string { + return string(*s) +} + +func (s *SloType) Set(r string) error { + switch r { + case "99-99", "99-95", "99-5", "99-9": + *s = SloType(r) + default: + return fmt.Errorf("must be one of %s, %s, %s, or %s", + SLO99_99, SLO99_95, SLO99_5, SLO99_9) + } + return nil +} + +func (s *SloType) Type() string { + return "sloType" +} diff --git a/internal/cmd/apihub/apis/apis.go b/internal/cmd/apihub/apis/apis.go index 45bc0ca41..45cd6f886 100644 --- a/internal/cmd/apihub/apis/apis.go +++ b/internal/cmd/apihub/apis/apis.go @@ -39,6 +39,7 @@ func init() { ApisCmd.AddCommand(CrtCmd) ApisCmd.AddCommand(GetCmd) ApisCmd.AddCommand(DelCmd) + ApisCmd.AddCommand(UpdateCmd) ApisCmd.AddCommand(versions.ApiVersionsCmd) _ = ApisCmd.MarkFlagRequired("org") diff --git a/internal/cmd/apihub/apis/update.go b/internal/cmd/apihub/apis/update.go new file mode 100644 index 000000000..aab5b40da --- /dev/null +++ b/internal/cmd/apihub/apis/update.go @@ -0,0 +1,54 @@ +// 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 apis + +import ( + "internal/apiclient" + "internal/client/hub" + "os" + + "github.com/spf13/cobra" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API Hub API", + Long: "Create a new API Hub API", + 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 + var apiFileBytes []byte + + if apiFileBytes, err = os.ReadFile(apiFilePath); err != nil { + return err + } + _, err = hub.CreateApi(id, apiFileBytes) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&id, "id", "i", + "", "API ID") + UpdateCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API defintion") + + _ = UpdateCmd.MarkFlagRequired("id") + _ = UpdateCmd.MarkFlagRequired("file") +} diff --git a/internal/cmd/apihub/apis/versions/specs/specs.go b/internal/cmd/apihub/apis/versions/specs/specs.go index 636556903..2533565ec 100644 --- a/internal/cmd/apihub/apis/versions/specs/specs.go +++ b/internal/cmd/apihub/apis/versions/specs/specs.go @@ -38,6 +38,7 @@ func init() { SpecsCmd.AddCommand(DelCmd) SpecsCmd.AddCommand(ListCmd) SpecsCmd.AddCommand(LintCmd) + SpecsCmd.AddCommand(UpdateCmd) _ = SpecsCmd.MarkFlagRequired("org") _ = SpecsCmd.MarkFlagRequired("region") diff --git a/internal/cmd/apihub/apis/versions/specs/update.go b/internal/cmd/apihub/apis/versions/specs/update.go new file mode 100644 index 000000000..6650df86a --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/update.go @@ -0,0 +1,71 @@ +// 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 specs + +import ( + "internal/apiclient" + "internal/client/hub" + "internal/cmd/utils" + "path/filepath" + + "github.com/spf13/cobra" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + Use: "update", + Short: "Updates a Spec for an API Hub API Version", + Long: "Updates a Spec for an API Hub API Version", + 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 + var contents []byte + + if contents, err = utils.ReadFile(apiFilePath); err != nil { + return err + } + _, err = hub.UpdateApiVersionSpec(apiID, versionID, specID, displayName, + contents, filepath.Ext(apiFilePath), sourceURI, documentation) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&specID, "id", "i", + "", "Spec ID") + UpdateCmd.Flags().StringVarP(&versionID, "version", "v", + "", "API Version ID") + UpdateCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + UpdateCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Spec Display Name") + UpdateCmd.Flags().StringToStringVar(&attributes, "attrs", + nil, "API Spec attributes") + UpdateCmd.Flags().StringVarP(&sourceURI, "source-uri", "s", + "", "API Spec attributes") + UpdateCmd.Flags().StringVarP(&documentation, "documentation", "", + "", "API Spec external documentation") + UpdateCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API spec") + + _ = UpdateCmd.MarkFlagRequired("id") + _ = UpdateCmd.MarkFlagRequired("api-id") + _ = UpdateCmd.MarkFlagRequired("version") + _ = UpdateCmd.MarkFlagRequired("display-name") + _ = UpdateCmd.MarkFlagRequired("file") +} diff --git a/internal/cmd/apihub/attributes/get.go b/internal/cmd/apihub/attributes/get.go index 398cd15ff..188fff6aa 100644 --- a/internal/cmd/apihub/attributes/get.go +++ b/internal/cmd/apihub/attributes/get.go @@ -15,6 +15,7 @@ package attributes import ( + "fmt" "internal/apiclient" "internal/client/hub" @@ -27,19 +28,52 @@ var GetCmd = &cobra.Command{ Short: "Get details for an Attribute", Long: "Get details for an Attribute", Args: func(cmd *cobra.Command, args []string) (err error) { + var count int + for _, v := range []bool{slo, env, dep, specType} { + if v { + count++ + } + } + if count > 1 { + return fmt.Errorf("only one of --slo, --env, --deployments, --spec-types can be specified") + } + if attributeID != "" && count != 0 { + return fmt.Errorf("attributeID cannot be mixed with other flags") + } + if attributeID == "" && count == 0 { + return fmt.Errorf("attributeID or --slo, --env, --deployments, --spec-types must be specified") + } + apiclient.SetRegion(region) return apiclient.SetApigeeOrg(org) }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true + if slo { + attributeID = "system-slo" + } else if env { + attributeID = "system-envvironment" + } else if dep { + attributeID = "system-deployment" + } else if specType { + attributeID = "system-spec-type" + } _, err = hub.GetAttribute(attributeID) return }, } +var slo, dep, env, specType bool + func init() { GetCmd.Flags().StringVarP(&attributeID, "id", "i", - "", "Dependency ID") - - _ = GetCmd.MarkFlagRequired("id") + "", "Attribute ID") + GetCmd.Flags().BoolVarP(&slo, "slo", "", + false, "Get System SLO Attributes") + GetCmd.Flags().BoolVarP(&env, "env", "", + false, "Get System Environment Attributes") + GetCmd.Flags().BoolVarP(&dep, "deployments", "", + false, "Get System Deployment Attributes") + GetCmd.Flags().BoolVarP(&specType, "spec-types", "", + false, "Get System Deployment Attributes") } diff --git a/internal/cmd/apihub/deployments/create.go b/internal/cmd/apihub/deployments/create.go index fa6f58e61..b4754630d 100644 --- a/internal/cmd/apihub/deployments/create.go +++ b/internal/cmd/apihub/deployments/create.go @@ -32,7 +32,7 @@ var CrtCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true - _, err = hub.CreateDeployment(deploymentID, displayName, description, externalURI, resourceURI, endpoints, d) + _, err = hub.CreateDeployment(deploymentID, displayName, description, externalURI, resourceURI, endpoints, d, e, s) return }, } @@ -40,6 +40,8 @@ var CrtCmd = &cobra.Command{ var deploymentID, displayName, description, externalURI, resourceURI string var endpoints []string var d hub.DeploymentType +var e hub.EnvironmentType +var s hub.SloType func init() { CrtCmd.Flags().StringVarP(&deploymentID, "id", "i", @@ -54,7 +56,9 @@ func init() { "", "A URI to the runtime resource") CrtCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", []string{}, " The endpoints at which this deployment resource is listening for API requests") - CrtCmd.Flags().Var(&d, "type", "The type of deployment") + CrtCmd.Flags().Var(&d, "dep-type", "The type of deployment") + CrtCmd.Flags().Var(&e, "env-type", "The environment mapping to this deployment") + CrtCmd.Flags().Var(&s, "slo-type", "The SLO for this deployment") _ = CrtCmd.MarkFlagRequired("display-name") _ = CrtCmd.MarkFlagRequired("resource-uri") diff --git a/internal/cmd/apihub/deployments/update.go b/internal/cmd/apihub/deployments/update.go new file mode 100644 index 000000000..e48641238 --- /dev/null +++ b/internal/cmd/apihub/deployments/update.go @@ -0,0 +1,61 @@ +// 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 deployments + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + Use: "update", + Short: "Updates an API Deployment in API Hub", + Long: "Updates an API Deployment in API Hub", + 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 = hub.CreateDeployment(deploymentID, displayName, description, externalURI, resourceURI, endpoints, d, e, s) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&deploymentID, "id", "i", + "", "Deployment ID") + UpdateCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Deployment Display Name") + UpdateCmd.Flags().StringVarP(&description, "description", "", + "", "Deployment Description") + UpdateCmd.Flags().StringVarP(&externalURI, "external-uri", "", + "", "The uri of the externally hosted documentation") + UpdateCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", + "", "A URI to the runtime resource") + UpdateCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", + []string{}, " The endpoints at which this deployment resource is listening for API requests") + UpdateCmd.Flags().Var(&d, "dep-type", "The type of deployment") + UpdateCmd.Flags().Var(&e, "env-type", "The environment mapping to this deployment") + UpdateCmd.Flags().Var(&s, "slo-type", "The SLO for this deployment") + + _ = UpdateCmd.MarkFlagRequired("display-name") + _ = UpdateCmd.MarkFlagRequired("resource-uri") + _ = UpdateCmd.MarkFlagRequired("endpoints") + _ = UpdateCmd.MarkFlagRequired("type") +} diff --git a/internal/cmd/apihub/externalapis/externalapis.go b/internal/cmd/apihub/externalapis/externalapis.go index 16af4c6fd..8a0dbd4cd 100644 --- a/internal/cmd/apihub/externalapis/externalapis.go +++ b/internal/cmd/apihub/externalapis/externalapis.go @@ -37,6 +37,7 @@ func init() { ExternalAPICmd.AddCommand(GetCmd) ExternalAPICmd.AddCommand(DelCmd) ExternalAPICmd.AddCommand(ListCmd) + ExternalAPICmd.AddCommand(UpdateCmd) _ = ExternalAPICmd.MarkFlagRequired("org") _ = ExternalAPICmd.MarkFlagRequired("region") diff --git a/internal/cmd/apihub/externalapis/update.go b/internal/cmd/apihub/externalapis/update.go new file mode 100644 index 000000000..d4ecc57e2 --- /dev/null +++ b/internal/cmd/apihub/externalapis/update.go @@ -0,0 +1,60 @@ +// 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 externalapis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + Use: "create", + Short: "Create a new API External API", + Long: "Create a new API External API", + 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 = hub.UpdateExternalAPI(externalApiId, displayName, description, endpoints, paths, externalURI) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&externalApiID, "id", "i", + "", "External API ID") + UpdateCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Exernal API Display Name") + UpdateCmd.Flags().StringVarP(&description, "description", "", + "", "External API Description") + UpdateCmd.Flags().StringVarP(&externalURI, "external-uri", "", + "", "The uri of the externally hosted documentation") + UpdateCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", + "", "A URI to the runtime resource") + UpdateCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", + []string{}, " The endpoints at which this deployment resource is listening for API requests") + UpdateCmd.Flags().StringArrayVarP(&paths, "paths", "", + []string{}, " API base paths") + + _ = UpdateCmd.MarkFlagRequired("id") + _ = UpdateCmd.MarkFlagRequired("display-name") + _ = UpdateCmd.MarkFlagRequired("resource-uri") + _ = UpdateCmd.MarkFlagRequired("endpoints") +} From 7b7d6013e306ab6b4df54113a3d95bce8d488377 Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 25 Jun 2024 17:55:12 +0000 Subject: [PATCH 12/25] chore: gofumpt files --- internal/cmd/res/crtres.go | 3 ++- internal/cmd/res/delres.go | 3 ++- internal/cmd/res/getres.go | 3 ++- internal/cmd/res/updres.go | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/cmd/res/crtres.go b/internal/cmd/res/crtres.go index d84d05c95..615ef0650 100644 --- a/internal/cmd/res/crtres.go +++ b/internal/cmd/res/crtres.go @@ -15,9 +15,10 @@ package res import ( - "internal/apiclient" "strings" + "internal/apiclient" + "internal/client/res" "github.com/spf13/cobra" diff --git a/internal/cmd/res/delres.go b/internal/cmd/res/delres.go index f73dd686f..5f0fba5bb 100644 --- a/internal/cmd/res/delres.go +++ b/internal/cmd/res/delres.go @@ -15,9 +15,10 @@ package res import ( - "internal/apiclient" "strings" + "internal/apiclient" + "internal/client/res" "github.com/spf13/cobra" diff --git a/internal/cmd/res/getres.go b/internal/cmd/res/getres.go index 7ae8e8d6c..58fed119e 100644 --- a/internal/cmd/res/getres.go +++ b/internal/cmd/res/getres.go @@ -15,9 +15,10 @@ package res import ( - "internal/apiclient" "strings" + "internal/apiclient" + "internal/client/res" "github.com/spf13/cobra" diff --git a/internal/cmd/res/updres.go b/internal/cmd/res/updres.go index ee0c39106..24b000a15 100644 --- a/internal/cmd/res/updres.go +++ b/internal/cmd/res/updres.go @@ -15,9 +15,10 @@ package res import ( - "internal/apiclient" "strings" + "internal/apiclient" + "internal/client/res" "github.com/spf13/cobra" From f21cc2601c0e45c563ff00b9c3324f633b436dfd Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 25 Jun 2024 17:55:54 +0000 Subject: [PATCH 13/25] chore: gofumpt files --- internal/bundlegen/proxybundle/proxybundle.go | 1 - internal/cmd/apis/apis.go | 6 ++++-- internal/cmd/products/products.go | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/bundlegen/proxybundle/proxybundle.go b/internal/bundlegen/proxybundle/proxybundle.go index 3a3cc726c..1b07ccdf5 100644 --- a/internal/bundlegen/proxybundle/proxybundle.go +++ b/internal/bundlegen/proxybundle/proxybundle.go @@ -797,7 +797,6 @@ func SetSharedFlowDescription(sfFolder string, name string, description string) return err } return apiclient.WriteByteArrayToFile(path.Join(sfFolder, name+".xml"), false, byteValue) - } func downloadProxyFromRepo(client *github.Client, ctx context.Context, owner string, repo string, repopath string, sharedflow bool) (err error) { diff --git a/internal/cmd/apis/apis.go b/internal/cmd/apis/apis.go index 7fa666ad1..969fec244 100644 --- a/internal/cmd/apis/apis.go +++ b/internal/cmd/apis/apis.go @@ -32,7 +32,8 @@ var ( const zipExt = ".zip" -var examples = []string{"apigeecli apis import -f samples/apis --default-token", +var examples = []string{ + "apigeecli apis import -f samples/apis --default-token", `apigeecli apis create oas -n petstore \ --oas-base-folderpath=./samples \ --oas-name=petstore.yaml --add-cors=true \ @@ -45,7 +46,8 @@ var examples = []string{"apigeecli apis import -f samples/apis --default-token" `apigeecli apis create github --name=petstore \ --owner=apigee \ --repo=api-platform-samples \ ---proxy-path=sample-proxies/apikey --default-token`} +--proxy-path=sample-proxies/apikey --default-token`, +} func init() { Cmd.PersistentFlags().StringVarP(&org, "org", "o", diff --git a/internal/cmd/products/products.go b/internal/cmd/products/products.go index 438395b4d..3c1889e87 100644 --- a/internal/cmd/products/products.go +++ b/internal/cmd/products/products.go @@ -44,7 +44,8 @@ var ( attrs map[string]string ) -var examples = []string{`apigeecli products create --name $product_name \ +var examples = []string{ + `apigeecli products create --name $product_name \ --display-name $product_name \ --opgrp $ops_file \ --envs $env \ @@ -58,7 +59,8 @@ var examples = []string{`apigeecli products create --name $product_name \ --quota 100 --interval 1 --unit minute --default-token`, `apigeecli products import -f samples/apiproduct-legacy.json --default-token`, `apigeecli products import -f samples/apiproduct-gqlgroup.json --default-token`, - `apigeecli products import -f samples/apiproduct-op-group.json --default-token`} + `apigeecli products import -f samples/apiproduct-op-group.json --default-token`, +} func init() { Cmd.PersistentFlags().StringVarP(&org, "org", "o", From 760a237cddc0151f7bea546799899f1d202901a6 Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 25 Jun 2024 17:56:34 +0000 Subject: [PATCH 14/25] feat: adds support to export APIs --- internal/client/hub/hub.go | 202 +++++++++++++++++++++++++---- internal/client/hub/hub_test.go | 11 +- internal/cmd/apihub/apis/export.go | 54 ++++++++ 3 files changed, 238 insertions(+), 29 deletions(-) create mode 100644 internal/cmd/apihub/apis/export.go diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index c7638822b..a2e585bd7 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -20,11 +20,15 @@ import ( "errors" "fmt" "net/url" + "os" "path" + "path/filepath" "strconv" "strings" "internal/apiclient" + "internal/clilog" + "internal/cmd/utils" ) type DeploymentType string @@ -226,12 +230,90 @@ func UpdateApi(apiID string, contents []byte) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID) q := u.Query() - q.Set("updateMask", "display_name,description,owner,documentation,target_user,team,business_unit,maturity_level,attributes") + q.Set("updateMask", + "display_name,description,owner,documentation,target_user,team,business_unit,maturity_level,attributes") u.RawQuery = q.Encode() respBody, err = apiclient.HttpClient(u.String(), string(contents), "PATCH") return respBody, err } +func ExportApi(apiID string, folder string) (err error) { + apiclient.ClientPrintHttpResponse.Set(false) + defer apiclient.ClientPrintHttpResponse.Set(apiclient.GetCmdPrintHttpResponseSetting()) + + folderName := path.Join(folder, "api"+utils.DefaultFileSplitter+apiID) + + // create a folder for the api + _, err = os.Stat(folderName) + if err != nil { + if os.IsNotExist(err) { + err = os.MkdirAll(folderName, 0o755) + if err != nil { + return err + } + } else { + return err + } + } + + // write api details + apiBody, err := GetApi(apiID) + if err != nil { + return err + } + apiFileName := fmt.Sprintf("api%s%s.json", utils.DefaultFileSplitter, apiID) + err = apiclient.WriteByteArrayToFile(path.Join(folderName, apiFileName), false, apiBody) + if err != nil { + return err + } + + type apiVersions struct { + Versions []map[string]interface{} `json:"versions"` + NextPageToken string `json:"nextPageToken"` + } + + apiVersionsObj := apiVersions{} + + for { + + a := apiVersions{} + + apiVersionsBody, err := ListApiVersions(apiID, "", -1, "") + if err != nil { + return fmt.Errorf("Error listing api versions: %s", err) + } + err = json.Unmarshal(apiVersionsBody, &a) + if err != nil { + return fmt.Errorf("Error unmarshalling api versions: %s", err) + } + + apiVersionsObj.Versions = append(apiVersionsObj.Versions, a.Versions...) + if a.NextPageToken == "" { + break + } + } + + for _, version := range apiVersionsObj.Versions { + versionName := filepath.Base(version["name"].(string)) + apiVersionBody, err := GetApiVersion(versionName, apiID) + if err != nil { + return fmt.Errorf("Error getting api version: %s", err) + } + apiVersionFileName := fmt.Sprintf("api%s%s%s%s.json", + utils.DefaultFileSplitter, apiID, utils.DefaultFileSplitter, versionName) + err = apiclient.WriteByteArrayToFile(path.Join(folderName, apiVersionFileName), false, apiVersionBody) + if err != nil { + return err + } + + if err = ExportApiVersionSpecs(apiID, versionName, folderName); err != nil { + return err + } + } + + return nil +} + func CreateApiVersion(versionID string, apiID string, contents []byte) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions") @@ -270,8 +352,8 @@ func GetApiVersionsDefinitions(apiID string, versionID string, definition string } func CreateApiVersionsSpec(apiID string, versionID string, specID string, displayName string, - contents []byte, mimeType string, sourceURI string, documentation string) (respBody []byte, err error) { - + contents []byte, mimeType string, sourceURI string, documentation string, +) (respBody []byte, err error) { return createOrUpdateApiVersionSpec(apiID, versionID, specID, displayName, contents, mimeType, sourceURI, documentation, CREATE) } @@ -308,14 +390,60 @@ func LintApiVersionSpec(apiID string, versionID string, specID string) (respBody } func UpdateApiVersionSpec(apiID string, versionID string, specID string, displayName string, - contents []byte, mimeType string, sourceURI string, documentation string) (respBody []byte, err error) { - + contents []byte, mimeType string, sourceURI string, documentation string, +) (respBody []byte, err error) { return createOrUpdateApiVersionSpec(apiID, versionID, specID, displayName, contents, mimeType, sourceURI, documentation, UPDATE) } -func createOrUpdateApiVersionSpec(apiID string, versionID string, specID string, displayName string, - contents []byte, mimeType string, sourceURI string, documentation string, action Action) (respBody []byte, err error) { +func ExportApiVersionSpecs(apiID string, versionID string, folder string) (err error) { + apiclient.ClientPrintHttpResponse.Set(false) + defer apiclient.ClientPrintHttpResponse.Set(apiclient.GetCmdPrintHttpResponseSetting()) + + var specResp map[string]string + // create a folder for the specs + _, err = os.Stat(path.Join(folder, "specs")) + if err != nil { + if os.IsNotExist(err) { + os.MkdirAll(path.Join(folder, "specs"), 0o755) + } else { + return err + } + } + + specsBody, err := ListApiVersionSpecs(apiID, versionID, "", -1, "") + if err != nil { + return err + } + + specList := getSpecIDList(specsBody) + for _, spec := range specList { + specBody, err := GetApiVersionsSpecContents(apiID, versionID, spec) + if err != nil { + return fmt.Errorf("unable to complete GetApiVersionsSpecContents") + } + + if err = json.Unmarshal(specBody, &specResp); err != nil { + return fmt.Errorf("unable to unmarshal specBody") + } + + specContent, err := base64.StdEncoding.DecodeString(specResp["contents"]) + if err != nil { + return fmt.Errorf("unable to decode contents %v", err) + } + err = apiclient.WriteByteArrayToFile(path.Join(folder, + "specs", spec), false, specContent) + if err != nil { + return err + } + } + + return nil +} + +func createOrUpdateApiVersionSpec(apiID string, versionID string, specID string, displayName string, + contents []byte, mimeType string, sourceURI string, documentation string, action Action, +) (respBody []byte, err error) { s := spec{} s.DisplayName = displayName if documentation != "" { @@ -371,8 +499,8 @@ func createOrUpdateApiVersionSpec(apiID string, versionID string, specID string, func CreateDependency(dependencyID string, description string, consumerDisplayName string, consumerOperationResourceName string, consumerExternalApiResourceName string, supplierDisplayName string, - supplierOperationResourceName string, supplierExternalApiResourceName string) (respBody []byte, err error) { - + supplierOperationResourceName string, supplierExternalApiResourceName string, +) (respBody []byte, err error) { type consumer struct { DisplayName string `json:"displayName,omitempty"` OperationResourceName *string `json:"operationResourceName,omitempty"` @@ -453,8 +581,8 @@ func ListDependencies(filter string, pageSize int, pageToken string) (respBody [ func CreateDeployment(deploymentID string, displayName string, description string, externalURI string, resourceURI string, endpoints []string, dep DeploymentType, - env EnvironmentType, slo SloType) (respBody []byte, err error) { - + env EnvironmentType, slo SloType, +) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "deployments") q := u.Query() @@ -490,8 +618,8 @@ func ListDeployments(filter string, pageSize int, pageToken string) (respBody [] func UpdateDeployment(deploymentID string, displayName string, description string, externalURI string, resourceURI string, endpoints []string, dep DeploymentType, - env EnvironmentType, slo SloType) (respBody []byte, err error) { - + env EnvironmentType, slo SloType, +) (respBody []byte, err error) { updateMask := []string{} if displayName != "" { @@ -539,8 +667,8 @@ func UpdateDeployment(deploymentID string, displayName string, description strin func getDeployment(displayName string, description string, externalURI string, resourceURI string, endpoints []string, dep DeploymentType, - env EnvironmentType, slo SloType) (string, error) { - + env EnvironmentType, slo SloType, +) (string, error) { type documentation struct { ExternalURI string `json:"externalUri,omitempty"` } @@ -594,8 +722,8 @@ func getDeployment(displayName string, description string, } func CreateExternalAPI(externalApiId string, displayName string, description string, - endpoints []string, paths []string, externalUri string) (respBody []byte, err error) { - + endpoints []string, paths []string, externalUri string, +) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "externalApi") q := u.Query() @@ -629,8 +757,8 @@ func ListExternalAPIs(filter string, pageSize int, pageToken string) (respBody [ } func UpdateExternalAPI(externalApiID string, displayName string, description string, - endpoints []string, paths []string, externalUri string) (respBody []byte, err error) { - + endpoints []string, paths []string, externalUri string, +) (respBody []byte, err error) { updateMask := []string{} if displayName != "" { @@ -668,8 +796,8 @@ func UpdateExternalAPI(externalApiID string, displayName string, description str } func getExternalApi(displayName string, description string, - endpoints []string, paths []string, externalUri string) (string, error) { - + endpoints []string, paths []string, externalUri string, +) (string, error) { type documentation struct { ExternalURI string `json:"externalUri,omitempty"` } @@ -706,8 +834,8 @@ func getExternalApi(displayName string, description string, } func CreateAttribute(attributeID string, displayName string, description string, scope string, - dataType string, aValues []byte, cardinality int) (respBody []byte, err error) { - + dataType string, aValues []byte, cardinality int, +) (respBody []byte, err error) { type attributeScope string const ( API attributeScope = "API" @@ -1056,3 +1184,31 @@ func (s *SloType) Set(r string) error { func (s *SloType) Type() string { return "sloType" } + +func getSpecIDList(s []byte) (sList []string) { + + type spec struct { + Name string `json:"name,omitempty"` + DisplayName string `json:"displayName,omitempty"` + SpecType map[string]interface{} `json:"specType,omitempty"` + Details map[string]interface{} `json:"details,omitempty"` + LintResponse map[string]interface{} `json:"lintResponse,omitempty"` + } + + type speclist struct { + Specs []spec `json:"specs,omitempty"` + } + + l := speclist{} + + if err := json.Unmarshal(s, &l); err != nil { + clilog.Error.Println(err) + return nil + } + + for _, i := range l.Specs { + sList = append(sList, filepath.Base(i.Name)) + } + + return sList +} diff --git a/internal/client/hub/hub_test.go b/internal/client/hub/hub_test.go index 58842a2a6..48a2dc1f2 100644 --- a/internal/client/hub/hub_test.go +++ b/internal/client/hub/hub_test.go @@ -15,17 +15,16 @@ package hub import ( - "internal/client/clienttest" - "internal/cmd/utils" "os" "path" "testing" -) -var ( - cliPath = os.Getenv("APIGEECLI_PATH") + "internal/client/clienttest" + "internal/cmd/utils" ) +var cliPath = os.Getenv("APIGEECLI_PATH") + func TestCreateApi(t *testing.T) { err := clienttest.TestSetup(clienttest.ENV_NOT_REQD, clienttest.SITEID_NOT_REQD, clienttest.CLIPATH_REQD) @@ -475,7 +474,7 @@ func TestCreateDeployment(t *testing.T) { endpoints := []string{"https://httpbin.org/get"} if _, err = CreateDeployment(deploymentID, displayName, description, externalURI, - resourceURI, endpoints, APIGEE); err != nil { + resourceURI, endpoints, APIGEE, DEVELOPMENT, SLO99_9); err != nil { t.Errorf("failed to create deployment %v", err) } } diff --git a/internal/cmd/apihub/apis/export.go b/internal/cmd/apihub/apis/export.go new file mode 100644 index 000000000..1015b06d0 --- /dev/null +++ b/internal/cmd/apihub/apis/export.go @@ -0,0 +1,54 @@ +// 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 apis + +import ( + "os" + + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// ExportCmd to get a catalog items +var ExportCmd = &cobra.Command{ + Use: "export", + Short: "Export API, versions and specifications", + Long: "Export API, versions and specifications", + 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 + if folder == "" { + folder, _ = os.Getwd() + } + err = hub.ExportApi(apiID, folder) + return + }, +} + +var folder string + +func init() { + ExportCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + ExportCmd.Flags().StringVarP(&folder, "folder", "", + "", "Folder to export the API details") + + _ = ExportCmd.MarkFlagRequired("api-id") +} From a0ea961a6a400b24b6a2926fefe3b07704e32384 Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 25 Jun 2024 17:56:45 +0000 Subject: [PATCH 15/25] chore: gofumpt files --- internal/cmd/apihub/apis/apis.go | 1 + internal/cmd/apihub/apis/create.go | 3 ++- internal/cmd/apihub/apis/update.go | 3 ++- internal/cmd/apihub/apis/versions/create.go | 3 ++- internal/cmd/apihub/apis/versions/delete.go | 1 - internal/cmd/apihub/apis/versions/get.go | 1 - internal/cmd/apihub/apis/versions/specs/create.go | 9 ++++++--- internal/cmd/apihub/apis/versions/specs/update.go | 3 ++- internal/cmd/apihub/attributes/attributes.go | 2 +- internal/cmd/apihub/attributes/create.go | 10 ++++++---- internal/cmd/apihub/attributes/get.go | 1 + internal/cmd/apihub/dependencies/create.go | 11 +++++++---- internal/cmd/apihub/deployments/create.go | 12 +++++++----- internal/cmd/apihub/externalapis/create.go | 6 ++++-- internal/cmd/apihub/instances/create.go | 3 ++- 15 files changed, 43 insertions(+), 26 deletions(-) diff --git a/internal/cmd/apihub/apis/apis.go b/internal/cmd/apihub/apis/apis.go index 45cd6f886..e44f07fc7 100644 --- a/internal/cmd/apihub/apis/apis.go +++ b/internal/cmd/apihub/apis/apis.go @@ -40,6 +40,7 @@ func init() { ApisCmd.AddCommand(GetCmd) ApisCmd.AddCommand(DelCmd) ApisCmd.AddCommand(UpdateCmd) + ApisCmd.AddCommand(ExportCmd) ApisCmd.AddCommand(versions.ApiVersionsCmd) _ = ApisCmd.MarkFlagRequired("org") diff --git a/internal/cmd/apihub/apis/create.go b/internal/cmd/apihub/apis/create.go index 5d64e0cdc..eb4b2fdee 100644 --- a/internal/cmd/apihub/apis/create.go +++ b/internal/cmd/apihub/apis/create.go @@ -15,9 +15,10 @@ package apis import ( + "os" + "internal/apiclient" "internal/client/hub" - "os" "github.com/spf13/cobra" ) diff --git a/internal/cmd/apihub/apis/update.go b/internal/cmd/apihub/apis/update.go index aab5b40da..aec39eff4 100644 --- a/internal/cmd/apihub/apis/update.go +++ b/internal/cmd/apihub/apis/update.go @@ -15,9 +15,10 @@ package apis import ( + "os" + "internal/apiclient" "internal/client/hub" - "os" "github.com/spf13/cobra" ) diff --git a/internal/cmd/apihub/apis/versions/create.go b/internal/cmd/apihub/apis/versions/create.go index 3d1224fd4..812ed9a44 100644 --- a/internal/cmd/apihub/apis/versions/create.go +++ b/internal/cmd/apihub/apis/versions/create.go @@ -15,9 +15,10 @@ package versions import ( + "os" + "internal/apiclient" "internal/client/hub" - "os" "github.com/spf13/cobra" ) diff --git a/internal/cmd/apihub/apis/versions/delete.go b/internal/cmd/apihub/apis/versions/delete.go index e82b3eeca..b818a8650 100644 --- a/internal/cmd/apihub/apis/versions/delete.go +++ b/internal/cmd/apihub/apis/versions/delete.go @@ -45,5 +45,4 @@ func init() { _ = DelCmd.MarkFlagRequired("api-id") _ = DelCmd.MarkFlagRequired("version") - } diff --git a/internal/cmd/apihub/apis/versions/get.go b/internal/cmd/apihub/apis/versions/get.go index d0721070b..86af9bf70 100644 --- a/internal/cmd/apihub/apis/versions/get.go +++ b/internal/cmd/apihub/apis/versions/get.go @@ -53,5 +53,4 @@ func init() { _ = GetCmd.MarkFlagRequired("api-id") _ = GetCmd.MarkFlagRequired("version") - } diff --git a/internal/cmd/apihub/apis/versions/specs/create.go b/internal/cmd/apihub/apis/versions/specs/create.go index b04f69f1f..941a4c290 100644 --- a/internal/cmd/apihub/apis/versions/specs/create.go +++ b/internal/cmd/apihub/apis/versions/specs/create.go @@ -15,10 +15,11 @@ package specs import ( + "path/filepath" + "internal/apiclient" "internal/client/hub" "internal/cmd/utils" - "path/filepath" "github.com/spf13/cobra" ) @@ -45,8 +46,10 @@ var CrtCmd = &cobra.Command{ }, } -var specID, displayName, mimeType, sourceURI, documentation, apiFilePath string -var attributes map[string]string +var ( + specID, displayName, mimeType, sourceURI, documentation, apiFilePath string + attributes map[string]string +) func init() { CrtCmd.Flags().StringVarP(&specID, "id", "i", diff --git a/internal/cmd/apihub/apis/versions/specs/update.go b/internal/cmd/apihub/apis/versions/specs/update.go index 6650df86a..e32006c01 100644 --- a/internal/cmd/apihub/apis/versions/specs/update.go +++ b/internal/cmd/apihub/apis/versions/specs/update.go @@ -15,10 +15,11 @@ package specs import ( + "path/filepath" + "internal/apiclient" "internal/client/hub" "internal/cmd/utils" - "path/filepath" "github.com/spf13/cobra" ) diff --git a/internal/cmd/apihub/attributes/attributes.go b/internal/cmd/apihub/attributes/attributes.go index 4c9b0ddf1..7b815d1f0 100644 --- a/internal/cmd/apihub/attributes/attributes.go +++ b/internal/cmd/apihub/attributes/attributes.go @@ -33,7 +33,7 @@ func init() { AttributeCmd.PersistentFlags().StringVarP(®ion, "region", "r", "", "API Hub region name") - //AttributeCmd.AddCommand(CrtCmd) + // AttributeCmd.AddCommand(CrtCmd) AttributeCmd.AddCommand(GetCmd) AttributeCmd.AddCommand(DelCmd) AttributeCmd.AddCommand(ListCmd) diff --git a/internal/cmd/apihub/attributes/create.go b/internal/cmd/apihub/attributes/create.go index af5b62f4e..b5d747fc2 100644 --- a/internal/cmd/apihub/attributes/create.go +++ b/internal/cmd/apihub/attributes/create.go @@ -15,9 +15,10 @@ package attributes import ( + "os" + "internal/apiclient" "internal/client/hub" - "os" "github.com/spf13/cobra" ) @@ -43,8 +44,10 @@ var CrtCmd = &cobra.Command{ }, } -var attributeID, displayName, description, scope, dataType, aValuesPath string -var cardinality int +var ( + attributeID, displayName, description, scope, dataType, aValuesPath string + cardinality int +) func init() { CrtCmd.Flags().StringVarP(&attributeID, "id", "i", @@ -66,5 +69,4 @@ func init() { _ = CrtCmd.MarkFlagRequired("display-name") _ = CrtCmd.MarkFlagRequired("scope") _ = CrtCmd.MarkFlagRequired("data-type") - } diff --git a/internal/cmd/apihub/attributes/get.go b/internal/cmd/apihub/attributes/get.go index 188fff6aa..8364f9f5a 100644 --- a/internal/cmd/apihub/attributes/get.go +++ b/internal/cmd/apihub/attributes/get.go @@ -16,6 +16,7 @@ package attributes import ( "fmt" + "internal/apiclient" "internal/client/hub" diff --git a/internal/cmd/apihub/dependencies/create.go b/internal/cmd/apihub/dependencies/create.go index 36c163d43..644bb95ad 100644 --- a/internal/cmd/apihub/dependencies/create.go +++ b/internal/cmd/apihub/dependencies/create.go @@ -16,9 +16,10 @@ package dependencies import ( "fmt" + "regexp" + "internal/apiclient" "internal/client/hub" - "regexp" "github.com/spf13/cobra" ) @@ -71,9 +72,11 @@ var CrtCmd = &cobra.Command{ }, } -var dependencyID, description, consumerDisplayName, consumerOperationResourceName string -var consumerExternalApiResouceName, supplierDisplayName, supplierOperationResourceName string -var supplierExternalApiResourceName string +var ( + dependencyID, description, consumerDisplayName, consumerOperationResourceName string + consumerExternalApiResouceName, supplierDisplayName, supplierOperationResourceName string + supplierExternalApiResourceName string +) func init() { CrtCmd.Flags().StringVarP(&dependencyID, "id", "i", diff --git a/internal/cmd/apihub/deployments/create.go b/internal/cmd/apihub/deployments/create.go index b4754630d..22e13786b 100644 --- a/internal/cmd/apihub/deployments/create.go +++ b/internal/cmd/apihub/deployments/create.go @@ -37,11 +37,13 @@ var CrtCmd = &cobra.Command{ }, } -var deploymentID, displayName, description, externalURI, resourceURI string -var endpoints []string -var d hub.DeploymentType -var e hub.EnvironmentType -var s hub.SloType +var ( + deploymentID, displayName, description, externalURI, resourceURI string + endpoints []string + d hub.DeploymentType + e hub.EnvironmentType + s hub.SloType +) func init() { CrtCmd.Flags().StringVarP(&deploymentID, "id", "i", diff --git a/internal/cmd/apihub/externalapis/create.go b/internal/cmd/apihub/externalapis/create.go index 63e3a2c06..2505fbe2b 100644 --- a/internal/cmd/apihub/externalapis/create.go +++ b/internal/cmd/apihub/externalapis/create.go @@ -37,8 +37,10 @@ var CrtCmd = &cobra.Command{ }, } -var externalApiId, displayName, description, externalURI, resourceURI string -var endpoints, paths []string +var ( + externalApiId, displayName, description, externalURI, resourceURI string + endpoints, paths []string +) func init() { CrtCmd.Flags().StringVarP(&externalApiID, "id", "i", diff --git a/internal/cmd/apihub/instances/create.go b/internal/cmd/apihub/instances/create.go index 2243b8aa3..0453e47ad 100644 --- a/internal/cmd/apihub/instances/create.go +++ b/internal/cmd/apihub/instances/create.go @@ -16,9 +16,10 @@ package instances import ( "fmt" + "regexp" + "internal/apiclient" "internal/client/hub" - "regexp" "github.com/spf13/cobra" ) From 383225cc4a8ba8e921a069ea3bf256089f256bb6 Mon Sep 17 00:00:00 2001 From: srinandan Date: Thu, 27 Jun 2024 16:32:38 +0000 Subject: [PATCH 16/25] bug: uncomment crt attribute --- internal/cmd/apihub/attributes/attributes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/apihub/attributes/attributes.go b/internal/cmd/apihub/attributes/attributes.go index 7b815d1f0..7aec798c1 100644 --- a/internal/cmd/apihub/attributes/attributes.go +++ b/internal/cmd/apihub/attributes/attributes.go @@ -33,7 +33,7 @@ func init() { AttributeCmd.PersistentFlags().StringVarP(®ion, "region", "r", "", "API Hub region name") - // AttributeCmd.AddCommand(CrtCmd) + AttributeCmd.AddCommand(CrtCmd) AttributeCmd.AddCommand(GetCmd) AttributeCmd.AddCommand(DelCmd) AttributeCmd.AddCommand(ListCmd) From a6ee39c70974069eb11944d423716feab08b0b57 Mon Sep 17 00:00:00 2001 From: srinandan Date: Thu, 27 Jun 2024 16:51:48 +0000 Subject: [PATCH 17/25] bug: check if allowedValues is present --- internal/cmd/apihub/attributes/create.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/cmd/apihub/attributes/create.go b/internal/cmd/apihub/attributes/create.go index b5d747fc2..0eeba1112 100644 --- a/internal/cmd/apihub/attributes/create.go +++ b/internal/cmd/apihub/attributes/create.go @@ -36,9 +36,12 @@ var CrtCmd = &cobra.Command{ cmd.SilenceUsage = true var aValues []byte - if aValues, err = os.ReadFile(aValuesPath); err != nil { - return err + if aValuesPath != "" { + if aValues, err = os.ReadFile(aValuesPath); err != nil { + return err + } } + _, err = hub.CreateAttribute(attributeID, displayName, description, scope, dataType, aValues, cardinality) return }, From ab8a4249090cb713e70473b0645973c18725bd9e Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 28 Jun 2024 17:17:14 +0000 Subject: [PATCH 18/25] bug: address review comments --- internal/cmd/apihub/apis/delete.go | 4 ++-- internal/cmd/apihub/apis/get.go | 4 ++-- internal/cmd/apihub/apis/update.go | 8 ++++---- internal/cmd/apihub/apis/versions/create.go | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/cmd/apihub/apis/delete.go b/internal/cmd/apihub/apis/delete.go index a1a30f353..fbdae6acb 100644 --- a/internal/cmd/apihub/apis/delete.go +++ b/internal/cmd/apihub/apis/delete.go @@ -38,8 +38,8 @@ var DelCmd = &cobra.Command{ } func init() { - DelCmd.Flags().StringVarP(&apiID, "api-id", "", + DelCmd.Flags().StringVarP(&apiID, "id", "", "", "API ID") - _ = DelCmd.MarkFlagRequired("api-id") + _ = DelCmd.MarkFlagRequired("id") } diff --git a/internal/cmd/apihub/apis/get.go b/internal/cmd/apihub/apis/get.go index aba8405f0..87baf54d7 100644 --- a/internal/cmd/apihub/apis/get.go +++ b/internal/cmd/apihub/apis/get.go @@ -40,8 +40,8 @@ var GetCmd = &cobra.Command{ var apiID string func init() { - GetCmd.Flags().StringVarP(&apiID, "api-id", "", + GetCmd.Flags().StringVarP(&apiID, "id", "i", "", "API ID") - _ = GetCmd.MarkFlagRequired("api-id") + _ = GetCmd.MarkFlagRequired("id") } diff --git a/internal/cmd/apihub/apis/update.go b/internal/cmd/apihub/apis/update.go index aec39eff4..1f30c0887 100644 --- a/internal/cmd/apihub/apis/update.go +++ b/internal/cmd/apihub/apis/update.go @@ -25,9 +25,9 @@ import ( // UpdateCmd var UpdateCmd = &cobra.Command{ - Use: "create", - Short: "Create a new API Hub API", - Long: "Create a new API Hub API", + Use: "update", + Short: "Updates an API in API Hub", + Long: "Updates an API in API Hub", Args: func(cmd *cobra.Command, args []string) (err error) { apiclient.SetRegion(region) return apiclient.SetApigeeOrg(org) @@ -39,7 +39,7 @@ var UpdateCmd = &cobra.Command{ if apiFileBytes, err = os.ReadFile(apiFilePath); err != nil { return err } - _, err = hub.CreateApi(id, apiFileBytes) + _, err = hub.UpdateApi(id, apiFileBytes) return }, } diff --git a/internal/cmd/apihub/apis/versions/create.go b/internal/cmd/apihub/apis/versions/create.go index 812ed9a44..e6d9e7185 100644 --- a/internal/cmd/apihub/apis/versions/create.go +++ b/internal/cmd/apihub/apis/versions/create.go @@ -52,7 +52,7 @@ func init() { CrtCmd.Flags().StringVarP(&apiID, "api-id", "", "", "API ID") CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", - "", "Path to a file containing the API defintion") + "", "Path to a file containing the API version definition") _ = CrtCmd.MarkFlagRequired("api-id") _ = CrtCmd.MarkFlagRequired("file") From e283b2a1fed31cb6edf33fafb650cd02aa3f3b8c Mon Sep 17 00:00:00 2001 From: srinandan Date: Fri, 28 Jun 2024 17:44:31 +0000 Subject: [PATCH 19/25] feat: write contents of spec to a file --- .../cmd/apihub/apis/versions/specs/get.go | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/internal/cmd/apihub/apis/versions/specs/get.go b/internal/cmd/apihub/apis/versions/specs/get.go index 79cd169cb..a1337b2f7 100644 --- a/internal/cmd/apihub/apis/versions/specs/get.go +++ b/internal/cmd/apihub/apis/versions/specs/get.go @@ -15,8 +15,12 @@ package specs import ( + "encoding/base64" + "encoding/json" + "fmt" "internal/apiclient" "internal/client/hub" + "internal/clilog" "github.com/spf13/cobra" ) @@ -27,20 +31,50 @@ var GetCmd = &cobra.Command{ Short: "Get a spec for an API Version", Long: "Get a spec for an API Version", Args: func(cmd *cobra.Command, args []string) (err error) { + if contents && fileContentPath == "" { + return fmt.Errorf("The output flag must be set when contents is set to true") + } + if fileContentPath != "" && !contents { + return fmt.Errorf("The output flag must not be set when contents is set to false") + } apiclient.SetRegion(region) return apiclient.SetApigeeOrg(org) }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true if contents { - _, err = hub.GetApiVersionsSpecContents(apiID, versionID, specID) - return + apiclient.DisableCmdPrintHttpResponse() + + respBody, err := hub.GetApiVersionsSpecContents(apiID, versionID, specID) + if err != nil { + return err + } + + var specContent map[string]string + var payload []byte + + err = json.Unmarshal(respBody, &specContent) + if err != nil { + return err + } + + payload, err = base64.StdEncoding.DecodeString(specContent["contents"]) + if err != nil { + return err + } + + err = apiclient.WriteByteArrayToFile(fileContentPath, false, payload) + if err == nil { + clilog.Info.Printf("Contents of Spec %s written to %s\n", specID, fileContentPath) + } + return err } _, err = hub.GetApiVersionSpec(apiID, versionID, specID) return }, } +var fileContentPath string var contents bool func init() { @@ -52,6 +86,8 @@ func init() { "", "Spec ID") GetCmd.Flags().BoolVarP(&contents, "contents", "c", false, "Get contents") + GetCmd.Flags().StringVarP(&fileContentPath, "output", "", + "", "Path to a file to write the contents of the spec") _ = GetCmd.MarkFlagRequired("api-id") _ = GetCmd.MarkFlagRequired("version") From 383728d14dfc1e795f20804409f99b4d49ee7cde Mon Sep 17 00:00:00 2001 From: srinandan Date: Mon, 1 Jul 2024 17:57:19 +0000 Subject: [PATCH 20/25] bug: fixes incorrect descriptions --- internal/cmd/apihub/dependencies/create.go | 4 ++-- internal/cmd/apihub/dependencies/delete.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/cmd/apihub/dependencies/create.go b/internal/cmd/apihub/dependencies/create.go index 644bb95ad..69c828278 100644 --- a/internal/cmd/apihub/dependencies/create.go +++ b/internal/cmd/apihub/dependencies/create.go @@ -27,8 +27,8 @@ import ( // CrtCmd var CrtCmd = &cobra.Command{ Use: "create", - Short: "Create a new API Deployment in API Hub", - Long: "Create a new API Deployment in API Hub", + Short: "Create a new Dependency in API Hub", + Long: "Create a new Dependency in API Hub", Args: func(cmd *cobra.Command, args []string) (err error) { extApiPattern := `^projects/[^/]+/locations/[^/]+/apis/[^/]+/externalApis/[^/]+$` opPattern := `^projects/[^/]+/locations/[^/]+/apis/[^/]+/versions/[^/]+/operations/[^/]+$` diff --git a/internal/cmd/apihub/dependencies/delete.go b/internal/cmd/apihub/dependencies/delete.go index 6e1e7f106..44ab21841 100644 --- a/internal/cmd/apihub/dependencies/delete.go +++ b/internal/cmd/apihub/dependencies/delete.go @@ -24,8 +24,8 @@ import ( // DelCmd to get a catalog items var DelCmd = &cobra.Command{ Use: "delete", - Short: "Delete a deployment", - Long: "Delete a deployment", + Short: "Delete a dependency", + Long: "Delete a dependency", Args: func(cmd *cobra.Command, args []string) (err error) { apiclient.SetRegion(region) return apiclient.SetApigeeOrg(org) From 680b92bec911b66e0d6d91d470b0ca7840ee4fcf Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 2 Jul 2024 00:28:39 +0000 Subject: [PATCH 21/25] bug: fixes params for deployments --- internal/client/hub/hub.go | 35 ++++++++++++++--------- internal/cmd/apihub/deployments/create.go | 16 +++++++---- internal/cmd/apihub/deployments/update.go | 10 ++----- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index a2e585bd7..5411200e2 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -67,10 +67,10 @@ const ( type SloType string const ( - SLO99_99 SloType = "99.99" - SLO99_95 SloType = "99.95" - SLO99_9 SloType = "99.9" - SLO99_5 SloType = "99.5" + SLO99_99 SloType = "99-99" + SLO99_95 SloType = "99-95" + SLO99_9 SloType = "99-9" + SLO99_5 SloType = "99-5" ) type documentation struct { @@ -579,17 +579,19 @@ func ListDependencies(filter string, pageSize int, pageToken string) (respBody [ return list("dependencies", filter, pageSize, pageToken) } -func CreateDeployment(deploymentID string, displayName string, description string, +func CreateDeployment(deploymentID string, displayName string, description string, deploymentName string, externalURI string, resourceURI string, endpoints []string, dep DeploymentType, env EnvironmentType, slo SloType, ) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "deployments") - q := u.Query() - q.Set("deploymentId", deploymentID) - u.RawQuery = q.Encode() + if deploymentID != "" { + q := u.Query() + q.Set("deploymentId", deploymentID) + u.RawQuery = q.Encode() + } - payload, err := getDeployment(displayName, description, externalURI, resourceURI, endpoints, dep, env, slo) + payload, err := getDeployment(displayName, description, deploymentName, externalURI, resourceURI, endpoints, dep, env, slo) if err != nil { return nil, err } @@ -616,7 +618,7 @@ func ListDeployments(filter string, pageSize int, pageToken string) (respBody [] return list("deployments", filter, pageSize, pageToken) } -func UpdateDeployment(deploymentID string, displayName string, description string, +func UpdateDeployment(deploymentName string, displayName string, description string, externalURI string, resourceURI string, endpoints []string, dep DeploymentType, env EnvironmentType, slo SloType, ) (respBody []byte, err error) { @@ -651,12 +653,13 @@ func UpdateDeployment(deploymentID string, displayName string, description strin } u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "deployments", deploymentID) + u.Path = path.Join(u.Path, "deployments", deploymentName) q := u.Query() q.Set("updateMask", strings.Join(updateMask, ",")) u.RawQuery = q.Encode() - payload, err := getDeployment(displayName, description, externalURI, resourceURI, endpoints, dep, env, slo) + payload, err := getDeployment(displayName, description, deploymentName, + externalURI, resourceURI, endpoints, dep, env, slo) if err != nil { return nil, err } @@ -665,7 +668,7 @@ func UpdateDeployment(deploymentID string, displayName string, description strin return respBody, err } -func getDeployment(displayName string, description string, +func getDeployment(displayName string, description string, deploymentName string, externalURI string, resourceURI string, endpoints []string, dep DeploymentType, env EnvironmentType, slo SloType, ) (string, error) { @@ -678,6 +681,7 @@ func getDeployment(displayName string, description string, } type deployment struct { + Name string `json:"name,omitempty"` DisplayName string `json:"displayName,omitempty"` Description string `json:"description,omitempty"` DeploymentType attributeType `json:"deploymentType,omitempty"` @@ -689,6 +693,11 @@ func getDeployment(displayName string, description string, } d := deployment{} + + if deploymentName != "" { + d.Name = deploymentName + } + if displayName != "" { d.DisplayName = displayName } diff --git a/internal/cmd/apihub/deployments/create.go b/internal/cmd/apihub/deployments/create.go index 22e13786b..98bfac487 100644 --- a/internal/cmd/apihub/deployments/create.go +++ b/internal/cmd/apihub/deployments/create.go @@ -32,22 +32,25 @@ var CrtCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true - _, err = hub.CreateDeployment(deploymentID, displayName, description, externalURI, resourceURI, endpoints, d, e, s) + _, err = hub.CreateDeployment(deploymentID, displayName, description, + deploymentName, externalURI, resourceURI, endpoints, d, e, s) return }, } var ( - deploymentID, displayName, description, externalURI, resourceURI string - endpoints []string - d hub.DeploymentType - e hub.EnvironmentType - s hub.SloType + deploymentID, displayName, deploymentName, description, externalURI, resourceURI string + endpoints []string + d hub.DeploymentType + e hub.EnvironmentType + s hub.SloType ) func init() { CrtCmd.Flags().StringVarP(&deploymentID, "id", "i", "", "Deployment ID") + CrtCmd.Flags().StringVarP(&deploymentName, "name", "n", + "", "Deployment Name") CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", "", "Deployment Display Name") CrtCmd.Flags().StringVarP(&description, "description", "", @@ -62,6 +65,7 @@ func init() { CrtCmd.Flags().Var(&e, "env-type", "The environment mapping to this deployment") CrtCmd.Flags().Var(&s, "slo-type", "The SLO for this deployment") + _ = CrtCmd.MarkFlagRequired("name") _ = CrtCmd.MarkFlagRequired("display-name") _ = CrtCmd.MarkFlagRequired("resource-uri") _ = CrtCmd.MarkFlagRequired("endpoints") diff --git a/internal/cmd/apihub/deployments/update.go b/internal/cmd/apihub/deployments/update.go index e48641238..2a51c36ac 100644 --- a/internal/cmd/apihub/deployments/update.go +++ b/internal/cmd/apihub/deployments/update.go @@ -32,14 +32,14 @@ var UpdateCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) (err error) { cmd.SilenceUsage = true - _, err = hub.CreateDeployment(deploymentID, displayName, description, externalURI, resourceURI, endpoints, d, e, s) + _, err = hub.UpdateDeployment(deploymentName, displayName, description, externalURI, resourceURI, endpoints, d, e, s) return }, } func init() { - UpdateCmd.Flags().StringVarP(&deploymentID, "id", "i", - "", "Deployment ID") + UpdateCmd.Flags().StringVarP(&deploymentName, "name", "n", + "", "Deployment Name") UpdateCmd.Flags().StringVarP(&displayName, "display-name", "d", "", "Deployment Display Name") UpdateCmd.Flags().StringVarP(&description, "description", "", @@ -54,8 +54,4 @@ func init() { UpdateCmd.Flags().Var(&e, "env-type", "The environment mapping to this deployment") UpdateCmd.Flags().Var(&s, "slo-type", "The SLO for this deployment") - _ = UpdateCmd.MarkFlagRequired("display-name") - _ = UpdateCmd.MarkFlagRequired("resource-uri") - _ = UpdateCmd.MarkFlagRequired("endpoints") - _ = UpdateCmd.MarkFlagRequired("type") } From 4fa155c179fcd99ce0e11ca8083210303dcc0345 Mon Sep 17 00:00:00 2001 From: Kurt Kanaskie Date: Tue, 2 Jul 2024 11:30:08 -0400 Subject: [PATCH 22/25] Fixed UpdateCmd for deployments and externalAPIs --- internal/client/hub/hub.go | 12 ++++++------ internal/cmd/apihub/deployments/depoyments.go | 1 + internal/cmd/apihub/deployments/update.go | 2 +- internal/cmd/apihub/externalapis/create.go | 10 ++++------ internal/cmd/apihub/externalapis/get.go | 2 -- internal/cmd/apihub/externalapis/update.go | 10 ++++------ 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index 5411200e2..cdfa2ee37 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -730,13 +730,13 @@ func getDeployment(displayName string, description string, deploymentName string return string(payload), nil } -func CreateExternalAPI(externalApiId string, displayName string, description string, +func CreateExternalAPI(externalApiID string, displayName string, description string, endpoints []string, paths []string, externalUri string, ) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "externalApi") + u.Path = path.Join(u.Path, "externalApis") q := u.Query() - q.Set("externalApiId", externalApiId) + q.Set("externalApiId", externalApiID) u.RawQuery = q.Encode() payload, err := getExternalApi(displayName, description, endpoints, paths, externalUri) @@ -747,9 +747,9 @@ func CreateExternalAPI(externalApiId string, displayName string, description str return respBody, err } -func GetExternalAPI(externalApiId string) (respBody []byte, err error) { +func GetExternalAPI(externalApiID string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "externalApis", externalApiId) + u.Path = path.Join(u.Path, "externalApis", externalApiID) respBody, err = apiclient.HttpClient(u.String()) return respBody, err } @@ -790,7 +790,7 @@ func UpdateExternalAPI(externalApiID string, displayName string, description str } u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) - u.Path = path.Join(u.Path, "externalApi", externalApiID) + u.Path = path.Join(u.Path, "externalApis", externalApiID) q := u.Query() q.Set("updateMask", strings.Join(updateMask, ",")) u.RawQuery = q.Encode() diff --git a/internal/cmd/apihub/deployments/depoyments.go b/internal/cmd/apihub/deployments/depoyments.go index 41756da71..8439aa7b1 100644 --- a/internal/cmd/apihub/deployments/depoyments.go +++ b/internal/cmd/apihub/deployments/depoyments.go @@ -37,6 +37,7 @@ func init() { DeploymentCmd.AddCommand(GetCmd) DeploymentCmd.AddCommand(DelCmd) DeploymentCmd.AddCommand(ListCmd) + DeploymentCmd.AddCommand(UpdateCmd) _ = DeploymentCmd.MarkFlagRequired("org") _ = DeploymentCmd.MarkFlagRequired("region") diff --git a/internal/cmd/apihub/deployments/update.go b/internal/cmd/apihub/deployments/update.go index 2a51c36ac..d8059cc73 100644 --- a/internal/cmd/apihub/deployments/update.go +++ b/internal/cmd/apihub/deployments/update.go @@ -38,7 +38,7 @@ var UpdateCmd = &cobra.Command{ } func init() { - UpdateCmd.Flags().StringVarP(&deploymentName, "name", "n", + UpdateCmd.Flags().StringVarP(&deploymentName, "id", "i", "", "Deployment Name") UpdateCmd.Flags().StringVarP(&displayName, "display-name", "d", "", "Deployment Display Name") diff --git a/internal/cmd/apihub/externalapis/create.go b/internal/cmd/apihub/externalapis/create.go index 2505fbe2b..3decd00c8 100644 --- a/internal/cmd/apihub/externalapis/create.go +++ b/internal/cmd/apihub/externalapis/create.go @@ -24,21 +24,21 @@ import ( // CrtCmd var CrtCmd = &cobra.Command{ Use: "create", - Short: "Create a new API External API", - Long: "Create a new API External API", + Short: "Create a new External API", + Long: "Create a new External API", 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 = hub.CreateExternalAPI(externalApiId, displayName, description, endpoints, paths, externalURI) + _, err = hub.CreateExternalAPI(externalApiID, displayName, description, endpoints, paths, externalURI) return }, } var ( - externalApiId, displayName, description, externalURI, resourceURI string + externalApiID, displayName, description, externalURI, resourceURI string endpoints, paths []string ) @@ -51,8 +51,6 @@ func init() { "", "External API Description") CrtCmd.Flags().StringVarP(&externalURI, "external-uri", "", "", "The uri of the externally hosted documentation") - CrtCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", - "", "A URI to the runtime resource") CrtCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", []string{}, " The endpoints at which this deployment resource is listening for API requests") CrtCmd.Flags().StringArrayVarP(&paths, "paths", "", diff --git a/internal/cmd/apihub/externalapis/get.go b/internal/cmd/apihub/externalapis/get.go index 71c8a7ef9..093e344d9 100644 --- a/internal/cmd/apihub/externalapis/get.go +++ b/internal/cmd/apihub/externalapis/get.go @@ -37,8 +37,6 @@ var GetCmd = &cobra.Command{ }, } -var externalApiID string - func init() { GetCmd.Flags().StringVarP(&externalApiID, "id", "i", "", "External API ID") diff --git a/internal/cmd/apihub/externalapis/update.go b/internal/cmd/apihub/externalapis/update.go index d4ecc57e2..fd13dab8f 100644 --- a/internal/cmd/apihub/externalapis/update.go +++ b/internal/cmd/apihub/externalapis/update.go @@ -23,16 +23,16 @@ import ( // UpdateCmd var UpdateCmd = &cobra.Command{ - Use: "create", - Short: "Create a new API External API", - Long: "Create a new API External API", + Use: "update", + Short: "Update an External API", + Long: "Update an External API", 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 = hub.UpdateExternalAPI(externalApiId, displayName, description, endpoints, paths, externalURI) + _, err = hub.UpdateExternalAPI(externalApiID, displayName, description, endpoints, paths, externalURI) return }, } @@ -46,8 +46,6 @@ func init() { "", "External API Description") UpdateCmd.Flags().StringVarP(&externalURI, "external-uri", "", "", "The uri of the externally hosted documentation") - UpdateCmd.Flags().StringVarP(&resourceURI, "resource-uri", "", - "", "A URI to the runtime resource") UpdateCmd.Flags().StringArrayVarP(&endpoints, "endpoints", "", []string{}, " The endpoints at which this deployment resource is listening for API requests") UpdateCmd.Flags().StringArrayVarP(&paths, "paths", "", From 969fa4227c69413e3a06222e08502af37c1c1a33 Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 2 Jul 2024 15:47:26 +0000 Subject: [PATCH 23/25] feat: adds capability to update api version --- internal/client/hub/hub.go | 62 +++++++++++++++++++ internal/cmd/apihub/apis/versions/update.go | 57 +++++++++++++++++ internal/cmd/apihub/apis/versions/versions.go | 1 + 3 files changed, 120 insertions(+) create mode 100644 internal/cmd/apihub/apis/versions/update.go diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index cdfa2ee37..bf1317088 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -344,6 +344,68 @@ func ListApiVersions(apiID string, filter string, pageSize int, pageToken string return list(path.Join("apis", apiID, "versions"), filter, pageSize, pageToken) } +func UpdateApiVersion(versionID string, apiID string, contents []byte) (respBody []byte, err error) { + + var updateMasks []string + + type apiversion struct { + DisplayName *string `json:"displayName,omitempty"` + Description *string `json:"description,omitempty"` + Documentation *map[string]interface{} `json:"documentation,omitempty"` + Deployments *map[string]interface{} `json:"deployments,omitempty"` + Lifecycle *map[string]interface{} `json:"lifecycle,omitempty"` + Compliance *map[string]interface{} `json:"compliance,omitempty"` + Accreditation *map[string]interface{} `json:"acreditation,omitempty"` + Attributes *map[string]interface{} `json:"attributes,omitempty"` + } + + a := apiversion{} + err = json.Unmarshal(contents, &a) + if err != nil { + return nil, err + } + + if a.DisplayName != nil { + updateMasks = append(updateMasks, "displayName") + } + if a.Description != nil { + updateMasks = append(updateMasks, "description") + } + if a.Documentation != nil { + updateMasks = append(updateMasks, "documentation") + } + if a.Deployments != nil { + updateMasks = append(updateMasks, "deployments") + } + if a.Lifecycle != nil { + updateMasks = append(updateMasks, "lifecycle") + } + if a.Compliance != nil { + updateMasks = append(updateMasks, "compliance") + } + if a.Accreditation != nil { + updateMasks = append(updateMasks, "acreditation") + } + if a.Attributes != nil { + updateMasks = append(updateMasks, "attributes") + } + + if len(updateMasks) == 0 { + return nil, fmt.Errorf("at least one update parameter is required") + } + + u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) + u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID) + + q := u.Query() + q.Set("updateMask", strings.Join(updateMasks, ",")) + u.RawQuery = q.Encode() + + respBody, err = apiclient.HttpClient(u.String(), string(contents), "PATCH") + + return respBody, err +} + func GetApiVersionsDefinitions(apiID string, versionID string, definition string) (respBody []byte, err error) { u, _ := url.Parse(apiclient.GetApigeeRegistryURL()) u.Path = path.Join(u.Path, "apis", apiID, "versions", versionID, "definitions", definition) diff --git a/internal/cmd/apihub/apis/versions/update.go b/internal/cmd/apihub/apis/versions/update.go new file mode 100644 index 000000000..f97bb69e2 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/update.go @@ -0,0 +1,57 @@ +// 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 versions + +import ( + "os" + + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + Use: "update", + Short: "Update an API Hub API Version", + Long: "Update an API Hub API Version", + 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 + var apiFileBytes []byte + + if apiFileBytes, err = os.ReadFile(apiFilePath); err != nil { + return err + } + _, err = hub.UpdateApiVersion(id, apiID, apiFileBytes) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&id, "id", "i", + "", "API Version ID") + UpdateCmd.Flags().StringVarP(&apiID, "api-id", "", + "", "API ID") + UpdateCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API version definition") + + _ = UpdateCmd.MarkFlagRequired("api-id") + _ = UpdateCmd.MarkFlagRequired("file") +} diff --git a/internal/cmd/apihub/apis/versions/versions.go b/internal/cmd/apihub/apis/versions/versions.go index cbb0ae742..736448851 100644 --- a/internal/cmd/apihub/apis/versions/versions.go +++ b/internal/cmd/apihub/apis/versions/versions.go @@ -39,6 +39,7 @@ func init() { ApiVersionsCmd.AddCommand(ListCmd) ApiVersionsCmd.AddCommand(GetCmd) ApiVersionsCmd.AddCommand(DelCmd) + ApiVersionsCmd.AddCommand(UpdateCmd) ApiVersionsCmd.AddCommand(specs.SpecsCmd) _ = ApiVersionsCmd.MarkFlagRequired("org") From ffeb6c761e680530675ec8b8a747dbef04cb1d87 Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 2 Jul 2024 16:13:56 +0000 Subject: [PATCH 24/25] bug: fixes flag naming to be consistent --- internal/cmd/apihub/apis/versions/delete.go | 2 +- internal/cmd/apihub/apis/versions/get.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/apihub/apis/versions/delete.go b/internal/cmd/apihub/apis/versions/delete.go index b818a8650..e78da8f57 100644 --- a/internal/cmd/apihub/apis/versions/delete.go +++ b/internal/cmd/apihub/apis/versions/delete.go @@ -38,7 +38,7 @@ var DelCmd = &cobra.Command{ } func init() { - DelCmd.Flags().StringVarP(&versionID, "version", "v", + DelCmd.Flags().StringVarP(&versionID, "id", "i", "", "API Version ID") DelCmd.Flags().StringVarP(&apiID, "api-id", "", "", "API ID") diff --git a/internal/cmd/apihub/apis/versions/get.go b/internal/cmd/apihub/apis/versions/get.go index 86af9bf70..ceed5dda9 100644 --- a/internal/cmd/apihub/apis/versions/get.go +++ b/internal/cmd/apihub/apis/versions/get.go @@ -44,7 +44,7 @@ var GetCmd = &cobra.Command{ var versionID, definition string func init() { - GetCmd.Flags().StringVarP(&versionID, "version", "v", + GetCmd.Flags().StringVarP(&versionID, "id", "i", "", "API Version ID") GetCmd.Flags().StringVarP(&apiID, "api-id", "", "", "API ID") From 42006bd15116b0846904708cbca3ccdc656886dc Mon Sep 17 00:00:00 2001 From: srinandan Date: Tue, 2 Jul 2024 16:16:52 +0000 Subject: [PATCH 25/25] bug: fixes struct for api version --- internal/client/hub/hub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/client/hub/hub.go b/internal/client/hub/hub.go index bf1317088..a1a7083ed 100644 --- a/internal/client/hub/hub.go +++ b/internal/client/hub/hub.go @@ -352,7 +352,7 @@ func UpdateApiVersion(versionID string, apiID string, contents []byte) (respBody DisplayName *string `json:"displayName,omitempty"` Description *string `json:"description,omitempty"` Documentation *map[string]interface{} `json:"documentation,omitempty"` - Deployments *map[string]interface{} `json:"deployments,omitempty"` + Deployments *[]string `json:"deployments,omitempty"` Lifecycle *map[string]interface{} `json:"lifecycle,omitempty"` Compliance *map[string]interface{} `json:"compliance,omitempty"` Accreditation *map[string]interface{} `json:"acreditation,omitempty"`