mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
Add /devfile PUT and GET endpoints (#6950)
* Serve /devfile * Implement /devfile endpoints * Load/Save devfile from UI * Required metadata fields in the response * Add an Apply button on 1st tab * Fix: validate new devfile, not previous one * Add generated UI files to gitattributes file * Fix rebase
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -12,3 +12,4 @@ pkg/apiserver-gen/**/* linguist-generated=true
|
||||
pkg/**/mock.go linguist-generated=true
|
||||
pkg/**/mock_Backend.go linguist-generated=true
|
||||
pkg/**/mock_Client.go linguist-generated=true
|
||||
ui/src/app/api-gen/**/* linguist-generated=true
|
||||
|
||||
@@ -223,6 +223,59 @@ paths:
|
||||
example:
|
||||
message: "a push operation is not possible at this time. Please retry later"
|
||||
|
||||
/devfile:
|
||||
put:
|
||||
description: Updates the Devfile used by the current dev session
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/DevfilePutRequest"
|
||||
responses:
|
||||
'200':
|
||||
description: Devfile content was successfully updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GeneralSuccess'
|
||||
example:
|
||||
message: "The Devfile content has been updated successfully"
|
||||
|
||||
'500':
|
||||
description: Error updating the Devfile content
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GeneralError'
|
||||
example:
|
||||
message: "Error updating the Devfile content"
|
||||
|
||||
get:
|
||||
description: Get the raw content of the Devfile used by the current dev session
|
||||
responses:
|
||||
'200':
|
||||
description: Devfile content was successfully returned
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
example:
|
||||
{
|
||||
"content": "schemaVersion: 2.2.0\n",
|
||||
}
|
||||
'500':
|
||||
description: Error getting the Devfile content
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GeneralError'
|
||||
example:
|
||||
message: "Error getting the Devfile content"
|
||||
|
||||
|
||||
/devstate/devfile:
|
||||
put:
|
||||
description: Updates the complete Devfile content
|
||||
@@ -230,12 +283,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- content
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
$ref: "#/components/schemas/DevstateDevfilePutRequest"
|
||||
responses:
|
||||
'200':
|
||||
description: Devfile content was successfully updated
|
||||
@@ -382,7 +430,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Metadata'
|
||||
$ref: '#/components/schemas/MetadataRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: metadata was successfully updated
|
||||
@@ -1176,6 +1224,20 @@ components:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
DevfilePutRequest:
|
||||
type: object
|
||||
required:
|
||||
- content
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
DevstateDevfilePutRequest:
|
||||
type: object
|
||||
required:
|
||||
- content
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
DevfileContent:
|
||||
type: object
|
||||
required:
|
||||
@@ -1361,6 +1423,49 @@ components:
|
||||
items:
|
||||
type: string
|
||||
Metadata:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- version
|
||||
- displayName
|
||||
- description
|
||||
- tags
|
||||
- architectures
|
||||
- icon
|
||||
- globalMemoryLimit
|
||||
- projectType
|
||||
- language
|
||||
- website
|
||||
- provider
|
||||
- supportUrl
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
tags:
|
||||
type: string
|
||||
architectures:
|
||||
type: string
|
||||
icon:
|
||||
type: string
|
||||
globalMemoryLimit:
|
||||
type: string
|
||||
projectType:
|
||||
type: string
|
||||
language:
|
||||
type: string
|
||||
website:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
supportUrl:
|
||||
type: string
|
||||
MetadataRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
|
||||
5
pkg/apiserver-gen/.openapi-generator/FILES
generated
5
pkg/apiserver-gen/.openapi-generator/FILES
generated
@@ -8,13 +8,13 @@ go/impl.go
|
||||
go/logger.go
|
||||
go/model__component_command_post_request.go
|
||||
go/model__component_get_200_response.go
|
||||
go/model__devfile_get_200_response.go
|
||||
go/model__devstate_apply_command_post_request.go
|
||||
go/model__devstate_chart_get_200_response.go
|
||||
go/model__devstate_command__command_name__move_post_request.go
|
||||
go/model__devstate_command__command_name__set_default_post_request.go
|
||||
go/model__devstate_composite_command_post_request.go
|
||||
go/model__devstate_container_post_request.go
|
||||
go/model__devstate_devfile_put_request.go
|
||||
go/model__devstate_events_put_request.go
|
||||
go/model__devstate_exec_command_post_request.go
|
||||
go/model__devstate_image_post_request.go
|
||||
@@ -26,6 +26,8 @@ go/model_command.go
|
||||
go/model_composite_command.go
|
||||
go/model_container.go
|
||||
go/model_devfile_content.go
|
||||
go/model_devfile_put_request.go
|
||||
go/model_devstate_devfile_put_request.go
|
||||
go/model_events.go
|
||||
go/model_exec_command.go
|
||||
go/model_general_error.go
|
||||
@@ -33,5 +35,6 @@ go/model_general_success.go
|
||||
go/model_image.go
|
||||
go/model_image_command.go
|
||||
go/model_metadata.go
|
||||
go/model_metadata_request.go
|
||||
go/model_resource.go
|
||||
go/routers.go
|
||||
|
||||
6
pkg/apiserver-gen/go/api.go
generated
6
pkg/apiserver-gen/go/api.go
generated
@@ -20,6 +20,8 @@ import (
|
||||
type DefaultApiRouter interface {
|
||||
ComponentCommandPost(http.ResponseWriter, *http.Request)
|
||||
ComponentGet(http.ResponseWriter, *http.Request)
|
||||
DevfileGet(http.ResponseWriter, *http.Request)
|
||||
DevfilePut(http.ResponseWriter, *http.Request)
|
||||
DevstateApplyCommandPost(http.ResponseWriter, *http.Request)
|
||||
DevstateChartGet(http.ResponseWriter, *http.Request)
|
||||
DevstateCommandCommandNameDelete(http.ResponseWriter, *http.Request)
|
||||
@@ -51,6 +53,8 @@ type DefaultApiRouter interface {
|
||||
type DefaultApiServicer interface {
|
||||
ComponentCommandPost(context.Context, ComponentCommandPostRequest) (ImplResponse, error)
|
||||
ComponentGet(context.Context) (ImplResponse, error)
|
||||
DevfileGet(context.Context) (ImplResponse, error)
|
||||
DevfilePut(context.Context, DevfilePutRequest) (ImplResponse, error)
|
||||
DevstateApplyCommandPost(context.Context, DevstateApplyCommandPostRequest) (ImplResponse, error)
|
||||
DevstateChartGet(context.Context) (ImplResponse, error)
|
||||
DevstateCommandCommandNameDelete(context.Context, string) (ImplResponse, error)
|
||||
@@ -67,7 +71,7 @@ type DefaultApiServicer interface {
|
||||
DevstateExecCommandPost(context.Context, DevstateExecCommandPostRequest) (ImplResponse, error)
|
||||
DevstateImageImageNameDelete(context.Context, string) (ImplResponse, error)
|
||||
DevstateImagePost(context.Context, DevstateImagePostRequest) (ImplResponse, error)
|
||||
DevstateMetadataPut(context.Context, Metadata) (ImplResponse, error)
|
||||
DevstateMetadataPut(context.Context, MetadataRequest) (ImplResponse, error)
|
||||
DevstateQuantityValidPost(context.Context, DevstateQuantityValidPostRequest) (ImplResponse, error)
|
||||
DevstateResourcePost(context.Context, DevstateResourcePostRequest) (ImplResponse, error)
|
||||
DevstateResourceResourceNameDelete(context.Context, string) (ImplResponse, error)
|
||||
|
||||
57
pkg/apiserver-gen/go/api_default.go
generated
57
pkg/apiserver-gen/go/api_default.go
generated
@@ -62,6 +62,18 @@ func (c *DefaultApiController) Routes() Routes {
|
||||
"/api/v1/component",
|
||||
c.ComponentGet,
|
||||
},
|
||||
{
|
||||
"DevfileGet",
|
||||
strings.ToUpper("Get"),
|
||||
"/api/v1/devfile",
|
||||
c.DevfileGet,
|
||||
},
|
||||
{
|
||||
"DevfilePut",
|
||||
strings.ToUpper("Put"),
|
||||
"/api/v1/devfile",
|
||||
c.DevfilePut,
|
||||
},
|
||||
{
|
||||
"DevstateApplyCommandPost",
|
||||
strings.ToUpper("Post"),
|
||||
@@ -234,6 +246,43 @@ func (c *DefaultApiController) ComponentGet(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
}
|
||||
|
||||
// DevfileGet -
|
||||
func (c *DefaultApiController) DevfileGet(w http.ResponseWriter, r *http.Request) {
|
||||
result, err := c.service.DevfileGet(r.Context())
|
||||
// If an error occurred, encode the error with the status code
|
||||
if err != nil {
|
||||
c.errorHandler(w, r, err, &result)
|
||||
return
|
||||
}
|
||||
// If no error, encode the body and the result code
|
||||
EncodeJSONResponse(result.Body, &result.Code, w)
|
||||
|
||||
}
|
||||
|
||||
// DevfilePut -
|
||||
func (c *DefaultApiController) DevfilePut(w http.ResponseWriter, r *http.Request) {
|
||||
devfilePutRequestParam := DevfilePutRequest{}
|
||||
d := json.NewDecoder(r.Body)
|
||||
d.DisallowUnknownFields()
|
||||
if err := d.Decode(&devfilePutRequestParam); err != nil {
|
||||
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
|
||||
return
|
||||
}
|
||||
if err := AssertDevfilePutRequestRequired(devfilePutRequestParam); err != nil {
|
||||
c.errorHandler(w, r, err, nil)
|
||||
return
|
||||
}
|
||||
result, err := c.service.DevfilePut(r.Context(), devfilePutRequestParam)
|
||||
// If an error occurred, encode the error with the status code
|
||||
if err != nil {
|
||||
c.errorHandler(w, r, err, &result)
|
||||
return
|
||||
}
|
||||
// If no error, encode the body and the result code
|
||||
EncodeJSONResponse(result.Body, &result.Code, w)
|
||||
|
||||
}
|
||||
|
||||
// DevstateApplyCommandPost -
|
||||
func (c *DefaultApiController) DevstateApplyCommandPost(w http.ResponseWriter, r *http.Request) {
|
||||
devstateApplyCommandPostRequestParam := DevstateApplyCommandPostRequest{}
|
||||
@@ -555,18 +604,18 @@ func (c *DefaultApiController) DevstateImagePost(w http.ResponseWriter, r *http.
|
||||
|
||||
// DevstateMetadataPut -
|
||||
func (c *DefaultApiController) DevstateMetadataPut(w http.ResponseWriter, r *http.Request) {
|
||||
metadataParam := Metadata{}
|
||||
metadataRequestParam := MetadataRequest{}
|
||||
d := json.NewDecoder(r.Body)
|
||||
d.DisallowUnknownFields()
|
||||
if err := d.Decode(&metadataParam); err != nil {
|
||||
if err := d.Decode(&metadataRequestParam); err != nil {
|
||||
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
|
||||
return
|
||||
}
|
||||
if err := AssertMetadataRequired(metadataParam); err != nil {
|
||||
if err := AssertMetadataRequestRequired(metadataRequestParam); err != nil {
|
||||
c.errorHandler(w, r, err, nil)
|
||||
return
|
||||
}
|
||||
result, err := c.service.DevstateMetadataPut(r.Context(), metadataParam)
|
||||
result, err := c.service.DevstateMetadataPut(r.Context(), metadataRequestParam)
|
||||
// If an error occurred, encode the error with the status code
|
||||
if err != nil {
|
||||
c.errorHandler(w, r, err, &result)
|
||||
|
||||
31
pkg/apiserver-gen/go/model__devfile_get_200_response.go
generated
Normal file
31
pkg/apiserver-gen/go/model__devfile_get_200_response.go
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* odo dev
|
||||
*
|
||||
* API interface for 'odo dev'
|
||||
*
|
||||
* API version: 0.1
|
||||
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||
*/
|
||||
|
||||
package openapi
|
||||
|
||||
type DevfileGet200Response struct {
|
||||
Content string `json:"content,omitempty"`
|
||||
}
|
||||
|
||||
// AssertDevfileGet200ResponseRequired checks if the required fields are not zero-ed
|
||||
func AssertDevfileGet200ResponseRequired(obj DevfileGet200Response) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseDevfileGet200ResponseRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of DevfileGet200Response (e.g. [][]DevfileGet200Response), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseDevfileGet200ResponseRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aDevfileGet200Response, ok := obj.(DevfileGet200Response)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertDevfileGet200ResponseRequired(aDevfileGet200Response)
|
||||
})
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* odo dev
|
||||
*
|
||||
* API interface for 'odo dev'
|
||||
*
|
||||
* API version: 0.1
|
||||
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||
*/
|
||||
|
||||
package openapi
|
||||
|
||||
type DevstateContainerPost200Response struct {
|
||||
|
||||
// Content of the Devfile
|
||||
Component map[string]interface{} `json:"component,omitempty"`
|
||||
}
|
||||
|
||||
// AssertDevstateContainerPost200ResponseRequired checks if the required fields are not zero-ed
|
||||
func AssertDevstateContainerPost200ResponseRequired(obj DevstateContainerPost200Response) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseDevstateContainerPost200ResponseRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of DevstateContainerPost200Response (e.g. [][]DevstateContainerPost200Response), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseDevstateContainerPost200ResponseRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aDevstateContainerPost200Response, ok := obj.(DevstateContainerPost200Response)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertDevstateContainerPost200ResponseRequired(aDevstateContainerPost200Response)
|
||||
})
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* odo dev
|
||||
*
|
||||
* API interface for 'odo dev'
|
||||
*
|
||||
* API version: 0.1
|
||||
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||
*/
|
||||
|
||||
package openapi
|
||||
|
||||
type DevstateMetadataPut200Response struct {
|
||||
|
||||
// Content of the Devfile
|
||||
Component map[string]interface{} `json:"component,omitempty"`
|
||||
}
|
||||
|
||||
// AssertDevstateMetadataPut200ResponseRequired checks if the required fields are not zero-ed
|
||||
func AssertDevstateMetadataPut200ResponseRequired(obj DevstateMetadataPut200Response) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseDevstateMetadataPut200ResponseRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of DevstateMetadataPut200Response (e.g. [][]DevstateMetadataPut200Response), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseDevstateMetadataPut200ResponseRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aDevstateMetadataPut200Response, ok := obj.(DevstateMetadataPut200Response)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertDevstateMetadataPut200ResponseRequired(aDevstateMetadataPut200Response)
|
||||
})
|
||||
}
|
||||
40
pkg/apiserver-gen/go/model_devfile_put_request.go
generated
Normal file
40
pkg/apiserver-gen/go/model_devfile_put_request.go
generated
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* odo dev
|
||||
*
|
||||
* API interface for 'odo dev'
|
||||
*
|
||||
* API version: 0.1
|
||||
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||
*/
|
||||
|
||||
package openapi
|
||||
|
||||
type DevfilePutRequest struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// AssertDevfilePutRequestRequired checks if the required fields are not zero-ed
|
||||
func AssertDevfilePutRequestRequired(obj DevfilePutRequest) error {
|
||||
elements := map[string]interface{}{
|
||||
"content": obj.Content,
|
||||
}
|
||||
for name, el := range elements {
|
||||
if isZero := IsZeroValue(el); isZero {
|
||||
return &RequiredError{Field: name}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseDevfilePutRequestRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of DevfilePutRequest (e.g. [][]DevfilePutRequest), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseDevfilePutRequestRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aDevfilePutRequest, ok := obj.(DevfilePutRequest)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertDevfilePutRequestRequired(aDevfilePutRequest)
|
||||
})
|
||||
}
|
||||
47
pkg/apiserver-gen/go/model_metadata.go
generated
47
pkg/apiserver-gen/go/model_metadata.go
generated
@@ -10,35 +10,56 @@
|
||||
package openapi
|
||||
|
||||
type Metadata struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Name string `json:"name"`
|
||||
|
||||
Version string `json:"version,omitempty"`
|
||||
Version string `json:"version"`
|
||||
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
DisplayName string `json:"displayName"`
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
Description string `json:"description"`
|
||||
|
||||
Tags string `json:"tags,omitempty"`
|
||||
Tags string `json:"tags"`
|
||||
|
||||
Architectures string `json:"architectures,omitempty"`
|
||||
Architectures string `json:"architectures"`
|
||||
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Icon string `json:"icon"`
|
||||
|
||||
GlobalMemoryLimit string `json:"globalMemoryLimit,omitempty"`
|
||||
GlobalMemoryLimit string `json:"globalMemoryLimit"`
|
||||
|
||||
ProjectType string `json:"projectType,omitempty"`
|
||||
ProjectType string `json:"projectType"`
|
||||
|
||||
Language string `json:"language,omitempty"`
|
||||
Language string `json:"language"`
|
||||
|
||||
Website string `json:"website,omitempty"`
|
||||
Website string `json:"website"`
|
||||
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Provider string `json:"provider"`
|
||||
|
||||
SupportUrl string `json:"supportUrl,omitempty"`
|
||||
SupportUrl string `json:"supportUrl"`
|
||||
}
|
||||
|
||||
// AssertMetadataRequired checks if the required fields are not zero-ed
|
||||
func AssertMetadataRequired(obj Metadata) error {
|
||||
elements := map[string]interface{}{
|
||||
"name": obj.Name,
|
||||
"version": obj.Version,
|
||||
"displayName": obj.DisplayName,
|
||||
"description": obj.Description,
|
||||
"tags": obj.Tags,
|
||||
"architectures": obj.Architectures,
|
||||
"icon": obj.Icon,
|
||||
"globalMemoryLimit": obj.GlobalMemoryLimit,
|
||||
"projectType": obj.ProjectType,
|
||||
"language": obj.Language,
|
||||
"website": obj.Website,
|
||||
"provider": obj.Provider,
|
||||
"supportUrl": obj.SupportUrl,
|
||||
}
|
||||
for name, el := range elements {
|
||||
if isZero := IsZeroValue(el); isZero {
|
||||
return &RequiredError{Field: name}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
package openapi
|
||||
|
||||
type DevstateMetadataPutRequest struct {
|
||||
type MetadataRequest struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
Version string `json:"version,omitempty"`
|
||||
@@ -37,19 +37,19 @@ type DevstateMetadataPutRequest struct {
|
||||
SupportUrl string `json:"supportUrl,omitempty"`
|
||||
}
|
||||
|
||||
// AssertDevstateMetadataPutRequestRequired checks if the required fields are not zero-ed
|
||||
func AssertDevstateMetadataPutRequestRequired(obj DevstateMetadataPutRequest) error {
|
||||
// AssertMetadataRequestRequired checks if the required fields are not zero-ed
|
||||
func AssertMetadataRequestRequired(obj MetadataRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseDevstateMetadataPutRequestRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of DevstateMetadataPutRequest (e.g. [][]DevstateMetadataPutRequest), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseDevstateMetadataPutRequestRequired(objSlice interface{}) error {
|
||||
// AssertRecurseMetadataRequestRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of MetadataRequest (e.g. [][]MetadataRequest), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseMetadataRequestRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aDevstateMetadataPutRequest, ok := obj.(DevstateMetadataPutRequest)
|
||||
aMetadataRequest, ok := obj.(MetadataRequest)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertDevstateMetadataPutRequestRequired(aDevstateMetadataPutRequest)
|
||||
return AssertMetadataRequestRequired(aMetadataRequest)
|
||||
})
|
||||
}
|
||||
@@ -4,25 +4,33 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
openapi "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
|
||||
"github.com/redhat-developer/odo/pkg/apiserver-impl/devstate"
|
||||
"github.com/redhat-developer/odo/pkg/component/describe"
|
||||
"github.com/redhat-developer/odo/pkg/devfile"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/validate"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
fcontext "github.com/redhat-developer/odo/pkg/odo/commonflags/context"
|
||||
odocontext "github.com/redhat-developer/odo/pkg/odo/context"
|
||||
"github.com/redhat-developer/odo/pkg/podman"
|
||||
"github.com/redhat-developer/odo/pkg/preference"
|
||||
"github.com/redhat-developer/odo/pkg/state"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// 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
|
||||
cancel context.CancelFunc
|
||||
pushWatcher chan<- struct{}
|
||||
kubeClient kclient.ClientInterface
|
||||
podmanClient podman.Client
|
||||
stateClient state.Client
|
||||
preferenceClient preference.Client
|
||||
|
||||
devfileState devstate.DevfileState
|
||||
}
|
||||
@@ -34,13 +42,15 @@ func NewDefaultApiService(
|
||||
kubeClient kclient.ClientInterface,
|
||||
podmanClient podman.Client,
|
||||
stateClient state.Client,
|
||||
preferenceClient preference.Client,
|
||||
) openapi.DefaultApiServicer {
|
||||
return &DefaultApiService{
|
||||
cancel: cancel,
|
||||
pushWatcher: pushWatcher,
|
||||
kubeClient: kubeClient,
|
||||
podmanClient: podmanClient,
|
||||
stateClient: stateClient,
|
||||
cancel: cancel,
|
||||
pushWatcher: pushWatcher,
|
||||
kubeClient: kubeClient,
|
||||
podmanClient: podmanClient,
|
||||
stateClient: stateClient,
|
||||
preferenceClient: preferenceClient,
|
||||
|
||||
devfileState: devstate.NewDevfileState(),
|
||||
}
|
||||
@@ -95,3 +105,73 @@ func (s *DefaultApiService) InstanceGet(ctx context.Context) (openapi.ImplRespon
|
||||
}
|
||||
return openapi.Response(http.StatusOK, response), nil
|
||||
}
|
||||
|
||||
func (s *DefaultApiService) DevfileGet(ctx context.Context) (openapi.ImplResponse, error) {
|
||||
devfilePath := odocontext.GetDevfilePath(ctx)
|
||||
content, err := os.ReadFile(devfilePath)
|
||||
if err != nil {
|
||||
return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
|
||||
Message: fmt.Sprintf("error getting Devfile content: %s", err),
|
||||
}), nil
|
||||
}
|
||||
return openapi.Response(http.StatusOK, openapi.DevfileGet200Response{
|
||||
Content: string(content),
|
||||
}), nil
|
||||
|
||||
}
|
||||
|
||||
func (s *DefaultApiService) DevfilePut(ctx context.Context, params openapi.DevfilePutRequest) (openapi.ImplResponse, error) {
|
||||
|
||||
tmpdir, err := func() (string, error) {
|
||||
dir, err := os.MkdirTemp("", "odo")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return dir, os.WriteFile(filepath.Join(dir, "devfile.yaml"), []byte(params.Content), 0600)
|
||||
}()
|
||||
defer func() {
|
||||
if tmpdir != "" {
|
||||
err = os.RemoveAll(tmpdir)
|
||||
if err != nil {
|
||||
klog.V(1).Infof("Error deleting temp directory %q: %s", tmpdir, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
|
||||
Message: fmt.Sprintf("error saving temp Devfile: %s", err),
|
||||
}), nil
|
||||
}
|
||||
|
||||
err = s.validateDevfile(ctx, tmpdir)
|
||||
if err != nil {
|
||||
return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
|
||||
Message: fmt.Sprintf("error validating Devfile: %s", err),
|
||||
}), nil
|
||||
}
|
||||
|
||||
devfilePath := odocontext.GetDevfilePath(ctx)
|
||||
err = os.WriteFile(devfilePath, []byte(params.Content), 0600)
|
||||
if err != nil {
|
||||
return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
|
||||
Message: fmt.Sprintf("error writing Devfile content to %q: %s", devfilePath, err),
|
||||
}), nil
|
||||
}
|
||||
|
||||
return openapi.Response(http.StatusOK, openapi.GeneralSuccess{
|
||||
Message: "devfile has been successfully written to disk",
|
||||
}), nil
|
||||
|
||||
}
|
||||
|
||||
func (s *DefaultApiService) validateDevfile(ctx context.Context, dir string) error {
|
||||
var (
|
||||
variables = fcontext.GetVariables(ctx)
|
||||
imageRegistry = s.preferenceClient.GetImageRegistry()
|
||||
)
|
||||
devObj, err := devfile.ParseAndValidateFromFileWithVariables(dir, variables, imageRegistry, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse the devfile: %w", err)
|
||||
}
|
||||
return validate.ValidateDevfileData(devObj.Data)
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ func (s *DefaultApiService) DevstateExecCommandPost(ctx context.Context, command
|
||||
return openapi.Response(http.StatusOK, newContent), nil
|
||||
}
|
||||
|
||||
func (s *DefaultApiService) DevstateMetadataPut(ctx context.Context, metadata openapi.Metadata) (openapi.ImplResponse, error) {
|
||||
func (s *DefaultApiService) DevstateMetadataPut(ctx context.Context, metadata openapi.MetadataRequest) (openapi.ImplResponse, error) {
|
||||
newContent, err := s.devfileState.SetMetadata(
|
||||
metadata.Name,
|
||||
metadata.Version,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
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/preference"
|
||||
"github.com/redhat-developer/odo/pkg/state"
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
"k8s.io/klog"
|
||||
@@ -25,6 +26,7 @@ func StartServer(
|
||||
kubernetesClient kclient.ClientInterface,
|
||||
podmanClient podman.Client,
|
||||
stateClient state.Client,
|
||||
preferenceClient preference.Client,
|
||||
) ApiServer {
|
||||
|
||||
pushWatcher := make(chan struct{})
|
||||
@@ -34,6 +36,7 @@ func StartServer(
|
||||
kubernetesClient,
|
||||
podmanClient,
|
||||
stateClient,
|
||||
preferenceClient,
|
||||
)
|
||||
defaultApiController := openapi.NewDefaultApiController(defaultApiService)
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ func (o *ApiServerOptions) Run(ctx context.Context) (err error) {
|
||||
nil,
|
||||
nil,
|
||||
o.clientset.StateClient,
|
||||
o.clientset.PreferenceClient,
|
||||
)
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
|
||||
@@ -267,6 +267,7 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
o.clientset.KubernetesClient,
|
||||
o.clientset.PodmanClient,
|
||||
o.clientset.StateClient,
|
||||
o.clientset.PreferenceClient,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
3
ui/src/app/api-gen/.openapi-generator/FILES
generated
3
ui/src/app/api-gen/.openapi-generator/FILES
generated
@@ -14,6 +14,8 @@ model/componentGet200Response.ts
|
||||
model/compositeCommand.ts
|
||||
model/container.ts
|
||||
model/devfileContent.ts
|
||||
model/devfileGet200Response.ts
|
||||
model/devfilePutRequest.ts
|
||||
model/devstateApplyCommandPostRequest.ts
|
||||
model/devstateChartGet200Response.ts
|
||||
model/devstateCommandCommandNameMovePostRequest.ts
|
||||
@@ -34,6 +36,7 @@ model/image.ts
|
||||
model/imageCommand.ts
|
||||
model/instanceGet200Response.ts
|
||||
model/metadata.ts
|
||||
model/metadataRequest.ts
|
||||
model/models.ts
|
||||
model/resource.ts
|
||||
param.ts
|
||||
|
||||
137
ui/src/app/api-gen/api/default.service.ts
generated
137
ui/src/app/api-gen/api/default.service.ts
generated
@@ -25,6 +25,10 @@ import { ComponentGet200Response } from '../model/componentGet200Response';
|
||||
// @ts-ignore
|
||||
import { DevfileContent } from '../model/devfileContent';
|
||||
// @ts-ignore
|
||||
import { DevfileGet200Response } from '../model/devfileGet200Response';
|
||||
// @ts-ignore
|
||||
import { DevfilePutRequest } from '../model/devfilePutRequest';
|
||||
// @ts-ignore
|
||||
import { DevstateApplyCommandPostRequest } from '../model/devstateApplyCommandPostRequest';
|
||||
// @ts-ignore
|
||||
import { DevstateChartGet200Response } from '../model/devstateChartGet200Response';
|
||||
@@ -55,7 +59,7 @@ import { GeneralSuccess } from '../model/generalSuccess';
|
||||
// @ts-ignore
|
||||
import { InstanceGet200Response } from '../model/instanceGet200Response';
|
||||
// @ts-ignore
|
||||
import { Metadata } from '../model/metadata';
|
||||
import { MetadataRequest } from '../model/metadataRequest';
|
||||
|
||||
// @ts-ignore
|
||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||
@@ -246,6 +250,125 @@ export class DefaultService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw content of the Devfile used by the current dev session
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public devfileGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<DevfileGet200Response>;
|
||||
public devfileGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<DevfileGet200Response>>;
|
||||
public devfileGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<DevfileGet200Response>>;
|
||||
public devfileGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' | 'blob' = 'json';
|
||||
if (localVarHttpHeaderAcceptSelected) {
|
||||
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
|
||||
responseType_ = 'json';
|
||||
} else {
|
||||
responseType_ = 'blob';
|
||||
}
|
||||
}
|
||||
|
||||
let localVarPath = `/devfile`;
|
||||
return this.httpClient.request<DevfileGet200Response>('get', `${this.configuration.basePath}${localVarPath}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Devfile used by the current dev session
|
||||
* @param devfilePutRequest
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public devfilePut(devfilePutRequest?: DevfilePutRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<GeneralSuccess>;
|
||||
public devfilePut(devfilePutRequest?: DevfilePutRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<GeneralSuccess>>;
|
||||
public devfilePut(devfilePutRequest?: DevfilePutRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<GeneralSuccess>>;
|
||||
public devfilePut(devfilePutRequest?: DevfilePutRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
// to determine the Content-Type header
|
||||
const consumes: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||
if (httpContentTypeSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
|
||||
}
|
||||
|
||||
let responseType_: 'text' | 'json' | 'blob' = 'json';
|
||||
if (localVarHttpHeaderAcceptSelected) {
|
||||
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
|
||||
responseType_ = 'json';
|
||||
} else {
|
||||
responseType_ = 'blob';
|
||||
}
|
||||
}
|
||||
|
||||
let localVarPath = `/devfile`;
|
||||
return this.httpClient.request<GeneralSuccess>('put', `${this.configuration.basePath}${localVarPath}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
body: devfilePutRequest,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Apply Command to the Devfile
|
||||
* @param devstateApplyCommandPostRequest
|
||||
@@ -1235,14 +1358,14 @@ export class DefaultService {
|
||||
|
||||
/**
|
||||
* Updates the metadata for the Devfile
|
||||
* @param metadata
|
||||
* @param metadataRequest
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public devstateMetadataPut(metadata?: Metadata, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<DevfileContent>;
|
||||
public devstateMetadataPut(metadata?: Metadata, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<DevfileContent>>;
|
||||
public devstateMetadataPut(metadata?: Metadata, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<DevfileContent>>;
|
||||
public devstateMetadataPut(metadata?: Metadata, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
public devstateMetadataPut(metadataRequest?: MetadataRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<DevfileContent>;
|
||||
public devstateMetadataPut(metadataRequest?: MetadataRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<DevfileContent>>;
|
||||
public devstateMetadataPut(metadataRequest?: MetadataRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<DevfileContent>>;
|
||||
public devstateMetadataPut(metadataRequest?: MetadataRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
@@ -1288,7 +1411,7 @@ export class DefaultService {
|
||||
return this.httpClient.request<DevfileContent>('put', `${this.configuration.basePath}${localVarPath}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
body: metadata,
|
||||
body: metadataRequest,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
|
||||
17
ui/src/app/api-gen/model/devfileGet200Response.ts
generated
Normal file
17
ui/src/app/api-gen/model/devfileGet200Response.ts
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* odo dev
|
||||
* API interface for \'odo dev\'
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface DevfileGet200Response {
|
||||
content?: string;
|
||||
}
|
||||
|
||||
17
ui/src/app/api-gen/model/devfilePutRequest.ts
generated
Normal file
17
ui/src/app/api-gen/model/devfilePutRequest.ts
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* odo dev
|
||||
* API interface for \'odo dev\'
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface DevfilePutRequest {
|
||||
content: string;
|
||||
}
|
||||
|
||||
26
ui/src/app/api-gen/model/metadata.ts
generated
26
ui/src/app/api-gen/model/metadata.ts
generated
@@ -12,18 +12,18 @@
|
||||
|
||||
|
||||
export interface Metadata {
|
||||
name?: string;
|
||||
version?: string;
|
||||
displayName?: string;
|
||||
description?: string;
|
||||
tags?: string;
|
||||
architectures?: string;
|
||||
icon?: string;
|
||||
globalMemoryLimit?: string;
|
||||
projectType?: string;
|
||||
language?: string;
|
||||
website?: string;
|
||||
provider?: string;
|
||||
supportUrl?: string;
|
||||
name: string;
|
||||
version: string;
|
||||
displayName: string;
|
||||
description: string;
|
||||
tags: string;
|
||||
architectures: string;
|
||||
icon: string;
|
||||
globalMemoryLimit: string;
|
||||
projectType: string;
|
||||
language: string;
|
||||
website: string;
|
||||
provider: string;
|
||||
supportUrl: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
|
||||
export interface DevstateMetadataPutRequest {
|
||||
export interface MetadataRequest {
|
||||
name?: string;
|
||||
version?: string;
|
||||
displayName?: string;
|
||||
3
ui/src/app/api-gen/model/models.ts
generated
3
ui/src/app/api-gen/model/models.ts
generated
@@ -5,6 +5,8 @@ export * from './componentGet200Response';
|
||||
export * from './compositeCommand';
|
||||
export * from './container';
|
||||
export * from './devfileContent';
|
||||
export * from './devfileGet200Response';
|
||||
export * from './devfilePutRequest';
|
||||
export * from './devstateApplyCommandPostRequest';
|
||||
export * from './devstateChartGet200Response';
|
||||
export * from './devstateCommandCommandNameMovePostRequest';
|
||||
@@ -25,4 +27,5 @@ export * from './image';
|
||||
export * from './imageCommand';
|
||||
export * from './instanceGet200Response';
|
||||
export * from './metadata';
|
||||
export * from './metadataRequest';
|
||||
export * from './resource';
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
<mat-label>Devfile YAML</mat-label>
|
||||
<textarea data-cy="yaml-input" matInput #input id="input" rows="20" [value]="devfileYaml"></textarea>
|
||||
</mat-form-field>
|
||||
<button data-cy="yaml-save" mat-flat-button color="primary" (click)="onButtonClick(input.value)">Save</button>
|
||||
<button data-cy="yaml-clear" mat-flat-button color="warn" (click)="clear()">Clear</button>
|
||||
<button data-cy="yaml-send" matTooltip="Save Devfile to disk" mat-flat-button color="primary" (click)="onButtonClick(input.value, true)">Save</button>
|
||||
<button data-cy="yaml-save" matTooltip="Apply changes to other tabs" mat-flat-button color="normal" (click)="onButtonClick(input.value, false)">Apply</button>
|
||||
<button data-cy="yaml-clear" matTooltip="Clear Devfile content" mat-flat-button color="normal" (click)="clear()">Clear</button>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { MermaidService } from './services/mermaid.service';
|
||||
import { StateService } from './services/state.service';
|
||||
import { MatIconRegistry } from "@angular/material/icon";
|
||||
import { OdoapiService } from './services/odoapi.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -20,6 +21,7 @@ export class AppComponent implements OnInit {
|
||||
protected sanitizer: DomSanitizer,
|
||||
private matIconRegistry: MatIconRegistry,
|
||||
private wasmGo: DevstateService,
|
||||
private odoApi: OdoapiService,
|
||||
private mermaid: MermaidService,
|
||||
private state: StateService,
|
||||
) {
|
||||
@@ -35,10 +37,12 @@ export class AppComponent implements OnInit {
|
||||
loading.style.visibility = "hidden";
|
||||
}
|
||||
|
||||
const devfile = this.wasmGo.getDevfileContent();
|
||||
const devfile = this.odoApi.getDevfile();
|
||||
devfile.subscribe({
|
||||
next: (devfile) => {
|
||||
this.onButtonClick(devfile.content);
|
||||
if (devfile.content != undefined) {
|
||||
this.onButtonClick(devfile.content, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -62,12 +66,20 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
onButtonClick(content: string){
|
||||
onButtonClick(content: string, save: boolean){
|
||||
const result = this.wasmGo.setDevfileContent(content);
|
||||
result.subscribe({
|
||||
next: (value) => {
|
||||
this.errorMessage = '';
|
||||
this.state.changeDevfileYaml(value);
|
||||
this.state.changeDevfileYaml(value);
|
||||
if (save) {
|
||||
this.odoApi.saveDevfile(value.content).subscribe({
|
||||
next: () => {},
|
||||
error: (error) => {
|
||||
this.errorMessage = error.error.message;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
this.errorMessage = error.error.message;
|
||||
@@ -79,7 +91,7 @@ export class AppComponent implements OnInit {
|
||||
if (confirm('You will delete the content of the Devfile. Continue?')) {
|
||||
this.wasmGo.clearDevfileContent().subscribe({
|
||||
next: (value) => {
|
||||
this.onButtonClick(value.content);
|
||||
this.onButtonClick(value.content, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,5 +64,5 @@
|
||||
</mat-form-field>
|
||||
</form>
|
||||
|
||||
<button [disabled]="form.invalid" mat-flat-button color="primary" (click)="onSave()">Save</button>
|
||||
<button [disabled]="form.invalid" mat-flat-button color="primary" (click)="onSave()">Apply</button>
|
||||
</div>
|
||||
|
||||
16
ui/src/app/services/odoapi.service.spec.ts
Normal file
16
ui/src/app/services/odoapi.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OdoapiService } from './odoapi.service';
|
||||
|
||||
describe('OdoapiService', () => {
|
||||
let service: OdoapiService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(OdoapiService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
24
ui/src/app/services/odoapi.service.ts
Normal file
24
ui/src/app/services/odoapi.service.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { DevfileGet200Response, GeneralSuccess } from '../api-gen';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class OdoapiService {
|
||||
|
||||
private base = "/api/v1";
|
||||
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getDevfile(): Observable<DevfileGet200Response> {
|
||||
return this.http.get<DevfileGet200Response>(this.base+"/devfile");
|
||||
}
|
||||
|
||||
saveDevfile(content: string): Observable<GeneralSuccess> {
|
||||
return this.http.put<GeneralSuccess>(this.base+"/devfile", {
|
||||
content: content
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user