Skip to content

Commit

Permalink
Implement API endpoints (#6915)
Browse files Browse the repository at this point in the history
* Pass odo context to api server

* Get /instance

* DELETE /instance implementation

* Move describe logic to pkg/component/describe

* Get /component implementation

* POST /component/command implementation

* Fix example by replacing action with name

* Fix integration test

* Integration tests

* Add comment for PushWatcher

* Test DELETE /instance without --no-watch

* Apply suggestions from code review

Co-authored-by: Armel Soro <[email protected]>

* Return an error if not ready for push

* Fix windows tests

* Fix tests for Windows

---------

Co-authored-by: Armel Soro <[email protected]>
  • Loading branch information
feloy and rm3l authored Jun 26, 2023
1 parent 535ee0a commit 94e3230
Show file tree
Hide file tree
Showing 10 changed files with 513 additions and 271 deletions.
2 changes: 1 addition & 1 deletion ododevapispec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ paths:
enum:
- "push"
example:
action: push
name: push
responses:
'200':
description: command was successfully executed
Expand Down
1 change: 0 additions & 1 deletion pkg/apiserver-gen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ To see how to make this your own, look here:

- API version: 0.1


### Running the server
To run the server, follow these simple steps:

Expand Down
87 changes: 56 additions & 31 deletions pkg/apiserver-impl/api_default_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,87 @@ package apiserver_impl

import (
"context"
"errors"
openapi "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
"fmt"
"net/http"

openapi "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
"github.com/redhat-developer/odo/pkg/component/describe"
"github.com/redhat-developer/odo/pkg/kclient"
odocontext "github.com/redhat-developer/odo/pkg/odo/context"
"github.com/redhat-developer/odo/pkg/podman"
"github.com/redhat-developer/odo/pkg/state"
)

// DefaultApiService is a service that implements the logic for the DefaultApiServicer
// This service should implement the business logic for every endpoint for the DefaultApi API.
// Include any external packages or services that will be required by this service.
type DefaultApiService struct {
cancel context.CancelFunc
pushWatcher chan<- struct{}
kubeClient kclient.ClientInterface
podmanClient podman.Client
stateClient state.Client
}

// NewDefaultApiService creates a default api service
func NewDefaultApiService() openapi.DefaultApiServicer {
return &DefaultApiService{}
func NewDefaultApiService(
cancel context.CancelFunc,
pushWatcher chan<- struct{},
kubeClient kclient.ClientInterface,
podmanClient podman.Client,
stateClient state.Client,
) openapi.DefaultApiServicer {
return &DefaultApiService{
cancel: cancel,
pushWatcher: pushWatcher,
kubeClient: kubeClient,
podmanClient: podmanClient,
stateClient: stateClient,
}
}

// ComponentCommandPost -
func (s *DefaultApiService) ComponentCommandPost(ctx context.Context, componentCommandPostRequest openapi.ComponentCommandPostRequest) (openapi.ImplResponse, error) {
// TODO - update ComponentCommandPost with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
switch componentCommandPostRequest.Name {
case "push":
select {
case s.pushWatcher <- struct{}{}:
return openapi.Response(http.StatusOK, openapi.GeneralSuccess{
Message: "push was successfully executed",
}), nil
default:
return openapi.Response(http.StatusTooManyRequests, openapi.GeneralError{
Message: "a push operation is not possible at this time. Please retry later",
}), nil
}

// TODO: Uncomment the next line to return response Response(200, GeneralSuccess{}) or use other options such as http.Ok ...
// return Response(200, GeneralSuccess{}), nil

return openapi.Response(http.StatusNotImplemented, nil), errors.New("ComponentCommandPost method not implemented")
default:
return openapi.Response(http.StatusBadRequest, nil), fmt.Errorf("command name %q not supported. Supported values are: %q", componentCommandPostRequest.Name, "push")
}
}

// ComponentGet -
func (s *DefaultApiService) ComponentGet(ctx context.Context) (openapi.ImplResponse, error) {
// TODO - update ComponentGet with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

// TODO: Uncomment the next line to return response Response(200, ComponentGet200Response{}) or use other options such as http.Ok ...
// return Response(200, ComponentGet200Response{}), nil

return openapi.Response(http.StatusNotImplemented, nil), errors.New("ComponentGet method not implemented")
value, _, err := describe.DescribeDevfileComponent(ctx, s.kubeClient, s.podmanClient, s.stateClient)
if err != nil {
return openapi.Response(http.StatusInternalServerError, ""), fmt.Errorf("error getting the description of the component: %w", err)
}
return openapi.Response(http.StatusOK, value), nil
}

// InstanceDelete -
func (s *DefaultApiService) InstanceDelete(ctx context.Context) (openapi.ImplResponse, error) {
// TODO - update InstanceDelete with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

// TODO: Uncomment the next line to return response Response(200, GeneralSuccess{}) or use other options such as http.Ok ...
// return Response(200, GeneralSuccess{}), nil

return openapi.Response(http.StatusNotImplemented, nil), errors.New("InstanceDelete method not implemented")
s.cancel()
return openapi.Response(http.StatusOK, openapi.GeneralSuccess{
Message: fmt.Sprintf("'odo dev' instance with pid: %d is shutting down.", odocontext.GetPID(ctx)),
}), nil
}

// InstanceGet -
func (s *DefaultApiService) InstanceGet(ctx context.Context) (openapi.ImplResponse, error) {
// TODO - update InstanceGet with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

// TODO: Uncomment the next line to return response Response(200, InstanceGet200Response{}) or use other options such as http.Ok ...
// return Response(200, InstanceGet200Response{}), nil

return openapi.Response(http.StatusNotImplemented, nil), errors.New("InstanceGet method not implemented")
response := openapi.InstanceGet200Response{
Pid: int32(odocontext.GetPID(ctx)),
ComponentDirectory: odocontext.GetWorkingDirectory(ctx),
}
return openapi.Response(http.StatusOK, response), nil
}
35 changes: 32 additions & 3 deletions pkg/apiserver-impl/starterserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,38 @@ package apiserver_impl
import (
"context"
"fmt"
"net"
"net/http"

openapi "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
"github.com/redhat-developer/odo/pkg/kclient"
"github.com/redhat-developer/odo/pkg/podman"
"github.com/redhat-developer/odo/pkg/state"
"github.com/redhat-developer/odo/pkg/util"
"k8s.io/klog"
"net/http"
)

func StartServer(ctx context.Context, cancelFunc context.CancelFunc, port int, stateClient state.Client) {
type ApiServer struct {
PushWatcher <-chan struct{}
}

func StartServer(
ctx context.Context,
cancelFunc context.CancelFunc,
port int,
kubernetesClient kclient.ClientInterface,
podmanClient podman.Client,
stateClient state.Client,
) ApiServer {

defaultApiService := NewDefaultApiService()
pushWatcher := make(chan struct{})
defaultApiService := NewDefaultApiService(
cancelFunc,
pushWatcher,
kubernetesClient,
podmanClient,
stateClient,
)
defaultApiController := openapi.NewDefaultApiController(defaultApiService)

router := openapi.NewRouter(defaultApiController)
Expand All @@ -38,6 +60,9 @@ func StartServer(ctx context.Context, cancelFunc context.CancelFunc, port int, s
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: router}
var errChan = make(chan error)
go func() {
server.BaseContext = func(net.Listener) context.Context {
return ctx
}
err = server.ListenAndServe()
errChan <- err
}()
Expand All @@ -54,4 +79,8 @@ func StartServer(ctx context.Context, cancelFunc context.CancelFunc, port int, s
cancelFunc()
}
}()

return ApiServer{
PushWatcher: pushWatcher,
}
}
Loading

0 comments on commit 94e3230

Please sign in to comment.