diff --git a/app/README.md b/app/README.md index ed158cc..5fac41c 100644 --- a/app/README.md +++ b/app/README.md @@ -2,5 +2,6 @@ Global app deployment # App Service -Deploy apps and services quickly and easily from a source url or container image. -Get a globally unique URL ([name].m3o.app) and share with others. Reserve your app name now. +Deploy apps and services quickly and easily from a source url. + +Run 10 apps for free. Pay to reserve more instances beyond it. diff --git a/app/config.md b/app/config.md new file mode 100644 index 0000000..0812c4f --- /dev/null +++ b/app/config.md @@ -0,0 +1,6 @@ +# Config + +The app service currently defaults to Google Cloud Run as a provider. In future it will support more. +This requires setting up a config key `app` with service accounts and related info. See handler/google.go +to understand what is required. Additionally we require a dummy service account with no permissions +for the deployed apps. diff --git a/app/examples.json b/app/examples.json index 0b7a487..2309715 100644 --- a/app/examples.json +++ b/app/examples.json @@ -17,16 +17,127 @@ } } ], - "vote": [ + "list": [ { - "title": "Vote for the API", + "title": "List the apps", + "run_check": false, + "request": {}, + "response": { + "services": [{ + "id": "helloworld", + "name": "helloworld", + "repo": "github.com/asim/helloworld", + "branch": "master", + "region": "europe-west1", + "port": 8080, + "status": "Running", + "url": "https://helloworld.m3o.app", + "created": "2021-12-15T09:48:50.864124234Z", + "updated": "2021-12-15T09:50:13.722008Z", + "env_vars": {}, + "custom_domains": [] + }] + } + } + ], + "run": [ + { + "title": "Run an app", "run_check": false, "request": { - "message": "Launch it!" + "name": "helloworld", + "repo": "github.com/asim/helloworld", + "branch": "master", + "port": 8080, + "region": "eu-west-1" }, "response": { - "message": "Thanks for the vote!" + "service": { + "id": "helloworld", + "name": "helloworld", + "repo": "github.com/asim/helloworld", + "branch": "master", + "region": "europe-west1", + "port": 8080, + "status": "Deploying", + "url": "https://helloworld.m3o.app", + "created": "2021-12-15T09:48:50.864124234Z", + "updated": "", + "env_vars": {}, + "custom_domains": [] + } } } + ], + "regions": [ + { + "title": "List regions", + "run_check": false, + "request": {}, + "response": { + "regions": [ + "europe-west1", + "us-east1", + "us-west1" + ] + } + } + ], + "status": [ + { + "title": "Get the status of an app", + "run_check": false, + "request": { + "name": "helloworld" + }, + "response": { + "service": { + "id": "helloworld", + "name": "helloworld", + "repo": "github.com/asim/helloworld", + "branch": "master", + "region": "europe-west1", + "port": 8080, + "status": "Deploying", + "url": "https://helloworld.m3o.app", + "created": "2021-12-15T09:48:50.864124234Z", + "updated": "", + "env_vars": {}, + "custom_domains": [] + } + } + } + ], + "resolve": [ + { + "title": "Resolve app by id", + "run_check": false, + "request": { + "id": "helloworld" + }, + "response": { + "url": "https://helloworld-jn5gitv2pa-ew.a.run.app" + } + } + ], + "update": [ + { + "title": "Update an app", + "run_check": false, + "request": { + "name": "helloworld" + }, + "response": {} + } + ], + "delete": [ + { + "title": "Delete an app", + "run_check": false, + "request": { + "name": "helloworld" + }, + "response": {} + } ] } diff --git a/app/handler/app.go b/app/handler/app.go index 9a3c590..14ffe12 100644 --- a/app/handler/app.go +++ b/app/handler/app.go @@ -20,7 +20,9 @@ type App struct{} var ( mtx sync.Mutex - ReservationKey = "reservedApp/" + OwnerKey = "app/owner/" + ServiceKey = "app/service/" + ReservationKey = "app/reservation/" NameFormat = regexp.MustCompilePOSIX("[a-z0-9]+") ) @@ -83,14 +85,29 @@ func (a *App) Reserve(ctx context.Context, req *pb.ReserveRequest, rsp *pb.Reser return errors.BadRequest("app.reserve", "name already reserved") } - // check the owner matches - if rsrv.Owner != id { + // check the owner matches or if the reservation expired + if rsrv.Owner != id && rsrv.Expires.After(time.Now()) { return errors.BadRequest("app.reserve", "name already reserved") } - // update the reservation + // update the owner + rsrv.Owner = id + + // update the reservation expiry rsrv.Expires = time.Now().AddDate(1, 0, 0) } else { + // check if its already running + key := ServiceKey + req.Name + recs, err := store.Read(key, store.ReadLimit(1)) + if err != nil && err != store.ErrNotFound { + return errors.InternalServerError("app.reserve", "failed to reserve name") + } + + // existing service is running by that name + if len(recs) > 0 { + return errors.BadRequest("app.reserve", "service already exists") + } + // not reserved rsrv = &Reservation{ Name: req.Name, diff --git a/app/handler/google.go b/app/handler/google.go new file mode 100644 index 0000000..8429d87 --- /dev/null +++ b/app/handler/google.go @@ -0,0 +1,732 @@ +package handler + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "math/rand" + "os/exec" + "strings" + "time" + + "github.com/micro/micro/v3/service/auth" + "github.com/micro/micro/v3/service/config" + "github.com/micro/micro/v3/service/context/metadata" + "github.com/micro/micro/v3/service/errors" + log "github.com/micro/micro/v3/service/logger" + "github.com/micro/micro/v3/service/runtime/source/git" + "github.com/micro/micro/v3/service/store" + pb "github.com/micro/services/app/proto" + "github.com/micro/services/pkg/tenant" + "github.com/teris-io/shortid" +) + +type GoogleApp struct { + // the associated google project + project string + // eg. https://us-central1-m3o-apis.cloudfunctions.net/ + address string + // max number of apps per user + limit int + // custom domain for apps + domain string + // the service account for the app + identity string + // Embed the app handler + *App +} + +var ( + // hardcoded list of supported regions + GoogleRegions = []string{"europe-west1", "us-east1", "us-west1"} + + // hardcoded list of valid repos + GitRepos = []string{"github.com", "gitlab.org", "bitbucket.org"} +) + +var ( + alphanum = "abcdefghijklmnopqrstuvwxyz0123456789" +) + +func random(i int) string { + bytes := make([]byte, i) + for { + rand.Read(bytes) + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + return string(bytes) + } + return fmt.Sprintf("%d", time.Now().Unix()) +} + +func New() *GoogleApp { + v, err := config.Get("app.service_account_json") + if err != nil { + log.Fatalf("app.service_account_json: %v", err) + } + keyfile := v.Bytes() + if len(keyfile) == 0 { + log.Fatalf("empty keyfile") + } + + v, err = config.Get("app.address") + if err != nil { + log.Fatalf("app.address: %v", err) + } + address := v.String("") + if len(address) == 0 { + log.Fatalf("empty address") + } + + v, err = config.Get("app.domain") + if err != nil { + log.Fatalf("app.domain: %v", err) + } + domain := v.String("") + + v, err = config.Get("app.project") + if err != nil { + log.Fatalf("app.project: %v", err) + } + project := v.String("") + if len(project) == 0 { + log.Fatalf("empty project") + } + v, err = config.Get("app.limit") + if err != nil { + log.Fatalf("app.limit: %v", err) + } + limit := v.Int(0) + if limit == 0 { + log.Infof("App limit is %d", limit) + } + + v, err = config.Get("app.service_account") + if err != nil { + log.Fatalf("app.service_account: %v", err) + } + accName := v.String("") + + v, err = config.Get("app.service_identity") + if err != nil { + log.Fatalf("app.service_identity: %v", err) + } + identity := v.String("") + + m := map[string]interface{}{} + err = json.Unmarshal(keyfile, &m) + if err != nil { + log.Fatalf("invalid json: %v", err) + } + + // only root + err = ioutil.WriteFile("account.json", keyfile, 0700) + if err != nil { + log.Fatalf("app.service_account: %v", err) + } + + // DO THIS STEP + // https://cloud.google.com/functions/docs/reference/iam/roles#additional-configuration + + // https://cloud.google.com/sdk/docs/authorizing#authorizing_with_a_service_account + outp, err := exec.Command("gcloud", "auth", "activate-service-account", accName, "--key-file", "account.json").CombinedOutput() + if err != nil { + log.Fatal(string(outp), err.Error()) + } + + outp, err = exec.Command("gcloud", "auth", "list").CombinedOutput() + if err != nil { + log.Fatal(string(outp), err.Error()) + } + log.Info(string(outp)) + + return &GoogleApp{ + domain: domain, + project: project, + address: address, + limit: limit, + identity: identity, + App: new(App), + } +} + +func (e *GoogleApp) Regions(ctx context.Context, req *pb.RegionsRequest, rsp *pb.RegionsResponse) error { + rsp.Regions = GoogleRegions + return nil +} + +func (e *GoogleApp) Run(ctx context.Context, req *pb.RunRequest, rsp *pb.RunResponse) error { + log.Info("Received App.Run request") + + if len(req.Name) == 0 { + return errors.BadRequest("app.run", "missing name") + } + + if len(req.Repo) == 0 { + return errors.BadRequest("app.run", "missing repo") + } + + if req.Port <= 0 { + req.Port = 8080 + } + + // validations + if !NameFormat.MatchString(req.Name) { + return errors.BadRequest("app.run", "invalidate name format") + } + + id, ok := tenant.FromContext(ctx) + if !ok { + id = "micro" + } + + var reservedApp bool + + // check if the name is reserved by a different owner + reservedKey := ReservationKey + req.Name + + recs, err := store.Read(reservedKey, store.ReadLimit(1)) + if err == nil && len(recs) > 0 { + res := new(Reservation) + recs[0].Decode(res) + if res.Owner != id && res.Expires.After(time.Now()) { + return errors.BadRequest("app.run", "name %s is reserved", req.Name) + } + reservedApp = true + } + + var validRepo bool + + // only support github and gitlab + for _, repo := range GitRepos { + rp := repo + + if strings.HasPrefix(req.Repo, "https://") { + rp = "https://" + repo + } + + if strings.HasPrefix(req.Repo, rp) { + validRepo = true + break + } + } + + if !validRepo { + return errors.BadRequest("app.run", "invalid git repo") + } + + var supportedRegion bool + + if len(req.Region) == 0 { + // set to default region + req.Region = GoogleRegions[0] + supportedRegion = true + } + + // check if its in the supported regions + for _, reg := range GoogleRegions { + if req.Region == reg { + supportedRegion = true + break + } + } + + // unsupported region requested + if !supportedRegion { + return errors.BadRequest("app.run", "Unsupported region") + } + + // checkout the source code + if len(req.Branch) == 0 { + req.Branch = "master" + } + + // look for the existing service + key := OwnerKey + id + "/" + req.Name + + // check the owner isn't already running it + recs, err = store.Read(key, store.ReadLimit(1)) + if err == nil && len(recs) > 0 { + return errors.BadRequest("app.run", "%s already running", req.Name) + } + + // check the global namespace + // look for the existing service + key = ServiceKey + req.Name + + // set the id + appId := req.Name + + // check the owner isn't already running it + recs, err = store.Read(key, store.ReadLimit(1)) + + // if there's an existing service then generate a unique id + if err == nil && len(recs) > 0 { + // generate an id for the service + sid, err := shortid.Generate() + if err != nil || len(sid) == 0 { + sid = random(8) + } + + sid = strings.ToLower(sid) + sid = strings.Replace(sid, "-", "", -1) + sid = strings.Replace(sid, "_", "", -1) + appId = req.Name + "-" + sid + } + + // check for app limit + if e.limit > 0 && !reservedApp { + ownerKey := OwnerKey + id + "/" + recs, err := store.Read(ownerKey, store.ReadPrefix()) + if err == nil && len(recs) >= e.limit { + return errors.BadRequest("app.run", "deployment limit reached") + } + } + + // checkout the code + gitter := git.NewGitter(map[string]string{}) + if err := gitter.Checkout(req.Repo, req.Branch); err != nil { + log.Errorf("Failed to download %s@%s\n", req.Repo, req.Branch) + return errors.InternalServerError("app.run", "Failed to download source") + } + + // TODO validate name and use custom domain name + + // process the env vars to the required format + var envVars []string + + for k, v := range req.EnvVars { + envVars = append(envVars, k+"="+v) + } + + service := &pb.Service{ + Name: req.Name, + Id: appId, + Repo: req.Repo, + Branch: req.Branch, + Region: req.Region, + Port: req.Port, + Status: "Deploying", + EnvVars: req.EnvVars, + Created: time.Now().Format(time.RFC3339Nano), + } + + keys := []string{ + // service key + ServiceKey + service.Id, + // owner key + OwnerKey + id + "/" + req.Name, + } + + // write the keys for the service + for _, key := range keys { + rec := store.NewRecord(key, service) + + if err := store.Write(rec); err != nil { + log.Error(err) + return err + } + } + + go func(service *pb.Service) { + // generate a unique service account for the app + // https://jsoverson.medium.com/how-to-deploy-node-js-functions-to-google-cloud-8bba05e9c10a + cmd := exec.Command("gcloud", "--project", e.project, "--format", "json", "run", "deploy", service.Id, "--region", req.Region, + "--service-account", e.identity, + "--cpu", "1", "--memory", "256Mi", "--port", fmt.Sprintf("%d", req.Port), + "--allow-unauthenticated", "--max-instances", "1", "--source", ".", + ) + + // if env vars exist then set them + if len(envVars) > 0 { + cmd.Args = append(cmd.Args, "--set-env-vars", strings.Join(envVars, ",")) + } + + // set the command dir + cmd.Dir = gitter.RepoDir() + + // execute the command + outp, err := cmd.CombinedOutput() + + // by this point the context may have been cancelled + acc, _ := auth.AccountFromContext(ctx) + md, _ := metadata.FromContext(ctx) + + ctx = metadata.NewContext(context.Background(), md) + ctx = auth.ContextWithAccount(ctx, acc) + + if err == nil { + // populate the app status + err = e.Status(ctx, &pb.StatusRequest{Name: req.Name}, &pb.StatusResponse{}) + if err != nil { + log.Error(err) + } + return + } + + errString := string(outp) + + log.Error(fmt.Errorf(errString)) + + // set the error status + service.Status = "DeploymentError" + + if strings.Contains(errString, "Failed to start and then listen on the port defined by the PORT environment variable") { + service.Status += ": Failed to start and listen on port " + fmt.Sprintf("%d", req.Port) + } else if strings.Contains(errString, "Build failed") { + service.Status += ": Build failed" + } + + keys := []string{ + // service key + ServiceKey + service.Id, + // owner key + OwnerKey + id + "/" + req.Name, + } + + // write the keys for the service + for _, key := range keys { + rec := store.NewRecord(key, service) + + if err := store.Write(rec); err != nil { + log.Error(err) + return + } + } + }(service) + + // set the service in the response + rsp.Service = service + + return nil +} + +func (e *GoogleApp) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error { + log.Info("Received App.Update request") + + if len(req.Name) == 0 { + return errors.BadRequest("app.update", "missing name") + } + + // validations + if !NameFormat.MatchString(req.Name) { + return errors.BadRequest("app.run", "invalidate name format") + } + + id, ok := tenant.FromContext(ctx) + if !ok { + id = "micro" + } + + key := OwnerKey + id + "/" + req.Name + + // look for the existing service + recs, err := store.Read(key, store.ReadLimit(1)) + if err != nil && err == store.ErrNotFound { + return errors.BadRequest("app.update", "%s does not exist", req.Name) + } + + if len(recs) == 0 { + return errors.BadRequest("app.update", "%s does not exist", req.Name) + } + + srv := new(pb.Service) + + if err := recs[0].Decode(srv); err != nil { + return err + } + + // checkout the code + gitter := git.NewGitter(map[string]string{}) + if err := gitter.Checkout(srv.Repo, srv.Branch); err != nil { + log.Errorf("Failed to download %s@%s\n", srv.Repo, srv.Branch) + return errors.InternalServerError("app.run", "Failed to download source") + } + + // TODO validate name and use custom domain name + + // process the env vars to the required format + var envVars []string + + for k, v := range srv.EnvVars { + envVars = append(envVars, k+"="+v) + } + + go func(service *pb.Service) { + // https://jsoverson.medium.com/how-to-deploy-node-js-functions-to-google-cloud-8bba05e9c10a + cmd := exec.Command("gcloud", "--project", e.project, "--format", "json", "run", "deploy", service.Id, "--region", service.Region, + "--service-account", e.identity, + "--cpu", "1", "--memory", "256Mi", "--port", fmt.Sprintf("%d", service.Port), + "--allow-unauthenticated", "--max-instances", "1", "--source", ".", + ) + + // if env vars exist then set them + if len(envVars) > 0 { + cmd.Args = append(cmd.Args, "--set-env-vars", strings.Join(envVars, ",")) + } + + // set the command dir + cmd.Dir = gitter.RepoDir() + + // execute the command + outp, err := cmd.CombinedOutput() + + // by this point the context may have been cancelled + acc, _ := auth.AccountFromContext(ctx) + md, _ := metadata.FromContext(ctx) + + ctx = metadata.NewContext(context.Background(), md) + ctx = auth.ContextWithAccount(ctx, acc) + + if err == nil { + // populate the app status + err = e.Status(ctx, &pb.StatusRequest{Name: service.Name}, &pb.StatusResponse{}) + if err != nil { + log.Error(err) + } + return + } + + errString := string(outp) + + log.Error(fmt.Errorf(errString)) + + // set the error status + service.Status = "DeploymentError" + + if strings.Contains(errString, "Failed to start and then listen on the port defined by the PORT environment variable") { + service.Status += ": Failed to start and listen on port " + fmt.Sprintf("%d", service.Port) + } else if strings.Contains(errString, "Build failed") { + service.Status += ": Build failed" + } + + keys := []string{ + // service key + ServiceKey + service.Id, + // owner key + OwnerKey + id + "/" + req.Name, + } + + // write the keys for the service + for _, key := range keys { + rec := store.NewRecord(key, service) + + if err := store.Write(rec); err != nil { + log.Error(err) + return + } + } + }(srv) + + return err +} +func (e *GoogleApp) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { + log.Info("Received App.Delete request") + + if len(req.Name) == 0 { + return errors.BadRequest("app.delete", "missing name") + } + + id, ok := tenant.FromContext(ctx) + if !ok { + id = "micro" + } + + // read the app for the owner + key := OwnerKey + id + "/" + req.Name + recs, err := store.Read(key) + if err != nil { + return err + } + + // not running + if len(recs) == 0 { + return nil + } + + // decode the service + srv := new(pb.Service) + + if err := recs[0].Decode(srv); err != nil { + return err + } + + // execute the delete async + go func(srv *pb.Service) { + cmd := exec.Command("gcloud", "--quiet", "--project", e.project, "run", "services", "delete", "--region", srv.Region, srv.Id) + outp, err := cmd.CombinedOutput() + if err != nil && !strings.Contains(string(outp), "could not be found") { + log.Error(fmt.Errorf(string(outp))) + return + } + + // delete from the db + keys := []string{ + // service key + ServiceKey + srv.Id, + // owner key + OwnerKey + id + "/" + req.Name, + } + + // delete the keys for the service + for _, key := range keys { + if err := store.Delete(key); err != nil { + log.Error(err) + return + } + } + + }(srv) + + return nil +} + +func (e *GoogleApp) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error { + log.Info("Received App.List request") + + id, ok := tenant.FromContext(ctx) + if !ok { + id = "micro" + } + + key := OwnerKey + id + "/" + + recs, err := store.Read(key, store.ReadPrefix()) + if err != nil { + return err + } + + rsp.Services = []*pb.Service{} + + for _, rec := range recs { + srv := new(pb.Service) + if err := rec.Decode(srv); err != nil { + continue + } + + // set the custom domain + if len(e.domain) > 0 { + srv.Url = fmt.Sprintf("https://%s.%s", srv.Id, e.domain) + } + + rsp.Services = append(rsp.Services, srv) + } + + return nil +} + +func (e *GoogleApp) Status(ctx context.Context, req *pb.StatusRequest, rsp *pb.StatusResponse) error { + id, ok := tenant.FromContext(ctx) + if !ok { + id = "micro" + } + + key := OwnerKey + id + "/" + req.Name + + recs, err := store.Read(key) + if err != nil { + return err + } + + if len(recs) == 0 { + return errors.NotFound("app.status", "app not found") + } + + srv := new(pb.Service) + if err := recs[0].Decode(srv); err != nil { + return err + } + + // get the current app status + cmd := exec.Command("gcloud", "--project", e.project, "--format", "json", "run", "services", "describe", "--region", srv.Region, srv.Id) + outp, err := cmd.CombinedOutput() + if err != nil && srv.Status == "Deploying" { + log.Error(fmt.Errorf(string(outp))) + rsp.Service = srv + return nil + } else if err != nil { + log.Error(fmt.Errorf(string(outp))) + return errors.BadRequest("app.status", "service does not exist") + } + + var output map[string]interface{} + if err = json.Unmarshal(outp, &output); err != nil { + return err + } + + currentStatus := srv.Status + currentUrl := srv.Url + updatedAt := srv.Updated + + // get the service status + status := output["status"].(map[string]interface{}) + deployed := status["conditions"].([]interface{})[0].(map[string]interface{}) + srv.Updated = deployed["lastTransitionTime"].(string) + + switch deployed["status"].(string) { + case "True": + srv.Status = "Running" + srv.Url = status["url"].(string) + default: + srv.Status = deployed["status"].(string) + } + + // set response + rsp.Service = srv + + // no change in status and we have a pre-existing url + if srv.Status == currentStatus && srv.Url == currentUrl && srv.Updated == updatedAt { + return nil + } + + // update built in status + // delete from the db + keys := []string{ + // global key + ServiceKey + srv.Id, + // owner key + OwnerKey + id + "/" + req.Name, + } + + // delete the keys for the service + for _, key := range keys { + rec := store.NewRecord(key, srv) + // write the app to the db + if err := store.Write(rec); err != nil { + log.Error(err) + return err + } + } + + // set the custom domain + if len(e.domain) > 0 { + rsp.Service.Url = fmt.Sprintf("https://%s.%s", srv.Id, e.domain) + } + + return nil +} + +func (a *App) Resolve(ctx context.Context, req *pb.ResolveRequest, rsp *pb.ResolveResponse) error { + if len(req.Id) == 0 { + return errors.BadRequest("app.resolve", "missing id") + } + + key := ServiceKey + req.Id + + recs, err := store.Read(key, store.ReadLimit(1)) + if err != nil { + return err + } + + if len(recs) == 0 { + return errors.BadRequest("app.resolve", "app does not exist") + } + + srv := new(pb.Service) + recs[0].Decode(srv) + + rsp.Url = srv.Url + return nil +} diff --git a/app/handler/vote.go b/app/handler/vote.go deleted file mode 100644 index 9b1d117..0000000 --- a/app/handler/vote.go +++ /dev/null @@ -1,44 +0,0 @@ -package handler - -import ( - "context" - "time" - - - "github.com/micro/services/pkg/tenant" - "github.com/micro/micro/v3/service/store" - pb "github.com/micro/services/app/proto" -) - -var ( - voteKey = "votes/" -) - -type Vote struct { - Id string `json:"id"` - Message string `json:"message"` - VotedAt time.Time `json:"voted_at"` -} - -func (n *App) Vote(ctx context.Context, req *pb.VoteRequest, rsp *pb.VoteResponse) error { - mtx.Lock() - defer mtx.Unlock() - - id, ok := tenant.FromContext(ctx) - if !ok { - id = "micro" - } - - rec := store.NewRecord(voteKey + id, &Vote{ - Id: id, - Message: req.Message, - VotedAt: time.Now(), - }) - - // we don't need to check the error - store.Write(rec) - - rsp.Message = "Thanks for the vote!" - - return nil -} diff --git a/app/image/Dockerfile b/app/image/Dockerfile new file mode 100644 index 0000000..420ec08 --- /dev/null +++ b/app/image/Dockerfile @@ -0,0 +1,24 @@ +FROM micro/cells:v3 as builder + +RUN apk add curl + +# Install python/pip +ENV PYTHONUNBUFFERED=1 +RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python +RUN python3 -m ensurepip +RUN pip3 install --no-cache --upgrade pip setuptools + +# https://stackoverflow.com/questions/28372328/how-to-install-the-google-cloud-sdk-in-a-docker-image + +# Downloading gcloud package +RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz + +# Installing the package +RUN mkdir -p /usr/local/gcloud \ + && tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \ + && /usr/local/gcloud/google-cloud-sdk/install.sh + +# Adding the package path to local +ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin + + diff --git a/app/main.go b/app/main.go index 17c1931..a689ba3 100644 --- a/app/main.go +++ b/app/main.go @@ -15,7 +15,7 @@ func main() { ) // Register handler - pb.RegisterAppHandler(srv.Server(), new(handler.App)) + pb.RegisterAppHandler(srv.Server(), handler.New()) // Run service if err := srv.Run(); err != nil { diff --git a/app/proto/app.pb.go b/app/proto/app.pb.go index 87ef761..af7f0dd 100644 --- a/app/proto/app.pb.go +++ b/app/proto/app.pb.go @@ -20,6 +20,642 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type Service struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // unique id + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // name of the app + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // source repository + Repo string `protobuf:"bytes,3,opt,name=repo,proto3" json:"repo,omitempty"` + // branch of code + Branch string `protobuf:"bytes,4,opt,name=branch,proto3" json:"branch,omitempty"` + // region running in + Region string `protobuf:"bytes,5,opt,name=region,proto3" json:"region,omitempty"` + // port running on + Port int32 `protobuf:"varint,6,opt,name=port,proto3" json:"port,omitempty"` + // status of the app + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + // app url + Url string `protobuf:"bytes,8,opt,name=url,proto3" json:"url,omitempty"` + // time of creation + Created string `protobuf:"bytes,9,opt,name=created,proto3" json:"created,omitempty"` + // last updated + Updated string `protobuf:"bytes,10,opt,name=updated,proto3" json:"updated,omitempty"` + // associated env vars + EnvVars map[string]string `protobuf:"bytes,11,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // custom domains + CustomDomains []string `protobuf:"bytes,12,rep,name=custom_domains,json=customDomains,proto3" json:"custom_domains,omitempty"` +} + +func (x *Service) Reset() { + *x = Service{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Service) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Service) ProtoMessage() {} + +func (x *Service) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Service.ProtoReflect.Descriptor instead. +func (*Service) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{0} +} + +func (x *Service) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Service) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Service) GetRepo() string { + if x != nil { + return x.Repo + } + return "" +} + +func (x *Service) GetBranch() string { + if x != nil { + return x.Branch + } + return "" +} + +func (x *Service) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *Service) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *Service) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *Service) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *Service) GetCreated() string { + if x != nil { + return x.Created + } + return "" +} + +func (x *Service) GetUpdated() string { + if x != nil { + return x.Updated + } + return "" +} + +func (x *Service) GetEnvVars() map[string]string { + if x != nil { + return x.EnvVars + } + return nil +} + +func (x *Service) GetCustomDomains() []string { + if x != nil { + return x.CustomDomains + } + return nil +} + +// Delete an app +type DeleteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the app + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *DeleteRequest) Reset() { + *x = DeleteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest) ProtoMessage() {} + +func (x *DeleteRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead. +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{1} +} + +func (x *DeleteRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type DeleteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeleteResponse) Reset() { + *x = DeleteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteResponse) ProtoMessage() {} + +func (x *DeleteResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteResponse.ProtoReflect.Descriptor instead. +func (*DeleteResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{2} +} + +// List all the apps +type ListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListRequest) Reset() { + *x = ListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRequest) ProtoMessage() {} + +func (x *ListRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead. +func (*ListRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{3} +} + +type ListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // all the apps + Services []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` +} + +func (x *ListResponse) Reset() { + *x = ListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListResponse) ProtoMessage() {} + +func (x *ListResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListResponse.ProtoReflect.Descriptor instead. +func (*ListResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{4} +} + +func (x *ListResponse) GetServices() []*Service { + if x != nil { + return x.Services + } + return nil +} + +// Run an app +type RunRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the app + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // source repository + Repo string `protobuf:"bytes,2,opt,name=repo,proto3" json:"repo,omitempty"` + // branch. defaults to master + Branch string `protobuf:"bytes,3,opt,name=branch,proto3" json:"branch,omitempty"` + // region to run in + Region string `protobuf:"bytes,4,opt,name=region,proto3" json:"region,omitempty"` + // port to run on + Port int32 `protobuf:"varint,5,opt,name=port,proto3" json:"port,omitempty"` + // associatede env vars to pass in + EnvVars map[string]string `protobuf:"bytes,6,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *RunRequest) Reset() { + *x = RunRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RunRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunRequest) ProtoMessage() {} + +func (x *RunRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunRequest.ProtoReflect.Descriptor instead. +func (*RunRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{5} +} + +func (x *RunRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RunRequest) GetRepo() string { + if x != nil { + return x.Repo + } + return "" +} + +func (x *RunRequest) GetBranch() string { + if x != nil { + return x.Branch + } + return "" +} + +func (x *RunRequest) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *RunRequest) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *RunRequest) GetEnvVars() map[string]string { + if x != nil { + return x.EnvVars + } + return nil +} + +type RunResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The running service + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` +} + +func (x *RunResponse) Reset() { + *x = RunResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RunResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunResponse) ProtoMessage() {} + +func (x *RunResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunResponse.ProtoReflect.Descriptor instead. +func (*RunResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{6} +} + +func (x *RunResponse) GetService() *Service { + if x != nil { + return x.Service + } + return nil +} + +// Update the app +type UpdateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the app + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *UpdateRequest) Reset() { + *x = UpdateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateRequest) ProtoMessage() {} + +func (x *UpdateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateRequest.ProtoReflect.Descriptor instead. +func (*UpdateRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{7} +} + +func (x *UpdateRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UpdateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *UpdateResponse) Reset() { + *x = UpdateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateResponse) ProtoMessage() {} + +func (x *UpdateResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateResponse.ProtoReflect.Descriptor instead. +func (*UpdateResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{8} +} + +// Return the support regions +type RegionsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RegionsRequest) Reset() { + *x = RegionsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegionsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegionsRequest) ProtoMessage() {} + +func (x *RegionsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegionsRequest.ProtoReflect.Descriptor instead. +func (*RegionsRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{9} +} + +type RegionsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Regions []string `protobuf:"bytes,1,rep,name=regions,proto3" json:"regions,omitempty"` +} + +func (x *RegionsResponse) Reset() { + *x = RegionsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegionsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegionsResponse) ProtoMessage() {} + +func (x *RegionsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegionsResponse.ProtoReflect.Descriptor instead. +func (*RegionsResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{10} +} + +func (x *RegionsResponse) GetRegions() []string { + if x != nil { + return x.Regions + } + return nil +} + // Vote to have the App api launched faster! type VoteRequest struct { state protoimpl.MessageState @@ -33,7 +669,7 @@ type VoteRequest struct { func (x *VoteRequest) Reset() { *x = VoteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_app_proto_msgTypes[0] + mi := &file_proto_app_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -46,7 +682,7 @@ func (x *VoteRequest) String() string { func (*VoteRequest) ProtoMessage() {} func (x *VoteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_app_proto_msgTypes[0] + mi := &file_proto_app_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -59,7 +695,7 @@ func (x *VoteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VoteRequest.ProtoReflect.Descriptor instead. func (*VoteRequest) Descriptor() ([]byte, []int) { - return file_proto_app_proto_rawDescGZIP(), []int{0} + return file_proto_app_proto_rawDescGZIP(), []int{11} } func (x *VoteRequest) GetMessage() string { @@ -81,7 +717,7 @@ type VoteResponse struct { func (x *VoteResponse) Reset() { *x = VoteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_app_proto_msgTypes[1] + mi := &file_proto_app_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -94,7 +730,7 @@ func (x *VoteResponse) String() string { func (*VoteResponse) ProtoMessage() {} func (x *VoteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_app_proto_msgTypes[1] + mi := &file_proto_app_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -107,7 +743,7 @@ func (x *VoteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VoteResponse.ProtoReflect.Descriptor instead. func (*VoteResponse) Descriptor() ([]byte, []int) { - return file_proto_app_proto_rawDescGZIP(), []int{1} + return file_proto_app_proto_rawDescGZIP(), []int{12} } func (x *VoteResponse) GetMessage() string { @@ -137,7 +773,7 @@ type Reservation struct { func (x *Reservation) Reset() { *x = Reservation{} if protoimpl.UnsafeEnabled { - mi := &file_proto_app_proto_msgTypes[2] + mi := &file_proto_app_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -150,7 +786,7 @@ func (x *Reservation) String() string { func (*Reservation) ProtoMessage() {} func (x *Reservation) ProtoReflect() protoreflect.Message { - mi := &file_proto_app_proto_msgTypes[2] + mi := &file_proto_app_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -163,7 +799,7 @@ func (x *Reservation) ProtoReflect() protoreflect.Message { // Deprecated: Use Reservation.ProtoReflect.Descriptor instead. func (*Reservation) Descriptor() ([]byte, []int) { - return file_proto_app_proto_rawDescGZIP(), []int{2} + return file_proto_app_proto_rawDescGZIP(), []int{13} } func (x *Reservation) GetName() string { @@ -201,7 +837,7 @@ func (x *Reservation) GetExpires() string { return "" } -// Reserve your app name +// Reserve apps beyond the free quota. Call Run after. type ReserveRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -214,7 +850,7 @@ type ReserveRequest struct { func (x *ReserveRequest) Reset() { *x = ReserveRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_app_proto_msgTypes[3] + mi := &file_proto_app_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -227,7 +863,7 @@ func (x *ReserveRequest) String() string { func (*ReserveRequest) ProtoMessage() {} func (x *ReserveRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_app_proto_msgTypes[3] + mi := &file_proto_app_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -240,7 +876,7 @@ func (x *ReserveRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveRequest.ProtoReflect.Descriptor instead. func (*ReserveRequest) Descriptor() ([]byte, []int) { - return file_proto_app_proto_rawDescGZIP(), []int{3} + return file_proto_app_proto_rawDescGZIP(), []int{14} } func (x *ReserveRequest) GetName() string { @@ -255,13 +891,14 @@ type ReserveResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // The app reservation Reservation *Reservation `protobuf:"bytes,1,opt,name=reservation,proto3" json:"reservation,omitempty"` } func (x *ReserveResponse) Reset() { *x = ReserveResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_app_proto_msgTypes[4] + mi := &file_proto_app_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -274,7 +911,7 @@ func (x *ReserveResponse) String() string { func (*ReserveResponse) ProtoMessage() {} func (x *ReserveResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_app_proto_msgTypes[4] + mi := &file_proto_app_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -287,7 +924,7 @@ func (x *ReserveResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveResponse.ProtoReflect.Descriptor instead. func (*ReserveResponse) Descriptor() ([]byte, []int) { - return file_proto_app_proto_rawDescGZIP(), []int{4} + return file_proto_app_proto_rawDescGZIP(), []int{15} } func (x *ReserveResponse) GetReservation() *Reservation { @@ -297,39 +934,321 @@ func (x *ReserveResponse) GetReservation() *Reservation { return nil } +// Get the status of an app +type StatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the app + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *StatusRequest) Reset() { + *x = StatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatusRequest) ProtoMessage() {} + +func (x *StatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StatusRequest.ProtoReflect.Descriptor instead. +func (*StatusRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{16} +} + +func (x *StatusRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type StatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // running service info + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` +} + +func (x *StatusResponse) Reset() { + *x = StatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatusResponse) ProtoMessage() {} + +func (x *StatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. +func (*StatusResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{17} +} + +func (x *StatusResponse) GetService() *Service { + if x != nil { + return x.Service + } + return nil +} + +// Resolve an app id to its url +type ResolveRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // the service id + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *ResolveRequest) Reset() { + *x = ResolveRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResolveRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveRequest) ProtoMessage() {} + +func (x *ResolveRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveRequest.ProtoReflect.Descriptor instead. +func (*ResolveRequest) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{18} +} + +func (x *ResolveRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type ResolveResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // the url + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *ResolveResponse) Reset() { + *x = ResolveResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_app_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResolveResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveResponse) ProtoMessage() {} + +func (x *ResolveResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_app_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveResponse.ProtoReflect.Descriptor instead. +func (*ResolveResponse) Descriptor() ([]byte, []int) { + return file_proto_app_proto_rawDescGZIP(), []int{19} +} + +func (x *ResolveResponse) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + var File_proto_app_proto protoreflect.FileDescriptor var file_proto_app_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x03, 0x61, 0x70, 0x70, 0x22, 0x27, 0x0a, 0x0b, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x28, 0x0a, 0x0c, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x52, 0x65, - 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x22, 0x24, 0x0a, - 0x0e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x72, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x6c, 0x0a, 0x03, 0x41, 0x70, - 0x70, 0x12, 0x36, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x12, 0x13, 0x2e, 0x61, - 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x04, 0x56, 0x6f, 0x74, - 0x65, 0x12, 0x10, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x3b, 0x61, 0x70, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x12, 0x03, 0x61, 0x70, 0x70, 0x22, 0xfc, 0x02, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x08, + 0x65, 0x6e, 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x76, + 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x56, 0x61, + 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x64, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, + 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x23, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0d, 0x0a, 0x0b, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x38, 0x0a, 0x0c, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0xed, 0x01, 0x0a, 0x0a, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x16, 0x0a, 0x06, + 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, + 0x12, 0x37, 0x0a, 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x07, 0x65, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, + 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x35, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x23, 0x0a, 0x0d, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x73, 0x22, 0x27, 0x0a, 0x0b, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x28, 0x0a, 0x0c, 0x56, + 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, + 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x22, 0x24, 0x0a, 0x0e, 0x52, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x45, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x65, + 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x23, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x38, 0x0a, 0x0e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, + 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x20, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x32, 0xa7, 0x03, 0x0a, + 0x03, 0x41, 0x70, 0x70, 0x12, 0x36, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x12, + 0x13, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, + 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, + 0x70, 0x70, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x2a, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x0f, 0x2e, 0x61, 0x70, + 0x70, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x61, + 0x70, 0x70, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x33, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x70, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x12, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x2d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, + 0x0a, 0x07, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x3b, 0x61, 0x70, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -344,25 +1263,59 @@ func file_proto_app_proto_rawDescGZIP() []byte { return file_proto_app_proto_rawDescData } -var file_proto_app_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_proto_app_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_proto_app_proto_goTypes = []interface{}{ - (*VoteRequest)(nil), // 0: app.VoteRequest - (*VoteResponse)(nil), // 1: app.VoteResponse - (*Reservation)(nil), // 2: app.Reservation - (*ReserveRequest)(nil), // 3: app.ReserveRequest - (*ReserveResponse)(nil), // 4: app.ReserveResponse + (*Service)(nil), // 0: app.Service + (*DeleteRequest)(nil), // 1: app.DeleteRequest + (*DeleteResponse)(nil), // 2: app.DeleteResponse + (*ListRequest)(nil), // 3: app.ListRequest + (*ListResponse)(nil), // 4: app.ListResponse + (*RunRequest)(nil), // 5: app.RunRequest + (*RunResponse)(nil), // 6: app.RunResponse + (*UpdateRequest)(nil), // 7: app.UpdateRequest + (*UpdateResponse)(nil), // 8: app.UpdateResponse + (*RegionsRequest)(nil), // 9: app.RegionsRequest + (*RegionsResponse)(nil), // 10: app.RegionsResponse + (*VoteRequest)(nil), // 11: app.VoteRequest + (*VoteResponse)(nil), // 12: app.VoteResponse + (*Reservation)(nil), // 13: app.Reservation + (*ReserveRequest)(nil), // 14: app.ReserveRequest + (*ReserveResponse)(nil), // 15: app.ReserveResponse + (*StatusRequest)(nil), // 16: app.StatusRequest + (*StatusResponse)(nil), // 17: app.StatusResponse + (*ResolveRequest)(nil), // 18: app.ResolveRequest + (*ResolveResponse)(nil), // 19: app.ResolveResponse + nil, // 20: app.Service.EnvVarsEntry + nil, // 21: app.RunRequest.EnvVarsEntry } var file_proto_app_proto_depIdxs = []int32{ - 2, // 0: app.ReserveResponse.reservation:type_name -> app.Reservation - 3, // 1: app.App.Reserve:input_type -> app.ReserveRequest - 0, // 2: app.App.Vote:input_type -> app.VoteRequest - 4, // 3: app.App.Reserve:output_type -> app.ReserveResponse - 1, // 4: app.App.Vote:output_type -> app.VoteResponse - 3, // [3:5] is the sub-list for method output_type - 1, // [1:3] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 20, // 0: app.Service.env_vars:type_name -> app.Service.EnvVarsEntry + 0, // 1: app.ListResponse.services:type_name -> app.Service + 21, // 2: app.RunRequest.env_vars:type_name -> app.RunRequest.EnvVarsEntry + 0, // 3: app.RunResponse.service:type_name -> app.Service + 13, // 4: app.ReserveResponse.reservation:type_name -> app.Reservation + 0, // 5: app.StatusResponse.service:type_name -> app.Service + 14, // 6: app.App.Reserve:input_type -> app.ReserveRequest + 9, // 7: app.App.Regions:input_type -> app.RegionsRequest + 5, // 8: app.App.Run:input_type -> app.RunRequest + 7, // 9: app.App.Update:input_type -> app.UpdateRequest + 1, // 10: app.App.Delete:input_type -> app.DeleteRequest + 16, // 11: app.App.Status:input_type -> app.StatusRequest + 3, // 12: app.App.List:input_type -> app.ListRequest + 18, // 13: app.App.Resolve:input_type -> app.ResolveRequest + 15, // 14: app.App.Reserve:output_type -> app.ReserveResponse + 10, // 15: app.App.Regions:output_type -> app.RegionsResponse + 6, // 16: app.App.Run:output_type -> app.RunResponse + 8, // 17: app.App.Update:output_type -> app.UpdateResponse + 2, // 18: app.App.Delete:output_type -> app.DeleteResponse + 17, // 19: app.App.Status:output_type -> app.StatusResponse + 4, // 20: app.App.List:output_type -> app.ListResponse + 19, // 21: app.App.Resolve:output_type -> app.ResolveResponse + 14, // [14:22] is the sub-list for method output_type + 6, // [6:14] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_proto_app_proto_init() } @@ -372,7 +1325,7 @@ func file_proto_app_proto_init() { } if !protoimpl.UnsafeEnabled { file_proto_app_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VoteRequest); i { + switch v := v.(*Service); i { case 0: return &v.state case 1: @@ -384,7 +1337,7 @@ func file_proto_app_proto_init() { } } file_proto_app_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VoteResponse); i { + switch v := v.(*DeleteRequest); i { case 0: return &v.state case 1: @@ -396,7 +1349,7 @@ func file_proto_app_proto_init() { } } file_proto_app_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Reservation); i { + switch v := v.(*DeleteResponse); i { case 0: return &v.state case 1: @@ -408,7 +1361,7 @@ func file_proto_app_proto_init() { } } file_proto_app_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReserveRequest); i { + switch v := v.(*ListRequest); i { case 0: return &v.state case 1: @@ -420,6 +1373,138 @@ func file_proto_app_proto_init() { } } file_proto_app_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RunRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RunResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegionsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegionsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VoteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VoteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Reservation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReserveRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReserveResponse); i { case 0: return &v.state @@ -431,6 +1516,54 @@ func file_proto_app_proto_init() { return nil } } + file_proto_app_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StatusRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StatusResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResolveRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_app_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResolveResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -438,7 +1571,7 @@ func file_proto_app_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_app_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/app/proto/app.pb.micro.go b/app/proto/app.pb.micro.go index fb9db8e..bd71eb5 100644 --- a/app/proto/app.pb.micro.go +++ b/app/proto/app.pb.micro.go @@ -43,7 +43,13 @@ func NewAppEndpoints() []*api.Endpoint { type AppService interface { Reserve(ctx context.Context, in *ReserveRequest, opts ...client.CallOption) (*ReserveResponse, error) - Vote(ctx context.Context, in *VoteRequest, opts ...client.CallOption) (*VoteResponse, error) + Regions(ctx context.Context, in *RegionsRequest, opts ...client.CallOption) (*RegionsResponse, error) + Run(ctx context.Context, in *RunRequest, opts ...client.CallOption) (*RunResponse, error) + Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) + Status(ctx context.Context, in *StatusRequest, opts ...client.CallOption) (*StatusResponse, error) + List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) + Resolve(ctx context.Context, in *ResolveRequest, opts ...client.CallOption) (*ResolveResponse, error) } type appService struct { @@ -68,9 +74,69 @@ func (c *appService) Reserve(ctx context.Context, in *ReserveRequest, opts ...cl return out, nil } -func (c *appService) Vote(ctx context.Context, in *VoteRequest, opts ...client.CallOption) (*VoteResponse, error) { - req := c.c.NewRequest(c.name, "App.Vote", in) - out := new(VoteResponse) +func (c *appService) Regions(ctx context.Context, in *RegionsRequest, opts ...client.CallOption) (*RegionsResponse, error) { + req := c.c.NewRequest(c.name, "App.Regions", in) + out := new(RegionsResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *appService) Run(ctx context.Context, in *RunRequest, opts ...client.CallOption) (*RunResponse, error) { + req := c.c.NewRequest(c.name, "App.Run", in) + out := new(RunResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *appService) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) { + req := c.c.NewRequest(c.name, "App.Update", in) + out := new(UpdateResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *appService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) { + req := c.c.NewRequest(c.name, "App.Delete", in) + out := new(DeleteResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *appService) Status(ctx context.Context, in *StatusRequest, opts ...client.CallOption) (*StatusResponse, error) { + req := c.c.NewRequest(c.name, "App.Status", in) + out := new(StatusResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *appService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) { + req := c.c.NewRequest(c.name, "App.List", in) + out := new(ListResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *appService) Resolve(ctx context.Context, in *ResolveRequest, opts ...client.CallOption) (*ResolveResponse, error) { + req := c.c.NewRequest(c.name, "App.Resolve", in) + out := new(ResolveResponse) err := c.c.Call(ctx, req, out, opts...) if err != nil { return nil, err @@ -82,13 +148,25 @@ func (c *appService) Vote(ctx context.Context, in *VoteRequest, opts ...client.C type AppHandler interface { Reserve(context.Context, *ReserveRequest, *ReserveResponse) error - Vote(context.Context, *VoteRequest, *VoteResponse) error + Regions(context.Context, *RegionsRequest, *RegionsResponse) error + Run(context.Context, *RunRequest, *RunResponse) error + Update(context.Context, *UpdateRequest, *UpdateResponse) error + Delete(context.Context, *DeleteRequest, *DeleteResponse) error + Status(context.Context, *StatusRequest, *StatusResponse) error + List(context.Context, *ListRequest, *ListResponse) error + Resolve(context.Context, *ResolveRequest, *ResolveResponse) error } func RegisterAppHandler(s server.Server, hdlr AppHandler, opts ...server.HandlerOption) error { type app interface { Reserve(ctx context.Context, in *ReserveRequest, out *ReserveResponse) error - Vote(ctx context.Context, in *VoteRequest, out *VoteResponse) error + Regions(ctx context.Context, in *RegionsRequest, out *RegionsResponse) error + Run(ctx context.Context, in *RunRequest, out *RunResponse) error + Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error + Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error + Status(ctx context.Context, in *StatusRequest, out *StatusResponse) error + List(ctx context.Context, in *ListRequest, out *ListResponse) error + Resolve(ctx context.Context, in *ResolveRequest, out *ResolveResponse) error } type App struct { app @@ -105,6 +183,30 @@ func (h *appHandler) Reserve(ctx context.Context, in *ReserveRequest, out *Reser return h.AppHandler.Reserve(ctx, in, out) } -func (h *appHandler) Vote(ctx context.Context, in *VoteRequest, out *VoteResponse) error { - return h.AppHandler.Vote(ctx, in, out) +func (h *appHandler) Regions(ctx context.Context, in *RegionsRequest, out *RegionsResponse) error { + return h.AppHandler.Regions(ctx, in, out) +} + +func (h *appHandler) Run(ctx context.Context, in *RunRequest, out *RunResponse) error { + return h.AppHandler.Run(ctx, in, out) +} + +func (h *appHandler) Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error { + return h.AppHandler.Update(ctx, in, out) +} + +func (h *appHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { + return h.AppHandler.Delete(ctx, in, out) +} + +func (h *appHandler) Status(ctx context.Context, in *StatusRequest, out *StatusResponse) error { + return h.AppHandler.Status(ctx, in, out) +} + +func (h *appHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error { + return h.AppHandler.List(ctx, in, out) +} + +func (h *appHandler) Resolve(ctx context.Context, in *ResolveRequest, out *ResolveResponse) error { + return h.AppHandler.Resolve(ctx, in, out) } diff --git a/app/proto/app.proto b/app/proto/app.proto index af3bcda..e0a4ef0 100644 --- a/app/proto/app.proto +++ b/app/proto/app.proto @@ -6,20 +6,98 @@ option go_package = "./proto;app"; service App { rpc Reserve(ReserveRequest) returns (ReserveResponse) {} - rpc Vote(VoteRequest) returns (VoteResponse) {} + rpc Regions(RegionsRequest) returns (RegionsResponse) {} + rpc Run(RunRequest) returns (RunResponse) {} + rpc Update(UpdateRequest) returns (UpdateResponse) {} + rpc Delete(DeleteRequest) returns (DeleteResponse) {} + rpc Status(StatusRequest) returns (StatusResponse) {} + rpc List(ListRequest) returns (ListResponse) {} + rpc Resolve(ResolveRequest) returns (ResolveResponse) {} } -// Vote to have the App api launched faster! -message VoteRequest { - // optional message - string message = 1; +message Service { + // unique id + string id = 1; + // name of the app + string name = 2; + // source repository + string repo = 3; + // branch of code + string branch = 4; + // region running in + string region = 5; + // port running on + int32 port = 6; + // status of the app + string status = 7; + // app url + string url = 8; + // time of creation + string created = 9; + // last updated + string updated = 10; + // associated env vars + map env_vars = 11; + // custom domains + repeated string custom_domains = 12; } -message VoteResponse { - // response message - string message = 2; +// Delete an app +message DeleteRequest { + // name of the app + string name = 1; } +message DeleteResponse {} + +// List all the apps +message ListRequest { +} + +message ListResponse { + // all the apps + repeated Service services = 1; +} + +// Run an app +message RunRequest { + // name of the app + string name = 1; + // source repository + string repo = 2; + // branch. defaults to master + string branch = 3; + // region to run in + string region = 4; + // port to run on + int32 port = 5; + // associatede env vars to pass in + map env_vars = 6; +} + +message RunResponse { + // The running service + Service service = 1; +} + +// Update the app +message UpdateRequest { + // name of the app + string name = 1; +} + +message UpdateResponse { +} + + +// Return the support regions +message RegionsRequest {} + +message RegionsResponse { + repeated string regions = 1; +} + +// Reservation represents a reserved app instance message Reservation { // name of the app string name = 1; @@ -33,12 +111,35 @@ message Reservation { string expires = 5; } -// Reserve your app name +// Reserve apps beyond the free quota. Call Run after. message ReserveRequest { // name of your app e.g helloworld string name = 1; } message ReserveResponse { + // The app reservation Reservation reservation = 1; } + +// Get the status of an app +message StatusRequest { + // name of the app + string name = 1; +} + +message StatusResponse { + // running service info + Service service = 1; +} + +// Resolve an app by id to its raw backend endpoint +message ResolveRequest { + // the service id + string id = 1; +} + +message ResolveResponse { + // the end provider url + string url = 1; +} diff --git a/app/publicapi.json b/app/publicapi.json index 06f5b53..f4aff50 100644 --- a/app/publicapi.json +++ b/app/publicapi.json @@ -1,9 +1,9 @@ { "name": "app", "icon": "☁️", - "category": "coming soon", - "display_name": "Apps (Coming Soon)", + "category": "hosting", + "display_name": "Apps", "pricing": { - "App.Reserve": 1000000 + "App.Reserve": 10000000 } }