...

Source file src/github.com/redhat-developer/odo/pkg/apiserver-impl/api_default_service.go

Documentation: github.com/redhat-developer/odo/pkg/apiserver-impl

     1  package apiserver_impl
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	openapi "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
    11  	"github.com/redhat-developer/odo/pkg/apiserver-impl/devstate"
    12  	"github.com/redhat-developer/odo/pkg/component/describe"
    13  	"github.com/redhat-developer/odo/pkg/devfile"
    14  	"github.com/redhat-developer/odo/pkg/devfile/validate"
    15  	"github.com/redhat-developer/odo/pkg/kclient"
    16  	fcontext "github.com/redhat-developer/odo/pkg/odo/commonflags/context"
    17  	odocontext "github.com/redhat-developer/odo/pkg/odo/context"
    18  	"github.com/redhat-developer/odo/pkg/podman"
    19  	"github.com/redhat-developer/odo/pkg/preference"
    20  	"github.com/redhat-developer/odo/pkg/segment"
    21  	scontext "github.com/redhat-developer/odo/pkg/segment/context"
    22  	"github.com/redhat-developer/odo/pkg/state"
    23  	"k8s.io/klog"
    24  )
    25  
    26  // DefaultApiService is a service that implements the logic for the DefaultApiServicer
    27  // This service should implement the business logic for every endpoint for the DefaultApi API.
    28  // Include any external packages or services that will be required by this service.
    29  type DefaultApiService struct {
    30  	cancel           context.CancelFunc
    31  	pushWatcher      chan<- struct{}
    32  	kubeClient       kclient.ClientInterface
    33  	podmanClient     podman.Client
    34  	stateClient      state.Client
    35  	preferenceClient preference.Client
    36  
    37  	devfileState devstate.DevfileState
    38  }
    39  
    40  // NewDefaultApiService creates a default api service
    41  func NewDefaultApiService(
    42  	cancel context.CancelFunc,
    43  	pushWatcher chan<- struct{},
    44  	kubeClient kclient.ClientInterface,
    45  	podmanClient podman.Client,
    46  	stateClient state.Client,
    47  	preferenceClient preference.Client,
    48  ) openapi.DefaultApiServicer {
    49  	return &DefaultApiService{
    50  		cancel:           cancel,
    51  		pushWatcher:      pushWatcher,
    52  		kubeClient:       kubeClient,
    53  		podmanClient:     podmanClient,
    54  		stateClient:      stateClient,
    55  		preferenceClient: preferenceClient,
    56  
    57  		devfileState: devstate.NewDevfileState(),
    58  	}
    59  }
    60  
    61  // ComponentCommandPost -
    62  func (s *DefaultApiService) ComponentCommandPost(ctx context.Context, componentCommandPostRequest openapi.ComponentCommandPostRequest) (openapi.ImplResponse, error) {
    63  	switch componentCommandPostRequest.Name {
    64  	case "push":
    65  		select {
    66  		case s.pushWatcher <- struct{}{}:
    67  			return openapi.Response(http.StatusOK, openapi.GeneralSuccess{
    68  				Message: "push was successfully executed",
    69  			}), nil
    70  		default:
    71  			return openapi.Response(http.StatusTooManyRequests, openapi.GeneralError{
    72  				Message: "a push operation is not possible at this time. Please retry later",
    73  			}), nil
    74  		}
    75  
    76  	default:
    77  		return openapi.Response(http.StatusBadRequest, openapi.GeneralError{
    78  			Message: fmt.Sprintf("command name %q not supported. Supported values are: %q", componentCommandPostRequest.Name, "push"),
    79  		}), nil
    80  	}
    81  }
    82  
    83  // ComponentGet -
    84  func (s *DefaultApiService) ComponentGet(ctx context.Context) (openapi.ImplResponse, error) {
    85  	value, _, err := describe.DescribeDevfileComponent(ctx, s.kubeClient, s.podmanClient, s.stateClient)
    86  	if err != nil {
    87  		return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
    88  			Message: fmt.Sprintf("error getting the description of the component: %s", err),
    89  		}), nil
    90  	}
    91  	return openapi.Response(http.StatusOK, value), nil
    92  }
    93  
    94  // InstanceDelete -
    95  func (s *DefaultApiService) InstanceDelete(ctx context.Context) (openapi.ImplResponse, error) {
    96  	s.cancel()
    97  	return openapi.Response(http.StatusOK, openapi.GeneralSuccess{
    98  		Message: fmt.Sprintf("'odo dev' instance with pid: %d is shutting down.", odocontext.GetPID(ctx)),
    99  	}), nil
   100  }
   101  
   102  // InstanceGet -
   103  func (s *DefaultApiService) InstanceGet(ctx context.Context) (openapi.ImplResponse, error) {
   104  	response := openapi.InstanceGet200Response{
   105  		Pid:                int32(odocontext.GetPID(ctx)),
   106  		ComponentDirectory: odocontext.GetWorkingDirectory(ctx),
   107  	}
   108  	return openapi.Response(http.StatusOK, response), nil
   109  }
   110  
   111  func (s *DefaultApiService) DevfileGet(ctx context.Context) (openapi.ImplResponse, error) {
   112  	devfilePath := odocontext.GetDevfilePath(ctx)
   113  	content, err := os.ReadFile(devfilePath)
   114  	if err != nil {
   115  		return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
   116  			Message: fmt.Sprintf("error getting Devfile content: %s", err),
   117  		}), nil
   118  	}
   119  	return openapi.Response(http.StatusOK, openapi.DevfileGet200Response{
   120  		Content: string(content),
   121  	}), nil
   122  
   123  }
   124  
   125  func (s *DefaultApiService) DevfilePut(ctx context.Context, params openapi.DevfilePutRequest) (openapi.ImplResponse, error) {
   126  
   127  	tmpdir, err := func() (string, error) {
   128  		dir, err := os.MkdirTemp("", "odo")
   129  		if err != nil {
   130  			return "", err
   131  		}
   132  		return dir, os.WriteFile(filepath.Join(dir, "devfile.yaml"), []byte(params.Content), 0600)
   133  	}()
   134  	defer func() {
   135  		if tmpdir != "" {
   136  			err = os.RemoveAll(tmpdir)
   137  			if err != nil {
   138  				klog.V(1).Infof("Error deleting temp directory %q: %s", tmpdir, err)
   139  			}
   140  		}
   141  	}()
   142  	if err != nil {
   143  		return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
   144  			Message: fmt.Sprintf("error saving temp Devfile: %s", err),
   145  		}), nil
   146  	}
   147  
   148  	err = s.validateDevfile(ctx, tmpdir)
   149  	if err != nil {
   150  		return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
   151  			Message: fmt.Sprintf("error validating Devfile: %s", err),
   152  		}), nil
   153  	}
   154  
   155  	devfilePath := odocontext.GetDevfilePath(ctx)
   156  	err = os.WriteFile(devfilePath, []byte(params.Content), 0600)
   157  	if err != nil {
   158  		return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
   159  			Message: fmt.Sprintf("error writing Devfile content to %q: %s", devfilePath, err),
   160  		}), nil
   161  	}
   162  
   163  	return openapi.Response(http.StatusOK, openapi.GeneralSuccess{
   164  		Message: "devfile has been successfully written to disk",
   165  	}), nil
   166  
   167  }
   168  
   169  func (s *DefaultApiService) validateDevfile(ctx context.Context, dir string) error {
   170  	var (
   171  		variables     = fcontext.GetVariables(ctx)
   172  		imageRegistry = s.preferenceClient.GetImageRegistry()
   173  	)
   174  	devObj, err := devfile.ParseAndValidateFromFileWithVariables(dir, variables, imageRegistry, false)
   175  	if err != nil {
   176  		return fmt.Errorf("failed to parse the devfile: %w", err)
   177  	}
   178  	return validate.ValidateDevfileData(devObj.Data)
   179  }
   180  
   181  func (s *DefaultApiService) TelemetryGet(ctx context.Context) (openapi.ImplResponse, error) {
   182  	var (
   183  		enabled = scontext.GetTelemetryStatus(ctx)
   184  		apikey  string
   185  		userid  string
   186  	)
   187  	if enabled {
   188  		apikey = segment.GetApikey()
   189  		var err error
   190  		userid, err = segment.GetUserIdentity(segment.GetTelemetryFilePath())
   191  		if err != nil {
   192  			return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
   193  				Message: fmt.Sprintf("error getting telemetry data: %s", err),
   194  			}), nil
   195  		}
   196  	}
   197  
   198  	return openapi.Response(http.StatusOK, openapi.TelemetryResponse{
   199  		Enabled: enabled,
   200  		Apikey:  apikey,
   201  		Userid:  userid,
   202  	}), nil
   203  }
   204  

View as plain text