mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
remove publisher
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
# API Publisher
|
||||
|
||||
The public api publisher for Micro services
|
||||
|
||||
## Overview
|
||||
|
||||
The API publisher assumes a few things:
|
||||
|
||||
- Your service name is the directory of the service
|
||||
- You have a `README.md` file we take as description
|
||||
- You have a `make api` command to generate a `api-{service}.json` for the OpenAPI spec
|
||||
- You optionally have a `publicapi.json` file to define extra info such a category, icon, etc
|
||||
- You optionally have a `examples.json` file to separately define usage examples
|
||||
- You optionaly have a `pricing.json` file to separately define pricing information
|
||||
|
||||
All these are combined to produce a Public API.
|
||||
|
||||
## Readme
|
||||
|
||||
The readmes are taken verbatim. Everything before the newline is used as a short excerpt. Examples are appended to your API
|
||||
tab if they exist so no need to add random examples, curls, etc to the readme. Focus on describing the service in brevity.
|
||||
|
||||
## Comments
|
||||
|
||||
Some rules on how to write protos so they nicely appear in the output of this script:
|
||||
|
||||
- The request types (eg. `LoginRequest`) comments will be taken and used as a description for the endpoint (eg. `Login`) itself. This might change.
|
||||
- The proto message field comments will be taken and displayed to craft them with care
|
||||
|
||||
To provide example values use the following format:
|
||||
|
||||
```shell
|
||||
// rss feed name
|
||||
// eg. a16z
|
||||
string name = 1;
|
||||
```
|
||||
|
||||
The part after the `eg. ` until the newline will be used as example value.
|
||||
@@ -1,201 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
type PublicAPI struct {
|
||||
Name string `json:"name"`
|
||||
Category string `json:"category,omitempty"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
OpenAPIJson string `json:"open_api_json"`
|
||||
Pricing map[string]int64 `json:"pricing,omitempty"`
|
||||
ExamplesJson string `json:"examples_json,omitempty"`
|
||||
PostmanJson string `json:"postman_json,omitempty"`
|
||||
DisplayName string `json:"display_name,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
prodAPIDomain = "api.m3o.com"
|
||||
)
|
||||
|
||||
func publishAPI(apiSpec *PublicAPI, domain string) error {
|
||||
client := &http.Client{}
|
||||
|
||||
//Encode the data
|
||||
postBody, _ := json.Marshal(map[string]interface{}{
|
||||
"api": apiSpec,
|
||||
})
|
||||
|
||||
rbody := bytes.NewBuffer(postBody)
|
||||
|
||||
//Leverage Go's HTTP Post function to make request
|
||||
req, err := http.NewRequest("POST", fmt.Sprintf("https://%s/publicapi/Publish", domain), rbody)
|
||||
|
||||
// Add auth headers here if needed
|
||||
req.Header.Add("Authorization", `Bearer `+os.Getenv("MICRO_ADMIN_TOKEN"))
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
return errors.New(string(b))
|
||||
}
|
||||
|
||||
io.Copy(ioutil.Discard, resp.Body)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
workDir, _ := os.Getwd()
|
||||
domainFlag := flag.String("domain", prodAPIDomain, "domain to publish to e.g. api.m3o.com")
|
||||
serviceFlag := flag.String("service", "", "individual service to publish e.g. helloworld")
|
||||
flag.Parse()
|
||||
|
||||
files, err := ioutil.ReadDir(flag.Arg(0))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, f := range files {
|
||||
if strings.Contains(f.Name(), "clients") || strings.Contains(f.Name(), "examples") {
|
||||
continue
|
||||
}
|
||||
if len(*serviceFlag) > 0 && f.Name() != *serviceFlag {
|
||||
continue
|
||||
}
|
||||
if f.IsDir() && !strings.HasPrefix(f.Name(), ".") {
|
||||
serviceDir := filepath.Join(workDir, f.Name())
|
||||
serviceFiles, err := ioutil.ReadDir(serviceDir)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to read service dir", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
skip := false
|
||||
for _, serviceFile := range serviceFiles {
|
||||
if serviceFile.Name() == "skip" {
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println("Processing folder", serviceDir)
|
||||
makeProto := exec.Command("make", "api")
|
||||
makeProto.Dir = serviceDir
|
||||
fmt.Println(serviceDir)
|
||||
outp, err := makeProto.CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to make api", string(outp))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
serviceName := f.Name()
|
||||
|
||||
// generate the Postman collection
|
||||
postman := exec.Command("openapi2postmanv2", "-s", fmt.Sprintf("api-%s.json", serviceName), "-o", "postman.json")
|
||||
postman.Dir = serviceDir
|
||||
outp, err = postman.CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to generate postman collection %s %s\n", string(outp), err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dat, err := ioutil.ReadFile(filepath.Join(serviceDir, "README.md"))
|
||||
if err != nil {
|
||||
fmt.Println("Failed to read readme", string(outp))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
apiJSON := filepath.Join(serviceDir, "api-"+serviceName+".json")
|
||||
js, err := ioutil.ReadFile(apiJSON)
|
||||
if err != nil {
|
||||
apiJSON := filepath.Join(serviceDir, "api-protobuf.json")
|
||||
js, err = ioutil.ReadFile(apiJSON)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to read json spec", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
spec := &openapi3.Swagger{}
|
||||
|
||||
// we have to read an openapi spec otherwise we can't publish
|
||||
if err := json.Unmarshal(js, &spec); err != nil {
|
||||
fmt.Println("Failed to unmarshal", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// define the default public api values
|
||||
publicApi := new(PublicAPI)
|
||||
|
||||
// if we find a public api definition we load it
|
||||
if b, err := ioutil.ReadFile(filepath.Join(serviceDir, "publicapi.json")); err == nil {
|
||||
// unpack the info if we read the file
|
||||
json.Unmarshal(b, &publicApi)
|
||||
}
|
||||
|
||||
// If we didn't get the default info from a file, populate it
|
||||
if publicApi.Name == "" {
|
||||
publicApi.Name = serviceName
|
||||
}
|
||||
if publicApi.Description == "" {
|
||||
publicApi.Description = string(dat)
|
||||
}
|
||||
if publicApi.OpenAPIJson == "" {
|
||||
publicApi.OpenAPIJson = string(js)
|
||||
}
|
||||
|
||||
// load the examples if they exist
|
||||
if examples, err := ioutil.ReadFile(filepath.Join(serviceDir, "examples.json")); err == nil {
|
||||
if len(examples) > 0 {
|
||||
publicApi.ExamplesJson = string(examples)
|
||||
}
|
||||
}
|
||||
|
||||
// load the separate pricing if it exists
|
||||
if pricingRaw, err := ioutil.ReadFile(filepath.Join(serviceDir, "pricing.json")); err == nil {
|
||||
pricing := map[string]int64{}
|
||||
// unmarshal the pricing info
|
||||
if len(pricingRaw) > 0 {
|
||||
json.Unmarshal(pricingRaw, &pricing)
|
||||
publicApi.Pricing = pricing
|
||||
}
|
||||
}
|
||||
|
||||
// load the postman json
|
||||
if postman, err := ioutil.ReadFile(filepath.Join(serviceDir, "postman.json")); err == nil {
|
||||
if len(postman) > 0 {
|
||||
publicApi.PostmanJson = string(postman)
|
||||
}
|
||||
}
|
||||
|
||||
// publish the api
|
||||
if err := publishAPI(publicApi, *domainFlag); err != nil {
|
||||
fmt.Println("Failed to save data to publicapi service", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user