diff --git a/internal/apiclient/options.go b/internal/apiclient/options.go index 990e05ed8..e427b1839 100644 --- a/internal/apiclient/options.go +++ b/internal/apiclient/options.go @@ -30,7 +30,7 @@ const ( ) // 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/" @@ -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 new file mode 100644 index 000000000..a1a7083ed --- /dev/null +++ b/internal/client/hub/hub.go @@ -0,0 +1,1285 @@ +// 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 ( + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net/url" + "os" + "path" + "path/filepath" + "strconv" + "strings" + + "internal/apiclient" + "internal/clilog" + "internal/cmd/utils" +) + +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 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"` +} + +type content struct { + Contents string `json:"contents,omitempty"` + MimeType string `json:"mimeType,omitempty"` +} + +type allowedValue struct { + Id string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Immutable bool `json:"immutable"` +} + +type enumValues struct { + Values []allowedValue `json:"values,omitempty"` +} + +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") + + 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 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") + + 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 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) { + 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 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) { + 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(), 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) { + 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 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") + q := u.Query() + if versionID != "" { + q.Set("versionId", versionID) + } + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String(), 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) { + 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 *[]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"` + 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) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func CreateApiVersionsSpec(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, CREATE) +} + +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 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") + return respBody, err +} + +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()) + return respBody, err +} + +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) +} + +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 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 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 != "" { + 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) { + 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) { + return list("dependencies", filter, pageSize, pageToken) +} + +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") + if deploymentID != "" { + q := u.Query() + q.Set("deploymentId", deploymentID) + u.RawQuery = q.Encode() + } + + payload, err := getDeployment(displayName, description, deploymentName, externalURI, resourceURI, endpoints, dep, env, slo) + if err != nil { + return nil, err + } + + respBody, err = apiclient.HttpClient(u.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) { + return list("deployments", filter, pageSize, pageToken) +} + +func UpdateDeployment(deploymentName 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", deploymentName) + q := u.Query() + q.Set("updateMask", strings.Join(updateMask, ",")) + u.RawQuery = q.Encode() + + payload, err := getDeployment(displayName, description, deploymentName, + 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, deploymentName string, + externalURI string, resourceURI string, endpoints []string, dep DeploymentType, + env EnvironmentType, slo SloType, +) (string, error) { + type documentation struct { + ExternalURI string `json:"externalUri,omitempty"` + } + + type attributeType struct { + EnumValues enumValues `json:"enumValues,omitempty"` + } + + type deployment struct { + Name string `json:"name,omitempty"` + 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 deploymentName != "" { + d.Name = deploymentName + } + + 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, "externalApis") + q := u.Query() + q.Set("externalApiId", externalApiID) + 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) + 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) { + 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, "externalApis", 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) { + 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 attributeScope `json:"scope,omitempty"` + DataType attributeDataType `json:"dataType,omitempty"` + AllowedValues []allowedValue `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 = attributeScope(scope) + a.DataType = attributeDataType(dataType) + a.Cardinality = cardinality + + if aValues != nil { + var av []allowedValue + 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, resource) + 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 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, + }) + } +} + +func getAttributeValues(a allowedValue) enumAttributeValue { + l := []allowedValue{} + l = append(l, a) + e := enumValues{} + e.Values = l + + s := enumAttributeValue{} + s.EnumValues = enumValues{} + s.EnumValues = e + + return s +} + +func getDeploymentEnum(d DeploymentType) enumAttributeValue { + switch d { + case APIGEE: + return getAttributeValues(allowedValue{ + Id: "apigee", + DisplayName: "Apigee", + Description: "Apigee", + Immutable: true, + }) + case APIGEE_HYBRID: + return getAttributeValues(allowedValue{ + Id: "apigee-hybrid", + DisplayName: "Apigee Hybrid", + Description: "Apigee Hybrid", + Immutable: true, + }) + case APIGEE_EDGE_PRIVATE: + return getAttributeValues(allowedValue{ + Id: "apigee-edge-private", + DisplayName: "Apigee Edge Private Cloud", + Description: "Apigee Edge Private Cloud", + Immutable: true, + }) + case APIGEE_EDGE_PUBLIC: + return getAttributeValues(allowedValue{ + Id: "apigee-edge-public", + DisplayName: "Apigee Edge Public Cloud", + Description: "Apigee Edge Public Cloud", + Immutable: true, + }) + case MOCK_SERVER: + return getAttributeValues(allowedValue{ + Id: "mock-server", + DisplayName: "Mock Server", + Description: "Mock Server", + Immutable: true, + }) + case CLOUD_API_GATEWAY: + return getAttributeValues(allowedValue{ + Id: "cloud-api-gateway", + DisplayName: "Cloud API Gateway", + Description: "Cloud API Gateway", + Immutable: true, + }) + case CLOUD_ENDPOINTS: + return getAttributeValues(allowedValue{ + Id: "cloud-endpoints", + DisplayName: "Cloud Endpoints", + Description: "Cloud Endpoints", + Immutable: true, + }) + case UNMANAGED: + return getAttributeValues(allowedValue{ + Id: "unmanaged", + DisplayName: "Unmanaged", + Description: "Unmanaged", + Immutable: true, + }) + case OTHERS: + return getAttributeValues(allowedValue{ + Id: "others", + DisplayName: "Others", + Description: "Others", + Immutable: true, + }) + default: + return getAttributeValues(allowedValue{ + Id: "others", + DisplayName: "Others", + Description: "Others", + Immutable: true, + }) + } +} + +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) +} + +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" +} + +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" +} + +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 new file mode 100644 index 000000000..48a2dc1f2 --- /dev/null +++ b/internal/client/hub/hub_test.go @@ -0,0 +1,603 @@ +// 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 ( + "os" + "path" + "testing" + + "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) + 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 dependency %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 dependencies %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 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, DEVELOPMENT, SLO99_9); 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/apihub.go b/internal/cmd/apihub/apihub.go new file mode 100644 index 000000000..919750b74 --- /dev/null +++ b/internal/cmd/apihub/apihub.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 apihub + +import ( + "internal/cmd/apihub/apis" + "internal/cmd/apihub/attributes" + "internal/cmd/apihub/dependencies" + "internal/cmd/apihub/deployments" + "internal/cmd/apihub/externalapis" + "internal/cmd/apihub/instances" + "internal/cmd/apihub/projectattachments" + "internal/cmd/apihub/projectregistrations" + + "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) + Cmd.AddCommand(attributes.AttributeCmd) + Cmd.AddCommand(projectattachments.ProjectAttachmentCmd) + Cmd.AddCommand(projectregistrations.ProjectRegistrationCmd) +} diff --git a/internal/cmd/apihub/apis/apis.go b/internal/cmd/apihub/apis/apis.go new file mode 100644 index 000000000..e44f07fc7 --- /dev/null +++ b/internal/cmd/apihub/apis/apis.go @@ -0,0 +1,48 @@ +// 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(UpdateCmd) + ApisCmd.AddCommand(ExportCmd) + 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..eb4b2fdee --- /dev/null +++ b/internal/cmd/apihub/apis/create.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 apis + +import ( + "os" + + "internal/apiclient" + "internal/client/hub" + + "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, "id", "i", + "", "API ID") + CrtCmd.Flags().StringVarP(&apiFilePath, "file", "f", + "", "Path to a file containing the API defintion") + + _ = CrtCmd.MarkFlagRequired("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..fbdae6acb --- /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, "id", "", + "", "API ID") + + _ = DelCmd.MarkFlagRequired("id") +} 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") +} diff --git a/internal/cmd/apihub/apis/get.go b/internal/cmd/apihub/apis/get.go new file mode 100644 index 000000000..87baf54d7 --- /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, "id", "i", + "", "API ID") + + _ = GetCmd.MarkFlagRequired("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/update.go b/internal/cmd/apihub/apis/update.go new file mode 100644 index 000000000..1f30c0887 --- /dev/null +++ b/internal/cmd/apihub/apis/update.go @@ -0,0 +1,55 @@ +// 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" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + 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) + }, + 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.UpdateApi(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/create.go b/internal/cmd/apihub/apis/versions/create.go new file mode 100644 index 000000000..e6d9e7185 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/create.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 versions + +import ( + "os" + + "internal/apiclient" + "internal/client/hub" + + "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 version definition") + + _ = 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..e78da8f57 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/delete.go @@ -0,0 +1,48 @@ +// 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, "id", "i", + "", "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..ceed5dda9 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/get.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" +) + +// 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 + if definition != "" { + _, err = hub.GetApiVersionsDefinitions(versionID, apiID, definition) + return + } + _, err = hub.GetApiVersion(versionID, apiID) + return + }, +} + +var versionID, definition string + +func init() { + GetCmd.Flags().StringVarP(&versionID, "id", "i", + "", "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/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..941a4c290 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/create.go @@ -0,0 +1,77 @@ +// 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 ( + "path/filepath" + + "internal/apiclient" + "internal/client/hub" + "internal/cmd/utils" + + "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 + 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", "", + "", "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("id") + _ = 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..78a2afeeb --- /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.DeleteApiVersionSpec(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..a1337b2f7 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/get.go @@ -0,0 +1,95 @@ +// 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 ( + "encoding/base64" + "encoding/json" + "fmt" + "internal/apiclient" + "internal/client/hub" + "internal/clilog" + + "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) { + 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 { + 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() { + 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.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") + _ = GetCmd.MarkFlagRequired("spec-id") +} 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/list.go b/internal/cmd/apihub/apis/versions/specs/list.go new file mode 100644 index 000000000..7087caa79 --- /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.ListApiVersionSpecs(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..2533565ec --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/specs.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 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.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..e32006c01 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/specs/update.go @@ -0,0 +1,72 @@ +// 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 ( + "path/filepath" + + "internal/apiclient" + "internal/client/hub" + "internal/cmd/utils" + + "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/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 new file mode 100644 index 000000000..736448851 --- /dev/null +++ b/internal/cmd/apihub/apis/versions/versions.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 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(UpdateCmd) + ApiVersionsCmd.AddCommand(specs.SpecsCmd) + + _ = ApiVersionsCmd.MarkFlagRequired("org") + _ = ApiVersionsCmd.MarkFlagRequired("region") +} diff --git a/internal/cmd/apihub/attributes/attributes.go b/internal/cmd/apihub/attributes/attributes.go new file mode 100644 index 000000000..7aec798c1 --- /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..0eeba1112 --- /dev/null +++ b/internal/cmd/apihub/attributes/create.go @@ -0,0 +1,75 @@ +// 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 ( + "os" + + "internal/apiclient" + "internal/client/hub" + + "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 aValuesPath != "" { + 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 + 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..8364f9f5a --- /dev/null +++ b/internal/cmd/apihub/attributes/get.go @@ -0,0 +1,80 @@ +// 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 ( + "fmt" + + "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) { + 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", + "", "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/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 new file mode 100644 index 000000000..69c828278 --- /dev/null +++ b/internal/cmd/apihub/dependencies/create.go @@ -0,0 +1,100 @@ +// 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" + "regexp" + + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// CrtCmd +var CrtCmd = &cobra.Command{ + Use: "create", + 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/[^/]+$` + + 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") + } + + 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 + consumerExternalApiResouceName, supplierDisplayName, supplierOperationResourceName string + 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") + + _ = CrtCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/dependencies/delete.go b/internal/cmd/apihub/dependencies/delete.go new file mode 100644 index 000000000..44ab21841 --- /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 dependency", + Long: "Delete 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.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..98bfac487 --- /dev/null +++ b/internal/cmd/apihub/deployments/create.go @@ -0,0 +1,73 @@ +// 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, + deploymentName, externalURI, resourceURI, endpoints, d, e, s) + return + }, +} + +var ( + 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", "", + "", "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, "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("name") + _ = 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..8439aa7b1 --- /dev/null +++ b/internal/cmd/apihub/deployments/depoyments.go @@ -0,0 +1,44 @@ +// 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.AddCommand(UpdateCmd) + + _ = 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/deployments/update.go b/internal/cmd/apihub/deployments/update.go new file mode 100644 index 000000000..d8059cc73 --- /dev/null +++ b/internal/cmd/apihub/deployments/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 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.UpdateDeployment(deploymentName, displayName, description, externalURI, resourceURI, endpoints, d, e, s) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&deploymentName, "id", "i", + "", "Deployment Name") + 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") + +} diff --git a/internal/cmd/apihub/externalapis/create.go b/internal/cmd/apihub/externalapis/create.go new file mode 100644 index 000000000..3decd00c8 --- /dev/null +++ b/internal/cmd/apihub/externalapis/create.go @@ -0,0 +1,63 @@ +// 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 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) + return + }, +} + +var ( + externalApiID, displayName, description, externalURI, resourceURI string + endpoints, paths []string +) + +func init() { + CrtCmd.Flags().StringVarP(&externalApiID, "id", "i", + "", "External API ID") + CrtCmd.Flags().StringVarP(&displayName, "display-name", "d", + "", "Exernal API Display Name") + CrtCmd.Flags().StringVarP(&description, "description", "", + "", "External API Description") + CrtCmd.Flags().StringVarP(&externalURI, "external-uri", "", + "", "The uri of the externally hosted documentation") + 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("id") + _ = 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..8a0dbd4cd --- /dev/null +++ b/internal/cmd/apihub/externalapis/externalapis.go @@ -0,0 +1,44 @@ +// 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.AddCommand(UpdateCmd) + + _ = 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..093e344d9 --- /dev/null +++ b/internal/cmd/apihub/externalapis/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 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 + }, +} + +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/externalapis/update.go b/internal/cmd/apihub/externalapis/update.go new file mode 100644 index 000000000..fd13dab8f --- /dev/null +++ b/internal/cmd/apihub/externalapis/update.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 externalapis + +import ( + "internal/apiclient" + "internal/client/hub" + + "github.com/spf13/cobra" +) + +// UpdateCmd +var UpdateCmd = &cobra.Command{ + 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) + 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().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") +} diff --git a/internal/cmd/apihub/instances/create.go b/internal/cmd/apihub/instances/create.go new file mode 100644 index 000000000..0453e47ad --- /dev/null +++ b/internal/cmd/apihub/instances/create.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 instances + +import ( + "fmt" + "regexp" + + "internal/apiclient" + "internal/client/hub" + + "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 new file mode 100644 index 000000000..b4e9fd918 --- /dev/null +++ b/internal/cmd/apihub/instances/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 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") + + GetCmd.MarkFlagRequired("id") +} diff --git a/internal/cmd/apihub/instances/instances.go b/internal/cmd/apihub/instances/instances.go new file mode 100644 index 000000000..5d0a484d7 --- /dev/null +++ b/internal/cmd/apihub/instances/instances.go @@ -0,0 +1,42 @@ +// 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(CrtCmd) + 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/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..cc2a30257 --- /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") +} 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") +} 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" + } +}