diff --git a/.licenses/arduino-create-agent/go/go.bug.st/downloader/v2.dep.yml b/.licenses/arduino-create-agent/go/go.bug.st/downloader/v2.dep.yml deleted file mode 100644 index e255579fe..000000000 --- a/.licenses/arduino-create-agent/go/go.bug.st/downloader/v2.dep.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: go.bug.st/downloader/v2 -version: v2.1.1 -type: go -summary: -homepage: https://pkg.go.dev/go.bug.st/downloader/v2 -license: bsd-3-clause -licenses: -- sources: LICENSE - text: |2+ - - Copyright (c) 2018, Cristian Maglie. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -notices: [] diff --git a/design/pkgs.go b/design/pkgs.go index 300bc9058..b059e0ddf 100644 --- a/design/pkgs.go +++ b/design/pkgs.go @@ -17,41 +17,6 @@ package design import . "goa.design/goa/v3/dsl" -var _ = Service("indexes", func() { - Description("The indexes service manages the package_index files") - - Error("invalid_url", ErrorResult, "url invalid") - HTTP(func() { - Response("invalid_url", StatusBadRequest) - }) - - Method("list", func() { - Result(ArrayOf(String)) - HTTP(func() { - GET("/pkgs/indexes") - Response(StatusOK) - }) - }) - - Method("add", func() { - Payload(IndexPayload) - Result(Operation) - HTTP(func() { - POST("/pkgs/indexes/add") - Response(StatusOK) - }) - }) - - Method("remove", func() { - Payload(IndexPayload) - Result(Operation) - HTTP(func() { - POST("/pkgs/indexes/delete") - Response(StatusOK) - }) - }) -}) - var _ = Service("tools", func() { Description("The tools service manages the available and installed tools") @@ -95,15 +60,6 @@ var _ = Service("tools", func() { }) }) -var IndexPayload = Type("arduino.index", func() { - TypeName("IndexPayload") - - Attribute("url", String, "The url of the index file", func() { - Example("https://downloads.arduino.cc/packages/package_index.json") - }) - Required("url") -}) - var ToolPayload = Type("arduino.tool", func() { Description(`A tool is an executable program that can upload sketches. If url is absent the tool will be searched among the package index installed`) diff --git a/gen/http/cli/arduino_create_agent/cli.go b/gen/http/cli/arduino_create_agent/cli.go index e53f7fa91..50b7a8eb0 100644 --- a/gen/http/cli/arduino_create_agent/cli.go +++ b/gen/http/cli/arduino_create_agent/cli.go @@ -13,7 +13,6 @@ import ( "net/http" "os" - indexesc "github.com/arduino/arduino-create-agent/gen/http/indexes/client" toolsc "github.com/arduino/arduino-create-agent/gen/http/tools/client" goahttp "goa.design/goa/v3/http" goa "goa.design/goa/v3/pkg" @@ -23,15 +22,13 @@ import ( // // command (subcommand1|subcommand2|...) func UsageCommands() string { - return `indexes (list|add|remove) -tools (available|installed|install|remove) + return `tools (available|installed|install|remove) ` } // UsageExamples produces an example of a valid invocation of the CLI tool. func UsageExamples() string { - return os.Args[0] + ` indexes list` + "\n" + - os.Args[0] + ` tools available` + "\n" + + return os.Args[0] + ` tools available` + "\n" + "" } @@ -45,16 +42,6 @@ func ParseEndpoint( restore bool, ) (goa.Endpoint, any, error) { var ( - indexesFlags = flag.NewFlagSet("indexes", flag.ContinueOnError) - - indexesListFlags = flag.NewFlagSet("list", flag.ExitOnError) - - indexesAddFlags = flag.NewFlagSet("add", flag.ExitOnError) - indexesAddBodyFlag = indexesAddFlags.String("body", "REQUIRED", "") - - indexesRemoveFlags = flag.NewFlagSet("remove", flag.ExitOnError) - indexesRemoveBodyFlag = indexesRemoveFlags.String("body", "REQUIRED", "") - toolsFlags = flag.NewFlagSet("tools", flag.ContinueOnError) toolsAvailableFlags = flag.NewFlagSet("available", flag.ExitOnError) @@ -70,11 +57,6 @@ func ParseEndpoint( toolsRemoveNameFlag = toolsRemoveFlags.String("name", "REQUIRED", "The name of the tool") toolsRemoveVersionFlag = toolsRemoveFlags.String("version", "REQUIRED", "The version of the tool") ) - indexesFlags.Usage = indexesUsage - indexesListFlags.Usage = indexesListUsage - indexesAddFlags.Usage = indexesAddUsage - indexesRemoveFlags.Usage = indexesRemoveUsage - toolsFlags.Usage = toolsUsage toolsAvailableFlags.Usage = toolsAvailableUsage toolsInstalledFlags.Usage = toolsInstalledUsage @@ -96,8 +78,6 @@ func ParseEndpoint( { svcn = flag.Arg(0) switch svcn { - case "indexes": - svcf = indexesFlags case "tools": svcf = toolsFlags default: @@ -115,19 +95,6 @@ func ParseEndpoint( { epn = svcf.Arg(0) switch svcn { - case "indexes": - switch epn { - case "list": - epf = indexesListFlags - - case "add": - epf = indexesAddFlags - - case "remove": - epf = indexesRemoveFlags - - } - case "tools": switch epn { case "available": @@ -164,19 +131,6 @@ func ParseEndpoint( ) { switch svcn { - case "indexes": - c := indexesc.NewClient(scheme, host, doer, enc, dec, restore) - switch epn { - case "list": - endpoint = c.List() - data = nil - case "add": - endpoint = c.Add() - data, err = indexesc.BuildAddPayload(*indexesAddBodyFlag) - case "remove": - endpoint = c.Remove() - data, err = indexesc.BuildRemovePayload(*indexesRemoveBodyFlag) - } case "tools": c := toolsc.NewClient(scheme, host, doer, enc, dec, restore) switch epn { @@ -202,57 +156,6 @@ func ParseEndpoint( return endpoint, data, nil } -// indexesUsage displays the usage of the indexes command and its subcommands. -func indexesUsage() { - fmt.Fprintf(os.Stderr, `The indexes service manages the package_index files -Usage: - %[1]s [globalflags] indexes COMMAND [flags] - -COMMAND: - list: List implements list. - add: Add implements add. - remove: Remove implements remove. - -Additional help: - %[1]s indexes COMMAND --help -`, os.Args[0]) -} -func indexesListUsage() { - fmt.Fprintf(os.Stderr, `%[1]s [flags] indexes list - -List implements list. - -Example: - %[1]s indexes list -`, os.Args[0]) -} - -func indexesAddUsage() { - fmt.Fprintf(os.Stderr, `%[1]s [flags] indexes add -body JSON - -Add implements add. - -body JSON: - -Example: - %[1]s indexes add --body '{ - "url": "https://downloads.arduino.cc/packages/package_index.json" - }' -`, os.Args[0]) -} - -func indexesRemoveUsage() { - fmt.Fprintf(os.Stderr, `%[1]s [flags] indexes remove -body JSON - -Remove implements remove. - -body JSON: - -Example: - %[1]s indexes remove --body '{ - "url": "https://downloads.arduino.cc/packages/package_index.json" - }' -`, os.Args[0]) -} - // toolsUsage displays the usage of the tools command and its subcommands. func toolsUsage() { fmt.Fprintf(os.Stderr, `The tools service manages the available and installed tools diff --git a/gen/http/indexes/client/cli.go b/gen/http/indexes/client/cli.go deleted file mode 100644 index f1808ebed..000000000 --- a/gen/http/indexes/client/cli.go +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes HTTP client CLI support package -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package client - -import ( - "encoding/json" - "fmt" - - indexes "github.com/arduino/arduino-create-agent/gen/indexes" -) - -// BuildAddPayload builds the payload for the indexes add endpoint from CLI -// flags. -func BuildAddPayload(indexesAddBody string) (*indexes.IndexPayload, error) { - var err error - var body AddRequestBody - { - err = json.Unmarshal([]byte(indexesAddBody), &body) - if err != nil { - return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"url\": \"https://downloads.arduino.cc/packages/package_index.json\"\n }'") - } - } - v := &indexes.IndexPayload{ - URL: body.URL, - } - - return v, nil -} - -// BuildRemovePayload builds the payload for the indexes remove endpoint from -// CLI flags. -func BuildRemovePayload(indexesRemoveBody string) (*indexes.IndexPayload, error) { - var err error - var body RemoveRequestBody - { - err = json.Unmarshal([]byte(indexesRemoveBody), &body) - if err != nil { - return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"url\": \"https://downloads.arduino.cc/packages/package_index.json\"\n }'") - } - } - v := &indexes.IndexPayload{ - URL: body.URL, - } - - return v, nil -} diff --git a/gen/http/indexes/client/client.go b/gen/http/indexes/client/client.go deleted file mode 100644 index 2ed037d2c..000000000 --- a/gen/http/indexes/client/client.go +++ /dev/null @@ -1,125 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes client HTTP transport -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package client - -import ( - "context" - "net/http" - - goahttp "goa.design/goa/v3/http" - goa "goa.design/goa/v3/pkg" -) - -// Client lists the indexes service endpoint HTTP clients. -type Client struct { - // List Doer is the HTTP client used to make requests to the list endpoint. - ListDoer goahttp.Doer - - // Add Doer is the HTTP client used to make requests to the add endpoint. - AddDoer goahttp.Doer - - // Remove Doer is the HTTP client used to make requests to the remove endpoint. - RemoveDoer goahttp.Doer - - // RestoreResponseBody controls whether the response bodies are reset after - // decoding so they can be read again. - RestoreResponseBody bool - - scheme string - host string - encoder func(*http.Request) goahttp.Encoder - decoder func(*http.Response) goahttp.Decoder -} - -// NewClient instantiates HTTP clients for all the indexes service servers. -func NewClient( - scheme string, - host string, - doer goahttp.Doer, - enc func(*http.Request) goahttp.Encoder, - dec func(*http.Response) goahttp.Decoder, - restoreBody bool, -) *Client { - return &Client{ - ListDoer: doer, - AddDoer: doer, - RemoveDoer: doer, - RestoreResponseBody: restoreBody, - scheme: scheme, - host: host, - decoder: dec, - encoder: enc, - } -} - -// List returns an endpoint that makes HTTP requests to the indexes service -// list server. -func (c *Client) List() goa.Endpoint { - var ( - decodeResponse = DecodeListResponse(c.decoder, c.RestoreResponseBody) - ) - return func(ctx context.Context, v any) (any, error) { - req, err := c.BuildListRequest(ctx, v) - if err != nil { - return nil, err - } - resp, err := c.ListDoer.Do(req) - if err != nil { - return nil, goahttp.ErrRequestError("indexes", "list", err) - } - return decodeResponse(resp) - } -} - -// Add returns an endpoint that makes HTTP requests to the indexes service add -// server. -func (c *Client) Add() goa.Endpoint { - var ( - encodeRequest = EncodeAddRequest(c.encoder) - decodeResponse = DecodeAddResponse(c.decoder, c.RestoreResponseBody) - ) - return func(ctx context.Context, v any) (any, error) { - req, err := c.BuildAddRequest(ctx, v) - if err != nil { - return nil, err - } - err = encodeRequest(req, v) - if err != nil { - return nil, err - } - resp, err := c.AddDoer.Do(req) - if err != nil { - return nil, goahttp.ErrRequestError("indexes", "add", err) - } - return decodeResponse(resp) - } -} - -// Remove returns an endpoint that makes HTTP requests to the indexes service -// remove server. -func (c *Client) Remove() goa.Endpoint { - var ( - encodeRequest = EncodeRemoveRequest(c.encoder) - decodeResponse = DecodeRemoveResponse(c.decoder, c.RestoreResponseBody) - ) - return func(ctx context.Context, v any) (any, error) { - req, err := c.BuildRemoveRequest(ctx, v) - if err != nil { - return nil, err - } - err = encodeRequest(req, v) - if err != nil { - return nil, err - } - resp, err := c.RemoveDoer.Do(req) - if err != nil { - return nil, goahttp.ErrRequestError("indexes", "remove", err) - } - return decodeResponse(resp) - } -} diff --git a/gen/http/indexes/client/encode_decode.go b/gen/http/indexes/client/encode_decode.go deleted file mode 100644 index ee011f60c..000000000 --- a/gen/http/indexes/client/encode_decode.go +++ /dev/null @@ -1,267 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes HTTP client encoders and decoders -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package client - -import ( - "bytes" - "context" - "io" - "net/http" - "net/url" - - indexes "github.com/arduino/arduino-create-agent/gen/indexes" - indexesviews "github.com/arduino/arduino-create-agent/gen/indexes/views" - goahttp "goa.design/goa/v3/http" -) - -// BuildListRequest instantiates a HTTP request object with method and path set -// to call the "indexes" service "list" endpoint -func (c *Client) BuildListRequest(ctx context.Context, v any) (*http.Request, error) { - u := &url.URL{Scheme: c.scheme, Host: c.host, Path: ListIndexesPath()} - req, err := http.NewRequest("GET", u.String(), nil) - if err != nil { - return nil, goahttp.ErrInvalidURL("indexes", "list", u.String(), err) - } - if ctx != nil { - req = req.WithContext(ctx) - } - - return req, nil -} - -// DecodeListResponse returns a decoder for responses returned by the indexes -// list endpoint. restoreBody controls whether the response body should be -// restored after having been read. -// DecodeListResponse may return the following errors: -// - "invalid_url" (type *goa.ServiceError): http.StatusBadRequest -// - error: internal error -func DecodeListResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { - return func(resp *http.Response) (any, error) { - if restoreBody { - b, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - resp.Body = io.NopCloser(bytes.NewBuffer(b)) - defer func() { - resp.Body = io.NopCloser(bytes.NewBuffer(b)) - }() - } else { - defer resp.Body.Close() - } - switch resp.StatusCode { - case http.StatusOK: - var ( - body []string - err error - ) - err = decoder(resp).Decode(&body) - if err != nil { - return nil, goahttp.ErrDecodingError("indexes", "list", err) - } - return body, nil - case http.StatusBadRequest: - var ( - body ListInvalidURLResponseBody - err error - ) - err = decoder(resp).Decode(&body) - if err != nil { - return nil, goahttp.ErrDecodingError("indexes", "list", err) - } - err = ValidateListInvalidURLResponseBody(&body) - if err != nil { - return nil, goahttp.ErrValidationError("indexes", "list", err) - } - return nil, NewListInvalidURL(&body) - default: - body, _ := io.ReadAll(resp.Body) - return nil, goahttp.ErrInvalidResponse("indexes", "list", resp.StatusCode, string(body)) - } - } -} - -// BuildAddRequest instantiates a HTTP request object with method and path set -// to call the "indexes" service "add" endpoint -func (c *Client) BuildAddRequest(ctx context.Context, v any) (*http.Request, error) { - u := &url.URL{Scheme: c.scheme, Host: c.host, Path: AddIndexesPath()} - req, err := http.NewRequest("POST", u.String(), nil) - if err != nil { - return nil, goahttp.ErrInvalidURL("indexes", "add", u.String(), err) - } - if ctx != nil { - req = req.WithContext(ctx) - } - - return req, nil -} - -// EncodeAddRequest returns an encoder for requests sent to the indexes add -// server. -func EncodeAddRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { - return func(req *http.Request, v any) error { - p, ok := v.(*indexes.IndexPayload) - if !ok { - return goahttp.ErrInvalidType("indexes", "add", "*indexes.IndexPayload", v) - } - body := NewAddRequestBody(p) - if err := encoder(req).Encode(&body); err != nil { - return goahttp.ErrEncodingError("indexes", "add", err) - } - return nil - } -} - -// DecodeAddResponse returns a decoder for responses returned by the indexes -// add endpoint. restoreBody controls whether the response body should be -// restored after having been read. -// DecodeAddResponse may return the following errors: -// - "invalid_url" (type *goa.ServiceError): http.StatusBadRequest -// - error: internal error -func DecodeAddResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { - return func(resp *http.Response) (any, error) { - if restoreBody { - b, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - resp.Body = io.NopCloser(bytes.NewBuffer(b)) - defer func() { - resp.Body = io.NopCloser(bytes.NewBuffer(b)) - }() - } else { - defer resp.Body.Close() - } - switch resp.StatusCode { - case http.StatusOK: - var ( - body AddResponseBody - err error - ) - err = decoder(resp).Decode(&body) - if err != nil { - return nil, goahttp.ErrDecodingError("indexes", "add", err) - } - p := NewAddOperationOK(&body) - view := "default" - vres := &indexesviews.Operation{Projected: p, View: view} - if err = indexesviews.ValidateOperation(vres); err != nil { - return nil, goahttp.ErrValidationError("indexes", "add", err) - } - res := indexes.NewOperation(vres) - return res, nil - case http.StatusBadRequest: - var ( - body AddInvalidURLResponseBody - err error - ) - err = decoder(resp).Decode(&body) - if err != nil { - return nil, goahttp.ErrDecodingError("indexes", "add", err) - } - err = ValidateAddInvalidURLResponseBody(&body) - if err != nil { - return nil, goahttp.ErrValidationError("indexes", "add", err) - } - return nil, NewAddInvalidURL(&body) - default: - body, _ := io.ReadAll(resp.Body) - return nil, goahttp.ErrInvalidResponse("indexes", "add", resp.StatusCode, string(body)) - } - } -} - -// BuildRemoveRequest instantiates a HTTP request object with method and path -// set to call the "indexes" service "remove" endpoint -func (c *Client) BuildRemoveRequest(ctx context.Context, v any) (*http.Request, error) { - u := &url.URL{Scheme: c.scheme, Host: c.host, Path: RemoveIndexesPath()} - req, err := http.NewRequest("POST", u.String(), nil) - if err != nil { - return nil, goahttp.ErrInvalidURL("indexes", "remove", u.String(), err) - } - if ctx != nil { - req = req.WithContext(ctx) - } - - return req, nil -} - -// EncodeRemoveRequest returns an encoder for requests sent to the indexes -// remove server. -func EncodeRemoveRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { - return func(req *http.Request, v any) error { - p, ok := v.(*indexes.IndexPayload) - if !ok { - return goahttp.ErrInvalidType("indexes", "remove", "*indexes.IndexPayload", v) - } - body := NewRemoveRequestBody(p) - if err := encoder(req).Encode(&body); err != nil { - return goahttp.ErrEncodingError("indexes", "remove", err) - } - return nil - } -} - -// DecodeRemoveResponse returns a decoder for responses returned by the indexes -// remove endpoint. restoreBody controls whether the response body should be -// restored after having been read. -// DecodeRemoveResponse may return the following errors: -// - "invalid_url" (type *goa.ServiceError): http.StatusBadRequest -// - error: internal error -func DecodeRemoveResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { - return func(resp *http.Response) (any, error) { - if restoreBody { - b, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - resp.Body = io.NopCloser(bytes.NewBuffer(b)) - defer func() { - resp.Body = io.NopCloser(bytes.NewBuffer(b)) - }() - } else { - defer resp.Body.Close() - } - switch resp.StatusCode { - case http.StatusOK: - var ( - body RemoveResponseBody - err error - ) - err = decoder(resp).Decode(&body) - if err != nil { - return nil, goahttp.ErrDecodingError("indexes", "remove", err) - } - p := NewRemoveOperationOK(&body) - view := "default" - vres := &indexesviews.Operation{Projected: p, View: view} - if err = indexesviews.ValidateOperation(vres); err != nil { - return nil, goahttp.ErrValidationError("indexes", "remove", err) - } - res := indexes.NewOperation(vres) - return res, nil - case http.StatusBadRequest: - var ( - body RemoveInvalidURLResponseBody - err error - ) - err = decoder(resp).Decode(&body) - if err != nil { - return nil, goahttp.ErrDecodingError("indexes", "remove", err) - } - err = ValidateRemoveInvalidURLResponseBody(&body) - if err != nil { - return nil, goahttp.ErrValidationError("indexes", "remove", err) - } - return nil, NewRemoveInvalidURL(&body) - default: - body, _ := io.ReadAll(resp.Body) - return nil, goahttp.ErrInvalidResponse("indexes", "remove", resp.StatusCode, string(body)) - } - } -} diff --git a/gen/http/indexes/client/paths.go b/gen/http/indexes/client/paths.go deleted file mode 100644 index 79236a06e..000000000 --- a/gen/http/indexes/client/paths.go +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// HTTP request path constructors for the indexes service. -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package client - -// ListIndexesPath returns the URL path to the indexes service list HTTP endpoint. -func ListIndexesPath() string { - return "/v2/pkgs/indexes" -} - -// AddIndexesPath returns the URL path to the indexes service add HTTP endpoint. -func AddIndexesPath() string { - return "/v2/pkgs/indexes/add" -} - -// RemoveIndexesPath returns the URL path to the indexes service remove HTTP endpoint. -func RemoveIndexesPath() string { - return "/v2/pkgs/indexes/delete" -} diff --git a/gen/http/indexes/client/types.go b/gen/http/indexes/client/types.go deleted file mode 100644 index 6194f0430..000000000 --- a/gen/http/indexes/client/types.go +++ /dev/null @@ -1,249 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes HTTP client types -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package client - -import ( - indexes "github.com/arduino/arduino-create-agent/gen/indexes" - indexesviews "github.com/arduino/arduino-create-agent/gen/indexes/views" - goa "goa.design/goa/v3/pkg" -) - -// AddRequestBody is the type of the "indexes" service "add" endpoint HTTP -// request body. -type AddRequestBody struct { - // The url of the index file - URL string `form:"url" json:"url" xml:"url"` -} - -// RemoveRequestBody is the type of the "indexes" service "remove" endpoint -// HTTP request body. -type RemoveRequestBody struct { - // The url of the index file - URL string `form:"url" json:"url" xml:"url"` -} - -// AddResponseBody is the type of the "indexes" service "add" endpoint HTTP -// response body. -type AddResponseBody struct { - // The status of the operation - Status *string `form:"status,omitempty" json:"status,omitempty" xml:"status,omitempty"` -} - -// RemoveResponseBody is the type of the "indexes" service "remove" endpoint -// HTTP response body. -type RemoveResponseBody struct { - // The status of the operation - Status *string `form:"status,omitempty" json:"status,omitempty" xml:"status,omitempty"` -} - -// ListInvalidURLResponseBody is the type of the "indexes" service "list" -// endpoint HTTP response body for the "invalid_url" error. -type ListInvalidURLResponseBody struct { - // Name is the name of this class of errors. - Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` - // ID is a unique identifier for this particular occurrence of the problem. - ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` - // Message is a human-readable explanation specific to this occurrence of the - // problem. - Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` - // Is the error temporary? - Temporary *bool `form:"temporary,omitempty" json:"temporary,omitempty" xml:"temporary,omitempty"` - // Is the error a timeout? - Timeout *bool `form:"timeout,omitempty" json:"timeout,omitempty" xml:"timeout,omitempty"` - // Is the error a server-side fault? - Fault *bool `form:"fault,omitempty" json:"fault,omitempty" xml:"fault,omitempty"` -} - -// AddInvalidURLResponseBody is the type of the "indexes" service "add" -// endpoint HTTP response body for the "invalid_url" error. -type AddInvalidURLResponseBody struct { - // Name is the name of this class of errors. - Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` - // ID is a unique identifier for this particular occurrence of the problem. - ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` - // Message is a human-readable explanation specific to this occurrence of the - // problem. - Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` - // Is the error temporary? - Temporary *bool `form:"temporary,omitempty" json:"temporary,omitempty" xml:"temporary,omitempty"` - // Is the error a timeout? - Timeout *bool `form:"timeout,omitempty" json:"timeout,omitempty" xml:"timeout,omitempty"` - // Is the error a server-side fault? - Fault *bool `form:"fault,omitempty" json:"fault,omitempty" xml:"fault,omitempty"` -} - -// RemoveInvalidURLResponseBody is the type of the "indexes" service "remove" -// endpoint HTTP response body for the "invalid_url" error. -type RemoveInvalidURLResponseBody struct { - // Name is the name of this class of errors. - Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` - // ID is a unique identifier for this particular occurrence of the problem. - ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` - // Message is a human-readable explanation specific to this occurrence of the - // problem. - Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` - // Is the error temporary? - Temporary *bool `form:"temporary,omitempty" json:"temporary,omitempty" xml:"temporary,omitempty"` - // Is the error a timeout? - Timeout *bool `form:"timeout,omitempty" json:"timeout,omitempty" xml:"timeout,omitempty"` - // Is the error a server-side fault? - Fault *bool `form:"fault,omitempty" json:"fault,omitempty" xml:"fault,omitempty"` -} - -// NewAddRequestBody builds the HTTP request body from the payload of the "add" -// endpoint of the "indexes" service. -func NewAddRequestBody(p *indexes.IndexPayload) *AddRequestBody { - body := &AddRequestBody{ - URL: p.URL, - } - return body -} - -// NewRemoveRequestBody builds the HTTP request body from the payload of the -// "remove" endpoint of the "indexes" service. -func NewRemoveRequestBody(p *indexes.IndexPayload) *RemoveRequestBody { - body := &RemoveRequestBody{ - URL: p.URL, - } - return body -} - -// NewListInvalidURL builds a indexes service list endpoint invalid_url error. -func NewListInvalidURL(body *ListInvalidURLResponseBody) *goa.ServiceError { - v := &goa.ServiceError{ - Name: *body.Name, - ID: *body.ID, - Message: *body.Message, - Temporary: *body.Temporary, - Timeout: *body.Timeout, - Fault: *body.Fault, - } - - return v -} - -// NewAddOperationOK builds a "indexes" service "add" endpoint result from a -// HTTP "OK" response. -func NewAddOperationOK(body *AddResponseBody) *indexesviews.OperationView { - v := &indexesviews.OperationView{ - Status: body.Status, - } - - return v -} - -// NewAddInvalidURL builds a indexes service add endpoint invalid_url error. -func NewAddInvalidURL(body *AddInvalidURLResponseBody) *goa.ServiceError { - v := &goa.ServiceError{ - Name: *body.Name, - ID: *body.ID, - Message: *body.Message, - Temporary: *body.Temporary, - Timeout: *body.Timeout, - Fault: *body.Fault, - } - - return v -} - -// NewRemoveOperationOK builds a "indexes" service "remove" endpoint result -// from a HTTP "OK" response. -func NewRemoveOperationOK(body *RemoveResponseBody) *indexesviews.OperationView { - v := &indexesviews.OperationView{ - Status: body.Status, - } - - return v -} - -// NewRemoveInvalidURL builds a indexes service remove endpoint invalid_url -// error. -func NewRemoveInvalidURL(body *RemoveInvalidURLResponseBody) *goa.ServiceError { - v := &goa.ServiceError{ - Name: *body.Name, - ID: *body.ID, - Message: *body.Message, - Temporary: *body.Temporary, - Timeout: *body.Timeout, - Fault: *body.Fault, - } - - return v -} - -// ValidateListInvalidURLResponseBody runs the validations defined on -// list_invalid_url_response_body -func ValidateListInvalidURLResponseBody(body *ListInvalidURLResponseBody) (err error) { - if body.Name == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("name", "body")) - } - if body.ID == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) - } - if body.Message == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("message", "body")) - } - if body.Temporary == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("temporary", "body")) - } - if body.Timeout == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("timeout", "body")) - } - if body.Fault == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("fault", "body")) - } - return -} - -// ValidateAddInvalidURLResponseBody runs the validations defined on -// add_invalid_url_response_body -func ValidateAddInvalidURLResponseBody(body *AddInvalidURLResponseBody) (err error) { - if body.Name == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("name", "body")) - } - if body.ID == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) - } - if body.Message == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("message", "body")) - } - if body.Temporary == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("temporary", "body")) - } - if body.Timeout == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("timeout", "body")) - } - if body.Fault == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("fault", "body")) - } - return -} - -// ValidateRemoveInvalidURLResponseBody runs the validations defined on -// remove_invalid_url_response_body -func ValidateRemoveInvalidURLResponseBody(body *RemoveInvalidURLResponseBody) (err error) { - if body.Name == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("name", "body")) - } - if body.ID == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) - } - if body.Message == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("message", "body")) - } - if body.Temporary == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("temporary", "body")) - } - if body.Timeout == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("timeout", "body")) - } - if body.Fault == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("fault", "body")) - } - return -} diff --git a/gen/http/indexes/server/encode_decode.go b/gen/http/indexes/server/encode_decode.go deleted file mode 100644 index fb023036f..000000000 --- a/gen/http/indexes/server/encode_decode.go +++ /dev/null @@ -1,192 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes HTTP server encoders and decoders -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package server - -import ( - "context" - "errors" - "io" - "net/http" - - indexesviews "github.com/arduino/arduino-create-agent/gen/indexes/views" - goahttp "goa.design/goa/v3/http" - goa "goa.design/goa/v3/pkg" -) - -// EncodeListResponse returns an encoder for responses returned by the indexes -// list endpoint. -func EncodeListResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { - return func(ctx context.Context, w http.ResponseWriter, v any) error { - res, _ := v.([]string) - enc := encoder(ctx, w) - body := res - w.WriteHeader(http.StatusOK) - return enc.Encode(body) - } -} - -// EncodeListError returns an encoder for errors returned by the list indexes -// endpoint. -func EncodeListError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { - encodeError := goahttp.ErrorEncoder(encoder, formatter) - return func(ctx context.Context, w http.ResponseWriter, v error) error { - var en goa.GoaErrorNamer - if !errors.As(v, &en) { - return encodeError(ctx, w, v) - } - switch en.GoaErrorName() { - case "invalid_url": - var res *goa.ServiceError - errors.As(v, &res) - enc := encoder(ctx, w) - var body any - if formatter != nil { - body = formatter(ctx, res) - } else { - body = NewListInvalidURLResponseBody(res) - } - w.Header().Set("goa-error", res.GoaErrorName()) - w.WriteHeader(http.StatusBadRequest) - return enc.Encode(body) - default: - return encodeError(ctx, w, v) - } - } -} - -// EncodeAddResponse returns an encoder for responses returned by the indexes -// add endpoint. -func EncodeAddResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { - return func(ctx context.Context, w http.ResponseWriter, v any) error { - res := v.(*indexesviews.Operation) - enc := encoder(ctx, w) - body := NewAddResponseBody(res.Projected) - w.WriteHeader(http.StatusOK) - return enc.Encode(body) - } -} - -// DecodeAddRequest returns a decoder for requests sent to the indexes add -// endpoint. -func DecodeAddRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { - return func(r *http.Request) (any, error) { - var ( - body AddRequestBody - err error - ) - err = decoder(r).Decode(&body) - if err != nil { - if err == io.EOF { - return nil, goa.MissingPayloadError() - } - return nil, goa.DecodePayloadError(err.Error()) - } - err = ValidateAddRequestBody(&body) - if err != nil { - return nil, err - } - payload := NewAddIndexPayload(&body) - - return payload, nil - } -} - -// EncodeAddError returns an encoder for errors returned by the add indexes -// endpoint. -func EncodeAddError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { - encodeError := goahttp.ErrorEncoder(encoder, formatter) - return func(ctx context.Context, w http.ResponseWriter, v error) error { - var en goa.GoaErrorNamer - if !errors.As(v, &en) { - return encodeError(ctx, w, v) - } - switch en.GoaErrorName() { - case "invalid_url": - var res *goa.ServiceError - errors.As(v, &res) - enc := encoder(ctx, w) - var body any - if formatter != nil { - body = formatter(ctx, res) - } else { - body = NewAddInvalidURLResponseBody(res) - } - w.Header().Set("goa-error", res.GoaErrorName()) - w.WriteHeader(http.StatusBadRequest) - return enc.Encode(body) - default: - return encodeError(ctx, w, v) - } - } -} - -// EncodeRemoveResponse returns an encoder for responses returned by the -// indexes remove endpoint. -func EncodeRemoveResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { - return func(ctx context.Context, w http.ResponseWriter, v any) error { - res := v.(*indexesviews.Operation) - enc := encoder(ctx, w) - body := NewRemoveResponseBody(res.Projected) - w.WriteHeader(http.StatusOK) - return enc.Encode(body) - } -} - -// DecodeRemoveRequest returns a decoder for requests sent to the indexes -// remove endpoint. -func DecodeRemoveRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { - return func(r *http.Request) (any, error) { - var ( - body RemoveRequestBody - err error - ) - err = decoder(r).Decode(&body) - if err != nil { - if err == io.EOF { - return nil, goa.MissingPayloadError() - } - return nil, goa.DecodePayloadError(err.Error()) - } - err = ValidateRemoveRequestBody(&body) - if err != nil { - return nil, err - } - payload := NewRemoveIndexPayload(&body) - - return payload, nil - } -} - -// EncodeRemoveError returns an encoder for errors returned by the remove -// indexes endpoint. -func EncodeRemoveError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { - encodeError := goahttp.ErrorEncoder(encoder, formatter) - return func(ctx context.Context, w http.ResponseWriter, v error) error { - var en goa.GoaErrorNamer - if !errors.As(v, &en) { - return encodeError(ctx, w, v) - } - switch en.GoaErrorName() { - case "invalid_url": - var res *goa.ServiceError - errors.As(v, &res) - enc := encoder(ctx, w) - var body any - if formatter != nil { - body = formatter(ctx, res) - } else { - body = NewRemoveInvalidURLResponseBody(res) - } - w.Header().Set("goa-error", res.GoaErrorName()) - w.WriteHeader(http.StatusBadRequest) - return enc.Encode(body) - default: - return encodeError(ctx, w, v) - } - } -} diff --git a/gen/http/indexes/server/paths.go b/gen/http/indexes/server/paths.go deleted file mode 100644 index 6f4e533aa..000000000 --- a/gen/http/indexes/server/paths.go +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// HTTP request path constructors for the indexes service. -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package server - -// ListIndexesPath returns the URL path to the indexes service list HTTP endpoint. -func ListIndexesPath() string { - return "/v2/pkgs/indexes" -} - -// AddIndexesPath returns the URL path to the indexes service add HTTP endpoint. -func AddIndexesPath() string { - return "/v2/pkgs/indexes/add" -} - -// RemoveIndexesPath returns the URL path to the indexes service remove HTTP endpoint. -func RemoveIndexesPath() string { - return "/v2/pkgs/indexes/delete" -} diff --git a/gen/http/indexes/server/server.go b/gen/http/indexes/server/server.go deleted file mode 100644 index a7ecebb30..000000000 --- a/gen/http/indexes/server/server.go +++ /dev/null @@ -1,233 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes HTTP server -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package server - -import ( - "context" - "net/http" - - indexes "github.com/arduino/arduino-create-agent/gen/indexes" - goahttp "goa.design/goa/v3/http" - goa "goa.design/goa/v3/pkg" -) - -// Server lists the indexes service endpoint HTTP handlers. -type Server struct { - Mounts []*MountPoint - List http.Handler - Add http.Handler - Remove http.Handler -} - -// MountPoint holds information about the mounted endpoints. -type MountPoint struct { - // Method is the name of the service method served by the mounted HTTP handler. - Method string - // Verb is the HTTP method used to match requests to the mounted handler. - Verb string - // Pattern is the HTTP request path pattern used to match requests to the - // mounted handler. - Pattern string -} - -// New instantiates HTTP handlers for all the indexes service endpoints using -// the provided encoder and decoder. The handlers are mounted on the given mux -// using the HTTP verb and path defined in the design. errhandler is called -// whenever a response fails to be encoded. formatter is used to format errors -// returned by the service methods prior to encoding. Both errhandler and -// formatter are optional and can be nil. -func New( - e *indexes.Endpoints, - mux goahttp.Muxer, - decoder func(*http.Request) goahttp.Decoder, - encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, - errhandler func(context.Context, http.ResponseWriter, error), - formatter func(ctx context.Context, err error) goahttp.Statuser, -) *Server { - return &Server{ - Mounts: []*MountPoint{ - {"List", "GET", "/v2/pkgs/indexes"}, - {"Add", "POST", "/v2/pkgs/indexes/add"}, - {"Remove", "POST", "/v2/pkgs/indexes/delete"}, - }, - List: NewListHandler(e.List, mux, decoder, encoder, errhandler, formatter), - Add: NewAddHandler(e.Add, mux, decoder, encoder, errhandler, formatter), - Remove: NewRemoveHandler(e.Remove, mux, decoder, encoder, errhandler, formatter), - } -} - -// Service returns the name of the service served. -func (s *Server) Service() string { return "indexes" } - -// Use wraps the server handlers with the given middleware. -func (s *Server) Use(m func(http.Handler) http.Handler) { - s.List = m(s.List) - s.Add = m(s.Add) - s.Remove = m(s.Remove) -} - -// MethodNames returns the methods served. -func (s *Server) MethodNames() []string { return indexes.MethodNames[:] } - -// Mount configures the mux to serve the indexes endpoints. -func Mount(mux goahttp.Muxer, h *Server) { - MountListHandler(mux, h.List) - MountAddHandler(mux, h.Add) - MountRemoveHandler(mux, h.Remove) -} - -// Mount configures the mux to serve the indexes endpoints. -func (s *Server) Mount(mux goahttp.Muxer) { - Mount(mux, s) -} - -// MountListHandler configures the mux to serve the "indexes" service "list" -// endpoint. -func MountListHandler(mux goahttp.Muxer, h http.Handler) { - f, ok := h.(http.HandlerFunc) - if !ok { - f = func(w http.ResponseWriter, r *http.Request) { - h.ServeHTTP(w, r) - } - } - mux.Handle("GET", "/v2/pkgs/indexes", f) -} - -// NewListHandler creates a HTTP handler which loads the HTTP request and calls -// the "indexes" service "list" endpoint. -func NewListHandler( - endpoint goa.Endpoint, - mux goahttp.Muxer, - decoder func(*http.Request) goahttp.Decoder, - encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, - errhandler func(context.Context, http.ResponseWriter, error), - formatter func(ctx context.Context, err error) goahttp.Statuser, -) http.Handler { - var ( - encodeResponse = EncodeListResponse(encoder) - encodeError = EncodeListError(encoder, formatter) - ) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) - ctx = context.WithValue(ctx, goa.MethodKey, "list") - ctx = context.WithValue(ctx, goa.ServiceKey, "indexes") - var err error - res, err := endpoint(ctx, nil) - if err != nil { - if err := encodeError(ctx, w, err); err != nil { - errhandler(ctx, w, err) - } - return - } - if err := encodeResponse(ctx, w, res); err != nil { - errhandler(ctx, w, err) - } - }) -} - -// MountAddHandler configures the mux to serve the "indexes" service "add" -// endpoint. -func MountAddHandler(mux goahttp.Muxer, h http.Handler) { - f, ok := h.(http.HandlerFunc) - if !ok { - f = func(w http.ResponseWriter, r *http.Request) { - h.ServeHTTP(w, r) - } - } - mux.Handle("POST", "/v2/pkgs/indexes/add", f) -} - -// NewAddHandler creates a HTTP handler which loads the HTTP request and calls -// the "indexes" service "add" endpoint. -func NewAddHandler( - endpoint goa.Endpoint, - mux goahttp.Muxer, - decoder func(*http.Request) goahttp.Decoder, - encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, - errhandler func(context.Context, http.ResponseWriter, error), - formatter func(ctx context.Context, err error) goahttp.Statuser, -) http.Handler { - var ( - decodeRequest = DecodeAddRequest(mux, decoder) - encodeResponse = EncodeAddResponse(encoder) - encodeError = EncodeAddError(encoder, formatter) - ) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) - ctx = context.WithValue(ctx, goa.MethodKey, "add") - ctx = context.WithValue(ctx, goa.ServiceKey, "indexes") - payload, err := decodeRequest(r) - if err != nil { - if err := encodeError(ctx, w, err); err != nil { - errhandler(ctx, w, err) - } - return - } - res, err := endpoint(ctx, payload) - if err != nil { - if err := encodeError(ctx, w, err); err != nil { - errhandler(ctx, w, err) - } - return - } - if err := encodeResponse(ctx, w, res); err != nil { - errhandler(ctx, w, err) - } - }) -} - -// MountRemoveHandler configures the mux to serve the "indexes" service -// "remove" endpoint. -func MountRemoveHandler(mux goahttp.Muxer, h http.Handler) { - f, ok := h.(http.HandlerFunc) - if !ok { - f = func(w http.ResponseWriter, r *http.Request) { - h.ServeHTTP(w, r) - } - } - mux.Handle("POST", "/v2/pkgs/indexes/delete", f) -} - -// NewRemoveHandler creates a HTTP handler which loads the HTTP request and -// calls the "indexes" service "remove" endpoint. -func NewRemoveHandler( - endpoint goa.Endpoint, - mux goahttp.Muxer, - decoder func(*http.Request) goahttp.Decoder, - encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, - errhandler func(context.Context, http.ResponseWriter, error), - formatter func(ctx context.Context, err error) goahttp.Statuser, -) http.Handler { - var ( - decodeRequest = DecodeRemoveRequest(mux, decoder) - encodeResponse = EncodeRemoveResponse(encoder) - encodeError = EncodeRemoveError(encoder, formatter) - ) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) - ctx = context.WithValue(ctx, goa.MethodKey, "remove") - ctx = context.WithValue(ctx, goa.ServiceKey, "indexes") - payload, err := decodeRequest(r) - if err != nil { - if err := encodeError(ctx, w, err); err != nil { - errhandler(ctx, w, err) - } - return - } - res, err := endpoint(ctx, payload) - if err != nil { - if err := encodeError(ctx, w, err); err != nil { - errhandler(ctx, w, err) - } - return - } - if err := encodeResponse(ctx, w, res); err != nil { - errhandler(ctx, w, err) - } - }) -} diff --git a/gen/http/indexes/server/types.go b/gen/http/indexes/server/types.go deleted file mode 100644 index a19a5459c..000000000 --- a/gen/http/indexes/server/types.go +++ /dev/null @@ -1,190 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes HTTP server types -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package server - -import ( - indexes "github.com/arduino/arduino-create-agent/gen/indexes" - indexesviews "github.com/arduino/arduino-create-agent/gen/indexes/views" - goa "goa.design/goa/v3/pkg" -) - -// AddRequestBody is the type of the "indexes" service "add" endpoint HTTP -// request body. -type AddRequestBody struct { - // The url of the index file - URL *string `form:"url,omitempty" json:"url,omitempty" xml:"url,omitempty"` -} - -// RemoveRequestBody is the type of the "indexes" service "remove" endpoint -// HTTP request body. -type RemoveRequestBody struct { - // The url of the index file - URL *string `form:"url,omitempty" json:"url,omitempty" xml:"url,omitempty"` -} - -// AddResponseBody is the type of the "indexes" service "add" endpoint HTTP -// response body. -type AddResponseBody struct { - // The status of the operation - Status string `form:"status" json:"status" xml:"status"` -} - -// RemoveResponseBody is the type of the "indexes" service "remove" endpoint -// HTTP response body. -type RemoveResponseBody struct { - // The status of the operation - Status string `form:"status" json:"status" xml:"status"` -} - -// ListInvalidURLResponseBody is the type of the "indexes" service "list" -// endpoint HTTP response body for the "invalid_url" error. -type ListInvalidURLResponseBody struct { - // Name is the name of this class of errors. - Name string `form:"name" json:"name" xml:"name"` - // ID is a unique identifier for this particular occurrence of the problem. - ID string `form:"id" json:"id" xml:"id"` - // Message is a human-readable explanation specific to this occurrence of the - // problem. - Message string `form:"message" json:"message" xml:"message"` - // Is the error temporary? - Temporary bool `form:"temporary" json:"temporary" xml:"temporary"` - // Is the error a timeout? - Timeout bool `form:"timeout" json:"timeout" xml:"timeout"` - // Is the error a server-side fault? - Fault bool `form:"fault" json:"fault" xml:"fault"` -} - -// AddInvalidURLResponseBody is the type of the "indexes" service "add" -// endpoint HTTP response body for the "invalid_url" error. -type AddInvalidURLResponseBody struct { - // Name is the name of this class of errors. - Name string `form:"name" json:"name" xml:"name"` - // ID is a unique identifier for this particular occurrence of the problem. - ID string `form:"id" json:"id" xml:"id"` - // Message is a human-readable explanation specific to this occurrence of the - // problem. - Message string `form:"message" json:"message" xml:"message"` - // Is the error temporary? - Temporary bool `form:"temporary" json:"temporary" xml:"temporary"` - // Is the error a timeout? - Timeout bool `form:"timeout" json:"timeout" xml:"timeout"` - // Is the error a server-side fault? - Fault bool `form:"fault" json:"fault" xml:"fault"` -} - -// RemoveInvalidURLResponseBody is the type of the "indexes" service "remove" -// endpoint HTTP response body for the "invalid_url" error. -type RemoveInvalidURLResponseBody struct { - // Name is the name of this class of errors. - Name string `form:"name" json:"name" xml:"name"` - // ID is a unique identifier for this particular occurrence of the problem. - ID string `form:"id" json:"id" xml:"id"` - // Message is a human-readable explanation specific to this occurrence of the - // problem. - Message string `form:"message" json:"message" xml:"message"` - // Is the error temporary? - Temporary bool `form:"temporary" json:"temporary" xml:"temporary"` - // Is the error a timeout? - Timeout bool `form:"timeout" json:"timeout" xml:"timeout"` - // Is the error a server-side fault? - Fault bool `form:"fault" json:"fault" xml:"fault"` -} - -// NewAddResponseBody builds the HTTP response body from the result of the -// "add" endpoint of the "indexes" service. -func NewAddResponseBody(res *indexesviews.OperationView) *AddResponseBody { - body := &AddResponseBody{ - Status: *res.Status, - } - return body -} - -// NewRemoveResponseBody builds the HTTP response body from the result of the -// "remove" endpoint of the "indexes" service. -func NewRemoveResponseBody(res *indexesviews.OperationView) *RemoveResponseBody { - body := &RemoveResponseBody{ - Status: *res.Status, - } - return body -} - -// NewListInvalidURLResponseBody builds the HTTP response body from the result -// of the "list" endpoint of the "indexes" service. -func NewListInvalidURLResponseBody(res *goa.ServiceError) *ListInvalidURLResponseBody { - body := &ListInvalidURLResponseBody{ - Name: res.Name, - ID: res.ID, - Message: res.Message, - Temporary: res.Temporary, - Timeout: res.Timeout, - Fault: res.Fault, - } - return body -} - -// NewAddInvalidURLResponseBody builds the HTTP response body from the result -// of the "add" endpoint of the "indexes" service. -func NewAddInvalidURLResponseBody(res *goa.ServiceError) *AddInvalidURLResponseBody { - body := &AddInvalidURLResponseBody{ - Name: res.Name, - ID: res.ID, - Message: res.Message, - Temporary: res.Temporary, - Timeout: res.Timeout, - Fault: res.Fault, - } - return body -} - -// NewRemoveInvalidURLResponseBody builds the HTTP response body from the -// result of the "remove" endpoint of the "indexes" service. -func NewRemoveInvalidURLResponseBody(res *goa.ServiceError) *RemoveInvalidURLResponseBody { - body := &RemoveInvalidURLResponseBody{ - Name: res.Name, - ID: res.ID, - Message: res.Message, - Temporary: res.Temporary, - Timeout: res.Timeout, - Fault: res.Fault, - } - return body -} - -// NewAddIndexPayload builds a indexes service add endpoint payload. -func NewAddIndexPayload(body *AddRequestBody) *indexes.IndexPayload { - v := &indexes.IndexPayload{ - URL: *body.URL, - } - - return v -} - -// NewRemoveIndexPayload builds a indexes service remove endpoint payload. -func NewRemoveIndexPayload(body *RemoveRequestBody) *indexes.IndexPayload { - v := &indexes.IndexPayload{ - URL: *body.URL, - } - - return v -} - -// ValidateAddRequestBody runs the validations defined on AddRequestBody -func ValidateAddRequestBody(body *AddRequestBody) (err error) { - if body.URL == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("url", "body")) - } - return -} - -// ValidateRemoveRequestBody runs the validations defined on RemoveRequestBody -func ValidateRemoveRequestBody(body *RemoveRequestBody) (err error) { - if body.URL == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("url", "body")) - } - return -} diff --git a/gen/http/openapi.json b/gen/http/openapi.json index 093633ef5..a8e08e509 100644 --- a/gen/http/openapi.json +++ b/gen/http/openapi.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"title":"Arduino Create Agent","description":"A companion of Arduino Create. \n\tAllows the website to perform operations on the user computer, \n\tsuch as detecting which boards are connected and upload sketches on them.","version":""},"host":"localhost:80","basePath":"/v2","consumes":["application/json","plain/text"],"produces":["application/json","application/xml","application/gob"],"paths":{"/pkgs/indexes":{"get":{"tags":["indexes"],"summary":"list indexes","operationId":"indexes#list","responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Pariatur laudantium inventore qui."}}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/IndexesListInvalidURLResponseBody"}}},"schemes":["http"]}},"/pkgs/indexes/add":{"post":{"tags":["indexes"],"summary":"add indexes","operationId":"indexes#add","parameters":[{"name":"AddRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/IndexesAddRequestBody","required":["url"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/IndexesAddResponseBody"}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/IndexesAddInvalidURLResponseBody"}}},"schemes":["http"]}},"/pkgs/indexes/delete":{"post":{"tags":["indexes"],"summary":"remove indexes","operationId":"indexes#remove","parameters":[{"name":"RemoveRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/IndexesRemoveRequestBody","required":["url"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/IndexesRemoveResponseBody"}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/IndexesRemoveInvalidURLResponseBody"}}},"schemes":["http"]}},"/pkgs/tools/available":{"get":{"tags":["tools"],"summary":"available tools","operationId":"tools#available","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsToolResponseCollection"}}},"schemes":["http"]}},"/pkgs/tools/installed":{"get":{"tags":["tools"],"summary":"installed tools","operationId":"tools#installed","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsToolResponseCollection"}}},"schemes":["http"]},"post":{"tags":["tools"],"summary":"install tools","operationId":"tools#install","parameters":[{"name":"InstallRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/ToolsInstallRequestBody","required":["name","version","packager"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsInstallResponseBody"}}},"schemes":["http"]}},"/pkgs/tools/installed/{packager}/{name}/{version}":{"delete":{"tags":["tools"],"summary":"remove tools","operationId":"tools#remove","parameters":[{"name":"packager","in":"path","description":"The packager of the tool","required":true,"type":"string"},{"name":"name","in":"path","description":"The name of the tool","required":true,"type":"string"},{"name":"version","in":"path","description":"The version of the tool","required":true,"type":"string"},{"name":"RemoveRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/ToolsRemoveRequestBody"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsRemoveResponseBody"}}},"schemes":["http"]}}},"definitions":{"IndexesAddInvalidURLResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"url invalid (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"IndexesAddRequestBody":{"title":"IndexesAddRequestBody","type":"object","properties":{"url":{"type":"string","description":"The url of the index file","example":"https://downloads.arduino.cc/packages/package_index.json"}},"example":{"url":"https://downloads.arduino.cc/packages/package_index.json"},"required":["url"]},"IndexesAddResponseBody":{"title":"Mediatype identifier: application/vnd.arduino.operation; view=default","type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"description":"AddResponseBody result type (default view)","example":{"status":"ok"},"required":["status"]},"IndexesListInvalidURLResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"url invalid (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"IndexesRemoveInvalidURLResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"url invalid (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"IndexesRemoveRequestBody":{"title":"IndexesRemoveRequestBody","type":"object","properties":{"url":{"type":"string","description":"The url of the index file","example":"https://downloads.arduino.cc/packages/package_index.json"}},"example":{"url":"https://downloads.arduino.cc/packages/package_index.json"},"required":["url"]},"IndexesRemoveResponseBody":{"title":"Mediatype identifier: application/vnd.arduino.operation; view=default","type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"description":"RemoveResponseBody result type (default view)","example":{"status":"ok"},"required":["status"]},"ToolResponse":{"title":"Mediatype identifier: application/vnd.arduino.tool; view=default","type":"object","properties":{"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"description":"A tool is an executable program that can upload sketches. (default view)","example":{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"ToolsInstallRequestBody":{"title":"ToolsInstallRequestBody","type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","name":"bossac","packager":"arduino","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"ToolsInstallResponseBody":{"title":"Mediatype identifier: application/vnd.arduino.operation; view=default","type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"description":"InstallResponseBody result type (default view)","example":{"status":"ok"},"required":["status"]},"ToolsRemoveRequestBody":{"title":"ToolsRemoveRequestBody","type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"ToolsRemoveResponseBody":{"title":"Mediatype identifier: application/vnd.arduino.operation; view=default","type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"description":"RemoveResponseBody result type (default view)","example":{"status":"ok"},"required":["status"]},"ToolsToolResponseCollection":{"title":"Mediatype identifier: application/vnd.arduino.tool; type=collection; view=default","type":"array","items":{"$ref":"#/definitions/ToolResponse"},"description":"AvailableResponseBody is the result type for an array of ToolResponse (default view)","example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}} \ No newline at end of file +{"swagger":"2.0","info":{"title":"Arduino Create Agent","description":"A companion of Arduino Create. \n\tAllows the website to perform operations on the user computer, \n\tsuch as detecting which boards are connected and upload sketches on them.","version":""},"host":"localhost:80","basePath":"/v2","consumes":["application/json","plain/text"],"produces":["application/json","application/xml","application/gob"],"paths":{"/pkgs/tools/available":{"get":{"tags":["tools"],"summary":"available tools","operationId":"tools#available","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsToolResponseCollection"}}},"schemes":["http"]}},"/pkgs/tools/installed":{"get":{"tags":["tools"],"summary":"installed tools","operationId":"tools#installed","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsToolResponseCollection"}}},"schemes":["http"]},"post":{"tags":["tools"],"summary":"install tools","operationId":"tools#install","parameters":[{"name":"InstallRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/ToolsInstallRequestBody","required":["name","version","packager"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsInstallResponseBody"}}},"schemes":["http"]}},"/pkgs/tools/installed/{packager}/{name}/{version}":{"delete":{"tags":["tools"],"summary":"remove tools","operationId":"tools#remove","parameters":[{"name":"packager","in":"path","description":"The packager of the tool","required":true,"type":"string"},{"name":"name","in":"path","description":"The name of the tool","required":true,"type":"string"},{"name":"version","in":"path","description":"The version of the tool","required":true,"type":"string"},{"name":"RemoveRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/ToolsRemoveRequestBody"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/ToolsRemoveResponseBody"}}},"schemes":["http"]}}},"definitions":{"ToolResponse":{"title":"Mediatype identifier: application/vnd.arduino.tool; view=default","type":"object","properties":{"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"description":"A tool is an executable program that can upload sketches. (default view)","example":{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"ToolsInstallRequestBody":{"title":"ToolsInstallRequestBody","type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","name":"bossac","packager":"arduino","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"ToolsInstallResponseBody":{"title":"Mediatype identifier: application/vnd.arduino.operation; view=default","type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"description":"InstallResponseBody result type (default view)","example":{"status":"ok"},"required":["status"]},"ToolsRemoveRequestBody":{"title":"ToolsRemoveRequestBody","type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"ToolsRemoveResponseBody":{"title":"Mediatype identifier: application/vnd.arduino.operation; view=default","type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"description":"RemoveResponseBody result type (default view)","example":{"status":"ok"},"required":["status"]},"ToolsToolResponseCollection":{"title":"Mediatype identifier: application/vnd.arduino.tool; type=collection; view=default","type":"array","items":{"$ref":"#/definitions/ToolResponse"},"description":"AvailableResponseBody is the result type for an array of ToolResponse (default view)","example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}} \ No newline at end of file diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml index fd351cf28..ac98393fc 100644 --- a/gen/http/openapi.yaml +++ b/gen/http/openapi.yaml @@ -13,76 +13,6 @@ produces: - application/xml - application/gob paths: - /pkgs/indexes: - get: - tags: - - indexes - summary: list indexes - operationId: indexes#list - responses: - "200": - description: OK response. - schema: - type: array - items: - type: string - example: Pariatur laudantium inventore qui. - "400": - description: Bad Request response. - schema: - $ref: '#/definitions/IndexesListInvalidURLResponseBody' - schemes: - - http - /pkgs/indexes/add: - post: - tags: - - indexes - summary: add indexes - operationId: indexes#add - parameters: - - name: AddRequestBody - in: body - required: true - schema: - $ref: '#/definitions/IndexesAddRequestBody' - required: - - url - responses: - "200": - description: OK response. - schema: - $ref: '#/definitions/IndexesAddResponseBody' - "400": - description: Bad Request response. - schema: - $ref: '#/definitions/IndexesAddInvalidURLResponseBody' - schemes: - - http - /pkgs/indexes/delete: - post: - tags: - - indexes - summary: remove indexes - operationId: indexes#remove - parameters: - - name: RemoveRequestBody - in: body - required: true - schema: - $ref: '#/definitions/IndexesRemoveRequestBody' - required: - - url - responses: - "200": - description: OK response. - schema: - $ref: '#/definitions/IndexesRemoveResponseBody' - "400": - description: Bad Request response. - schema: - $ref: '#/definitions/IndexesRemoveInvalidURLResponseBody' - schemes: - - http /pkgs/tools/available: get: tags: @@ -166,185 +96,6 @@ paths: schemes: - http definitions: - IndexesAddInvalidURLResponseBody: - title: 'Mediatype identifier: application/vnd.goa.error; view=default' - type: object - properties: - fault: - type: boolean - description: Is the error a server-side fault? - example: true - id: - type: string - description: ID is a unique identifier for this particular occurrence of the problem. - example: 123abc - message: - type: string - description: Message is a human-readable explanation specific to this occurrence of the problem. - example: parameter 'p' must be an integer - name: - type: string - description: Name is the name of this class of errors. - example: bad_request - temporary: - type: boolean - description: Is the error temporary? - example: true - timeout: - type: boolean - description: Is the error a timeout? - example: true - description: url invalid (default view) - example: - fault: false - id: 123abc - message: parameter 'p' must be an integer - name: bad_request - temporary: true - timeout: false - required: - - name - - id - - message - - temporary - - timeout - - fault - IndexesAddRequestBody: - title: IndexesAddRequestBody - type: object - properties: - url: - type: string - description: The url of the index file - example: https://downloads.arduino.cc/packages/package_index.json - example: - url: https://downloads.arduino.cc/packages/package_index.json - required: - - url - IndexesAddResponseBody: - title: 'Mediatype identifier: application/vnd.arduino.operation; view=default' - type: object - properties: - status: - type: string - description: The status of the operation - example: ok - description: AddResponseBody result type (default view) - example: - status: ok - required: - - status - IndexesListInvalidURLResponseBody: - title: 'Mediatype identifier: application/vnd.goa.error; view=default' - type: object - properties: - fault: - type: boolean - description: Is the error a server-side fault? - example: false - id: - type: string - description: ID is a unique identifier for this particular occurrence of the problem. - example: 123abc - message: - type: string - description: Message is a human-readable explanation specific to this occurrence of the problem. - example: parameter 'p' must be an integer - name: - type: string - description: Name is the name of this class of errors. - example: bad_request - temporary: - type: boolean - description: Is the error temporary? - example: false - timeout: - type: boolean - description: Is the error a timeout? - example: true - description: url invalid (default view) - example: - fault: false - id: 123abc - message: parameter 'p' must be an integer - name: bad_request - temporary: false - timeout: true - required: - - name - - id - - message - - temporary - - timeout - - fault - IndexesRemoveInvalidURLResponseBody: - title: 'Mediatype identifier: application/vnd.goa.error; view=default' - type: object - properties: - fault: - type: boolean - description: Is the error a server-side fault? - example: true - id: - type: string - description: ID is a unique identifier for this particular occurrence of the problem. - example: 123abc - message: - type: string - description: Message is a human-readable explanation specific to this occurrence of the problem. - example: parameter 'p' must be an integer - name: - type: string - description: Name is the name of this class of errors. - example: bad_request - temporary: - type: boolean - description: Is the error temporary? - example: false - timeout: - type: boolean - description: Is the error a timeout? - example: false - description: url invalid (default view) - example: - fault: true - id: 123abc - message: parameter 'p' must be an integer - name: bad_request - temporary: true - timeout: true - required: - - name - - id - - message - - temporary - - timeout - - fault - IndexesRemoveRequestBody: - title: IndexesRemoveRequestBody - type: object - properties: - url: - type: string - description: The url of the index file - example: https://downloads.arduino.cc/packages/package_index.json - example: - url: https://downloads.arduino.cc/packages/package_index.json - required: - - url - IndexesRemoveResponseBody: - title: 'Mediatype identifier: application/vnd.arduino.operation; view=default' - type: object - properties: - status: - type: string - description: The status of the operation - example: ok - description: RemoveResponseBody result type (default view) - example: - status: ok - required: - - status ToolResponse: title: 'Mediatype identifier: application/vnd.arduino.tool; view=default' type: object diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json index fb26d68bf..b02a940bd 100644 --- a/gen/http/openapi3.json +++ b/gen/http/openapi3.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Arduino Create Agent","description":"A companion of Arduino Create. \n\tAllows the website to perform operations on the user computer, \n\tsuch as detecting which boards are connected and upload sketches on them.","version":"1.0"},"servers":[{"url":"http://localhost:80","description":"Default server for arduino-create-agent"}],"paths":{"/v2/pkgs/indexes":{"get":{"tags":["indexes"],"summary":"list indexes","operationId":"indexes#list","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Rerum et soluta laudantium."},"example":["Et deserunt.","Impedit iusto libero explicabo.","Dolor adipisci nulla.","Quam voluptas voluptates expedita rem ipsum."]},"example":["Dignissimos consectetur eos molestiae culpa soluta deserunt.","Nobis sint dolorem unde.","Quia doloremque.","Atque iusto tempore sit quod dolor repellat."]}}},"400":{"description":"invalid_url: url invalid","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/pkgs/indexes/add":{"post":{"tags":["indexes"],"summary":"add indexes","operationId":"indexes#add","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRequestBody"},"example":{"url":"https://downloads.arduino.cc/packages/package_index.json"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Operation"},"example":{"status":"ok"}}}},"400":{"description":"invalid_url: url invalid","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/pkgs/indexes/delete":{"post":{"tags":["indexes"],"summary":"remove indexes","operationId":"indexes#remove","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRequestBody"},"example":{"url":"https://downloads.arduino.cc/packages/package_index.json"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Operation"},"example":{"status":"ok"}}}},"400":{"description":"invalid_url: url invalid","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/pkgs/tools/available":{"get":{"tags":["tools"],"summary":"available tools","operationId":"tools#available","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCollection"},"example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}}}}},"/v2/pkgs/tools/installed":{"get":{"tags":["tools"],"summary":"installed tools","operationId":"tools#installed","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCollection"},"example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}}}},"post":{"tags":["tools"],"summary":"install tools","operationId":"tools#install","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallRequestBody"},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","name":"bossac","packager":"arduino","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz","version":"1.7.0-arduino3"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Operation"},"example":{"status":"ok"}}}}}}},"/v2/pkgs/tools/installed/{packager}/{name}/{version}":{"delete":{"tags":["tools"],"summary":"remove tools","operationId":"tools#remove","parameters":[{"name":"packager","in":"path","description":"The packager of the tool","required":true,"schema":{"type":"string","description":"The packager of the tool","example":"arduino"},"example":"arduino"},{"name":"name","in":"path","description":"The name of the tool","required":true,"schema":{"type":"string","description":"The name of the tool","example":"bossac"},"example":"bossac"},{"name":"version","in":"path","description":"The version of the tool","required":true,"schema":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"},"example":"1.7.0-arduino3"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveRequestBody"},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Operation"},"example":{"status":"ok"}}}}}}}},"components":{"schemas":{"AddRequestBody":{"type":"object","properties":{"url":{"type":"string","description":"The url of the index file","example":"https://downloads.arduino.cc/packages/package_index.json"}},"example":{"url":"https://downloads.arduino.cc/packages/package_index.json"},"required":["url"]},"ArduinoTool":{"type":"object","properties":{"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"description":"A tool is an executable program that can upload sketches.","example":{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"Error":{"type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"url invalid","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"InstallRequestBody":{"type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","name":"bossac","packager":"arduino","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"Operation":{"type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"example":{"status":"ok"},"required":["status"]},"RemoveRequestBody":{"type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"ToolCollection":{"type":"array","items":{"$ref":"#/components/schemas/ArduinoTool"},"example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}},"tags":[{"name":"indexes","description":"The indexes service manages the package_index files"},{"name":"tools","description":"The tools service manages the available and installed tools"}]} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Arduino Create Agent","description":"A companion of Arduino Create. \n\tAllows the website to perform operations on the user computer, \n\tsuch as detecting which boards are connected and upload sketches on them.","version":"1.0"},"servers":[{"url":"http://localhost:80","description":"Default server for arduino-create-agent"}],"paths":{"/v2/pkgs/tools/available":{"get":{"tags":["tools"],"summary":"available tools","operationId":"tools#available","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCollection"},"example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}}}}},"/v2/pkgs/tools/installed":{"get":{"tags":["tools"],"summary":"installed tools","operationId":"tools#installed","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCollection"},"example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}}}},"post":{"tags":["tools"],"summary":"install tools","operationId":"tools#install","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallRequestBody"},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","name":"bossac","packager":"arduino","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz","version":"1.7.0-arduino3"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Operation"},"example":{"status":"ok"}}}}}}},"/v2/pkgs/tools/installed/{packager}/{name}/{version}":{"delete":{"tags":["tools"],"summary":"remove tools","operationId":"tools#remove","parameters":[{"name":"packager","in":"path","description":"The packager of the tool","required":true,"schema":{"type":"string","description":"The packager of the tool","example":"arduino"},"example":"arduino"},{"name":"name","in":"path","description":"The name of the tool","required":true,"schema":{"type":"string","description":"The name of the tool","example":"bossac"},"example":"bossac"},{"name":"version","in":"path","description":"The version of the tool","required":true,"schema":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"},"example":"1.7.0-arduino3"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveRequestBody"},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Operation"},"example":{"status":"ok"}}}}}}}},"components":{"schemas":{"ArduinoTool":{"type":"object","properties":{"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"description":"A tool is an executable program that can upload sketches.","example":{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"InstallRequestBody":{"type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"name":{"type":"string","description":"The name of the tool","example":"bossac"},"packager":{"type":"string","description":"The packager of the tool","example":"arduino"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"},"version":{"type":"string","description":"The version of the tool","example":"1.7.0-arduino3"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","name":"bossac","packager":"arduino","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz","version":"1.7.0-arduino3"},"required":["name","version","packager"]},"Operation":{"type":"object","properties":{"status":{"type":"string","description":"The status of the operation","example":"ok"}},"example":{"status":"ok"},"required":["status"]},"RemoveRequestBody":{"type":"object","properties":{"checksum":{"type":"string","description":"A checksum of the archive. Mandatory when url is present. \n\tThis ensures that the package is downloaded correcly.","example":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100"},"signature":{"type":"string","description":"The signature used to sign the url. Mandatory when url is present.\n\tThis ensure the security of the file downloaded","example":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0"},"url":{"type":"string","description":"The url where the package can be found. Optional. \n\tIf present checksum must also be present.","example":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"example":{"checksum":"SHA-256:1ae54999c1f97234a5c603eb99ad39313b11746a4ca517269a9285afa05f9100","signature":"382898a97b5a86edd74208f10107d2fecbf7059ffe9cc856e045266fb4db4e98802728a0859cfdcda1c0b9075ec01e42dbea1f430b813530d5a6ae1766dfbba64c3e689b59758062dc2ab2e32b2a3491dc2b9a80b9cda4ae514fbe0ec5af210111b6896976053ab76bac55bcecfcececa68adfa3299e3cde6b7f117b3552a7d80ca419374bb497e3c3f12b640cf5b20875416b45e662fc6150b99b178f8e41d6982b4c0a255925ea39773683f9aa9201dc5768b6fc857c87ff602b6a93452a541b8ec10ca07f166e61a9e9d91f0a6090bd2038ed4427af6251039fb9fe8eb62ec30d7b0f3df38bc9de7204dec478fb86f8eb3f71543710790ee169dce039d3e0","url":"http://downloads.arduino.cc/tools/bossac-1.7.0-arduino3-linux64.tar.gz"}},"ToolCollection":{"type":"array","items":{"$ref":"#/components/schemas/ArduinoTool"},"example":[{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"},{"name":"bossac","packager":"arduino","version":"1.7.0-arduino3"}]}}},"tags":[{"name":"tools","description":"The tools service manages the available and installed tools"}]} \ No newline at end of file diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml index 8608590fe..a39c969b2 100644 --- a/gen/http/openapi3.yaml +++ b/gen/http/openapi3.yaml @@ -7,96 +7,6 @@ servers: - url: http://localhost:80 description: Default server for arduino-create-agent paths: - /v2/pkgs/indexes: - get: - tags: - - indexes - summary: list indexes - operationId: indexes#list - responses: - "200": - description: OK response. - content: - application/json: - schema: - type: array - items: - type: string - example: Rerum et soluta laudantium. - example: - - Et deserunt. - - Impedit iusto libero explicabo. - - Dolor adipisci nulla. - - Quam voluptas voluptates expedita rem ipsum. - example: - - Dignissimos consectetur eos molestiae culpa soluta deserunt. - - Nobis sint dolorem unde. - - Quia doloremque. - - Atque iusto tempore sit quod dolor repellat. - "400": - description: 'invalid_url: url invalid' - content: - application/vnd.goa.error: - schema: - $ref: '#/components/schemas/Error' - /v2/pkgs/indexes/add: - post: - tags: - - indexes - summary: add indexes - operationId: indexes#add - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AddRequestBody' - example: - url: https://downloads.arduino.cc/packages/package_index.json - responses: - "200": - description: OK response. - content: - application/json: - schema: - $ref: '#/components/schemas/Operation' - example: - status: ok - "400": - description: 'invalid_url: url invalid' - content: - application/vnd.goa.error: - schema: - $ref: '#/components/schemas/Error' - /v2/pkgs/indexes/delete: - post: - tags: - - indexes - summary: remove indexes - operationId: indexes#remove - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AddRequestBody' - example: - url: https://downloads.arduino.cc/packages/package_index.json - responses: - "200": - description: OK response. - content: - application/json: - schema: - $ref: '#/components/schemas/Operation' - example: - status: ok - "400": - description: 'invalid_url: url invalid' - content: - application/vnd.goa.error: - schema: - $ref: '#/components/schemas/Error' /v2/pkgs/tools/available: get: tags: @@ -225,17 +135,6 @@ paths: status: ok components: schemas: - AddRequestBody: - type: object - properties: - url: - type: string - description: The url of the index file - example: https://downloads.arduino.cc/packages/package_index.json - example: - url: https://downloads.arduino.cc/packages/package_index.json - required: - - url ArduinoTool: type: object properties: @@ -260,48 +159,6 @@ components: - name - version - packager - Error: - type: object - properties: - fault: - type: boolean - description: Is the error a server-side fault? - example: false - id: - type: string - description: ID is a unique identifier for this particular occurrence of the problem. - example: 123abc - message: - type: string - description: Message is a human-readable explanation specific to this occurrence of the problem. - example: parameter 'p' must be an integer - name: - type: string - description: Name is the name of this class of errors. - example: bad_request - temporary: - type: boolean - description: Is the error temporary? - example: true - timeout: - type: boolean - description: Is the error a timeout? - example: false - description: url invalid - example: - fault: false - id: 123abc - message: parameter 'p' must be an integer - name: bad_request - temporary: true - timeout: false - required: - - name - - id - - message - - temporary - - timeout - - fault InstallRequestBody: type: object properties: @@ -388,8 +245,9 @@ components: - name: bossac packager: arduino version: 1.7.0-arduino3 + - name: bossac + packager: arduino + version: 1.7.0-arduino3 tags: - - name: indexes - description: The indexes service manages the package_index files - name: tools description: The tools service manages the available and installed tools diff --git a/gen/indexes/client.go b/gen/indexes/client.go deleted file mode 100644 index 382b373dc..000000000 --- a/gen/indexes/client.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes client -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package indexes - -import ( - "context" - - goa "goa.design/goa/v3/pkg" -) - -// Client is the "indexes" service client. -type Client struct { - ListEndpoint goa.Endpoint - AddEndpoint goa.Endpoint - RemoveEndpoint goa.Endpoint -} - -// NewClient initializes a "indexes" service client given the endpoints. -func NewClient(list, add, remove goa.Endpoint) *Client { - return &Client{ - ListEndpoint: list, - AddEndpoint: add, - RemoveEndpoint: remove, - } -} - -// List calls the "list" endpoint of the "indexes" service. -// List may return the following errors: -// - "invalid_url" (type *goa.ServiceError): url invalid -// - error: internal error -func (c *Client) List(ctx context.Context) (res []string, err error) { - var ires any - ires, err = c.ListEndpoint(ctx, nil) - if err != nil { - return - } - return ires.([]string), nil -} - -// Add calls the "add" endpoint of the "indexes" service. -// Add may return the following errors: -// - "invalid_url" (type *goa.ServiceError): url invalid -// - error: internal error -func (c *Client) Add(ctx context.Context, p *IndexPayload) (res *Operation, err error) { - var ires any - ires, err = c.AddEndpoint(ctx, p) - if err != nil { - return - } - return ires.(*Operation), nil -} - -// Remove calls the "remove" endpoint of the "indexes" service. -// Remove may return the following errors: -// - "invalid_url" (type *goa.ServiceError): url invalid -// - error: internal error -func (c *Client) Remove(ctx context.Context, p *IndexPayload) (res *Operation, err error) { - var ires any - ires, err = c.RemoveEndpoint(ctx, p) - if err != nil { - return - } - return ires.(*Operation), nil -} diff --git a/gen/indexes/endpoints.go b/gen/indexes/endpoints.go deleted file mode 100644 index cb08cb3c4..000000000 --- a/gen/indexes/endpoints.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes endpoints -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package indexes - -import ( - "context" - - goa "goa.design/goa/v3/pkg" -) - -// Endpoints wraps the "indexes" service endpoints. -type Endpoints struct { - List goa.Endpoint - Add goa.Endpoint - Remove goa.Endpoint -} - -// NewEndpoints wraps the methods of the "indexes" service with endpoints. -func NewEndpoints(s Service) *Endpoints { - return &Endpoints{ - List: NewListEndpoint(s), - Add: NewAddEndpoint(s), - Remove: NewRemoveEndpoint(s), - } -} - -// Use applies the given middleware to all the "indexes" service endpoints. -func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) { - e.List = m(e.List) - e.Add = m(e.Add) - e.Remove = m(e.Remove) -} - -// NewListEndpoint returns an endpoint function that calls the method "list" of -// service "indexes". -func NewListEndpoint(s Service) goa.Endpoint { - return func(ctx context.Context, req any) (any, error) { - return s.List(ctx) - } -} - -// NewAddEndpoint returns an endpoint function that calls the method "add" of -// service "indexes". -func NewAddEndpoint(s Service) goa.Endpoint { - return func(ctx context.Context, req any) (any, error) { - p := req.(*IndexPayload) - res, err := s.Add(ctx, p) - if err != nil { - return nil, err - } - vres := NewViewedOperation(res, "default") - return vres, nil - } -} - -// NewRemoveEndpoint returns an endpoint function that calls the method -// "remove" of service "indexes". -func NewRemoveEndpoint(s Service) goa.Endpoint { - return func(ctx context.Context, req any) (any, error) { - p := req.(*IndexPayload) - res, err := s.Remove(ctx, p) - if err != nil { - return nil, err - } - vres := NewViewedOperation(res, "default") - return vres, nil - } -} diff --git a/gen/indexes/service.go b/gen/indexes/service.go deleted file mode 100644 index 597c0abf2..000000000 --- a/gen/indexes/service.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes service -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package indexes - -import ( - "context" - - indexesviews "github.com/arduino/arduino-create-agent/gen/indexes/views" - goa "goa.design/goa/v3/pkg" -) - -// The indexes service manages the package_index files -type Service interface { - // List implements list. - List(context.Context) (res []string, err error) - // Add implements add. - Add(context.Context, *IndexPayload) (res *Operation, err error) - // Remove implements remove. - Remove(context.Context, *IndexPayload) (res *Operation, err error) -} - -// ServiceName is the name of the service as defined in the design. This is the -// same value that is set in the endpoint request contexts under the ServiceKey -// key. -const ServiceName = "indexes" - -// MethodNames lists the service method names as defined in the design. These -// are the same values that are set in the endpoint request contexts under the -// MethodKey key. -var MethodNames = [3]string{"list", "add", "remove"} - -// IndexPayload is the payload type of the indexes service add method. -type IndexPayload struct { - // The url of the index file - URL string -} - -// Operation is the result type of the indexes service add method. -type Operation struct { - // The status of the operation - Status string -} - -// MakeInvalidURL builds a goa.ServiceError from an error. -func MakeInvalidURL(err error) *goa.ServiceError { - return goa.NewServiceError(err, "invalid_url", false, false, false) -} - -// NewOperation initializes result type Operation from viewed result type -// Operation. -func NewOperation(vres *indexesviews.Operation) *Operation { - return newOperation(vres.Projected) -} - -// NewViewedOperation initializes viewed result type Operation from result type -// Operation using the given view. -func NewViewedOperation(res *Operation, view string) *indexesviews.Operation { - p := newOperationView(res) - return &indexesviews.Operation{Projected: p, View: "default"} -} - -// newOperation converts projected type Operation to service type Operation. -func newOperation(vres *indexesviews.OperationView) *Operation { - res := &Operation{} - if vres.Status != nil { - res.Status = *vres.Status - } - return res -} - -// newOperationView projects result type Operation to projected type -// OperationView using the "default" view. -func newOperationView(res *Operation) *indexesviews.OperationView { - vres := &indexesviews.OperationView{ - Status: &res.Status, - } - return vres -} diff --git a/gen/indexes/views/view.go b/gen/indexes/views/view.go deleted file mode 100644 index 4c8b42272..000000000 --- a/gen/indexes/views/view.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by goa v3.13.1, DO NOT EDIT. -// -// indexes views -// -// Command: -// $ goa gen github.com/arduino/arduino-create-agent/design - -package views - -import ( - goa "goa.design/goa/v3/pkg" -) - -// Operation is the viewed result type that is projected based on a view. -type Operation struct { - // Type to project - Projected *OperationView - // View to render - View string -} - -// OperationView is a type that runs validations on a projected type. -type OperationView struct { - // The status of the operation - Status *string -} - -var ( - // OperationMap is a map indexing the attribute names of Operation by view name. - OperationMap = map[string][]string{ - "default": { - "status", - }, - } -) - -// ValidateOperation runs the validations defined on the viewed result type -// Operation. -func ValidateOperation(result *Operation) (err error) { - switch result.View { - case "default", "": - err = ValidateOperationView(result.Projected) - default: - err = goa.InvalidEnumValueError("view", result.View, []any{"default"}) - } - return -} - -// ValidateOperationView runs the validations defined on OperationView using -// the "default" view. -func ValidateOperationView(result *OperationView) (err error) { - if result.Status == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("status", "result")) - } - return -} diff --git a/go.mod b/go.mod index 99704fd6a..16f74d6a7 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ require ( github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/stretchr/testify v1.8.4 github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 - go.bug.st/downloader/v2 v2.1.1 go.bug.st/serial v1.6.1 goa.design/goa/v3 v3.13.1 golang.org/x/crypto v0.13.0 diff --git a/go.sum b/go.sum index b070dd3f7..b05dfb663 100644 --- a/go.sum +++ b/go.sum @@ -166,8 +166,6 @@ github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 h1:w8V9v0qVympSF6GjdjIyeqR7+EVhAF9CBQmkmW7Zw0w= github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -go.bug.st/downloader/v2 v2.1.1 h1:nyqbUizo3E2IxCCm4YFac4FtSqqFpqWP+Aae5GCMuw4= -go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII= go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY= go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= goa.design/goa/v3 v3.13.1 h1:JRWJs1GSD5WWPvGq7Ru68au7BcxG+cA7fWCi/q4ONq0= diff --git a/tools/hidefile_darwin.go b/index/hidefile_default.go similarity index 73% rename from tools/hidefile_darwin.go rename to index/hidefile_default.go index b9f04e4c9..b777bcd5d 100644 --- a/tools/hidefile_darwin.go +++ b/index/hidefile_default.go @@ -13,21 +13,11 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package tools +//go:build !windows -import ( - "os/exec" -) +package index -func hideFile(path string) { - -} - -// TellCommandNotToSpawnShell will now spawn a shell -func TellCommandNotToSpawnShell(_ *exec.Cmd) { -} - -// MessageBox will open a dialog -func MessageBox(title, text string) int { - return 6 +// hideFile will do nothing in this platform +func hideFile(path string) error { + return nil } diff --git a/index/hidefile_windows.go b/index/hidefile_windows.go new file mode 100644 index 000000000..78a613d46 --- /dev/null +++ b/index/hidefile_windows.go @@ -0,0 +1,33 @@ +// Copyright 2022 Arduino SA +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package index + +import ( + "syscall" +) + +// hideFile will set the hidden attribute on the file +func hideFile(path string) error { + filenameW, err := syscall.UTF16PtrFromString(path) + if err != nil { + return err + } + err = syscall.SetFileAttributes(filenameW, syscall.FILE_ATTRIBUTE_HIDDEN) + if err != nil { + return err + } + return nil +} diff --git a/index/index.go b/index/index.go new file mode 100644 index 000000000..6ec0a4bb7 --- /dev/null +++ b/index/index.go @@ -0,0 +1,146 @@ +// Copyright 2022 Arduino SA +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package index + +import ( + "bytes" + "encoding/hex" + "io" + "log" + "net/http" + "net/url" + "path" + "time" + + "github.com/arduino/go-paths-helper" + "golang.org/x/crypto/openpgp" +) + +// Resource represent the index of the system +type Resource struct { + LastRefresh time.Time // Last time the index was downloaded + IndexURL url.URL // The URL used to host the index.json + IndexFile paths.Path // The location of the index on the filesystem + IndexSignature paths.Path // The location of the signature on the filesystem +} + +// gpg --export YOURKEYID --export-options export-minimal,no-export-attributes | hexdump /dev/stdin -v -e '/1 "%02X"' +var publicKeyHex string = "99020D0452FAA2FA011000D0C5604932111750628F171E4E612D599ABEA8E4309888B9B9E87CCBD3AAD014B27454B0AF08E7CDD019DA72D492B6CF882AD7FA8571E985C538582DA096C371E7FCD95B71BC00C0E92BDDC26801F1B11C86814E0EA849E5973F630FC426E6A5F262C22986CB489B5304005202BA729D519725E3E6042C9199C8ECE734052B7376CF40A864679C3594C93203EBFB3F82CD42CD956F961792233B4C7C1A28252360F48F1D6D8662F2CF93F87DB40A99304F61828AF8A3EB07239E984629DC0B1D5C6494C9AFB5C8F8B9A53F1324C254A1AEA4CD9219AB4DF8667653AC9A6E76C3DB37CE8F60B546F78ECA43A90CB82A2278A291D2E98D66753B56F0595280C6E33B274F631846806D97447DD5C9438E7EC85779D9FA2173E088CE6FA156E291FAFD432C4FC2B1EB251DAFD13C721FF6618F696B77C122FB75E3CBCB446FAAA7FFFDD071C81C6C3D2360D495964C623617352915BBB30FA7C903EA096BF01E77FC84C8B51C02EB11BC9F03F19C7E81254F1F786E64A7A9F7F438873583CFA40F49C0F041432EAECCEC7EE9BA465A30320306F0E2E65EBE01E533CBBD8B1C1C04222213D5D05F4B689193DB60A68A6F1FC8B2ADD9E58A104E482AAD3869CCC42236EDC9CBE8561E105837AB6F7A764DCE5D8CB62608E8133F0FDD5F8FAFBE3BC57EE551ADC7386AADD443B331716EC032ACF9C639BF9DFE62301D4F197221F10DEF0011010001B42041726475696E6F204C4C43203C737570706F72744061726475696E6F2E63633E890238041301020022050252FAA2FA021B03060B090807030206150802090A0B0416020301021E01021780000A09107BAF404C2DFAB4AEF8090FFE20C3B36BF786D692969DA2ECFD7BCA3961E735D3CBB5585D7AB04BB8A0B64B64528ED76DB4752FA24523AA1E07B69A6A66CDDAE074A6A572800228194DD5916A956BF22606D866C7FD81F32878E06FEC200DDB0703D805E1A61006EB0B5BDB3AA89C095BB259BD93C7AAE8BDB18468A6DBE30F85BD6A3271F5456EB22BC2BCE99DB3A054D9BCA8F562C01B99E6BF4C2136B62771EEF54CB2AE95F8E2FE543284C37EB77E5104D49939ABAEF323CA5F1A66CA48ED423DBB3A2CFF12792CCA71ACD1E3032186CC7D05A13E0D66A3258E443527AAF921B7EA70C6CC10E2A51FCAB4DD130A10D3D29B1B01FB4207EF6501D3A9186BDB652ECCC9F354599A114DD3F80F9ED3493AC51A5C4F1F3BB59049EE7EC61411E90E02F27789E87B18A860551DFDFFA870E8542F6128E167CE1875C5C5B1128259347B85265487006B173AA631F1CDA1EDC68C54978E1D0FE3B310CC0F49F9AE84F37B1472437B69DA125BAFDC99AE57C2245F70747E1EFD52849C40469247CF13CB679A31AF4700468E09ED1ECFE5A53F67C80C48A0B0C1334FAE9650584DFD406ADA30FFBEED659256D40924432B029BBB24CEF22195D389381F0B1EB964C6494942335E74A373D869D1FB0C7967F30F79D71AB06929CEBB660514C2567284BD9EC32470B263539B3AFF5D3FBA9A275D4665E6B502B4031B63F511C1DFDD16B617A6FB046FCEB018A7A01CEFB9020D0452FAA2FA011000D6DE1747395EB3836103D30FA5CF555F6FBC982FB8B0FD72389CD6E99A88ACA1BCBD8BAD35211929AB5AB7F656BA1AFFA8C9A5AF83436FC8FE36AB403453E3E6EC679371AD81657FA1506956B1165D8887E3FB7EF366EFCCA82EE543E0B22170D0164A6702EF5280398A901CB6262E63C0AE378FD8CA1957EEED9CE48AA3D481BD117A2CA0341C3E16FE20CB6A5C3130A19B364F656CDC45E2216DE7ACFAD429967D71D101CADE10BA64F4075801ED2E9E3A3293114543456A26236CCA459DC7700D2E9C692BADCA9BA0CDE7189CD594B20CA4D1F20A70B02B9B50F70CFC6F7697B1D500702CE29492C7CD28C5D555475788DDE57482BC39E8465A720E25866AC931D5D7030AB61136BF702B25BC850A5089D1E6F0F68B8AE894ADFC3C92BB836888E3DB5A940426DBE7BBC5BDD3DDD6F5123627D1CE6FD1845CC66A920094391BE783069CB05746C0A55DAFC869FDAF0A08F81099E4F4CD07D05C7269C538C341CF1EDB94114B8CD97B44214EA58EEDB93FAB772013A1D77A08B9208082F9617A6CFE39B56F0078406C6267ABF5CF1078C49B1AB9B60EA1451351CF889EF72D7D696B23B22F753B28979AF10237B579A350FA5596A3B22244FA91402562AE530E814EF19A9E3448F465F78C16220DE0663F7B97C7F0EF1629E2F64A76B21BB695A3DE505B22B09B3459A3CE2180424BD67C8482EBD5EBC8128F98634EEE8707001101000189021F041801020009050252FAA2FA021B0C000A09107BAF404C2DFAB4AE050B1000C1434E8CC0D6F8E60E2FB091AA5EA04E7612B29D3823E09914F704DE1835A7B202D3F619183BD3A16439BFA31A6AF342672E8F59184333C4F56D18AF3B7CE8326F655F7C8DD1D4B38A1964E6A4D7550D159CE1B5EC44BC2091B1097CABE724C0E8C4942C2CF82672E3F209322270D133313CF601E07756B705946A45235DAF7294BCD34292D989EFDFDA2F46AF0AEAEC72F55DC6B2940C7C6A409B7FAD3354D5CA30C3E4EE29F9218A56EF8D7FBA2A7BB8E6304110A21DF0C847C4B761CDE408CE156D53091535A800C1C522CA33C71105B11550A145FD0E41B464146B46D46F08DFAEF9B03D313D54A1E4A82E8749895AB78521DAA8E66EEF6F7B17A0CA4B4CBFCB937713B9806269556EBD88AE87996EFAC0846ACBA0D3412FC0A5E90923C261CD443E4D6C1AE93D83166937C5F606A14FD73DB4919A0ED416D4B3163420F57FACCE9C9347BD5501BE3FC830472B64068E5FF5B09E7425030625246720D21608DEE829F84E8365527F764C91DA93372C72AA4054B458104CAFC2BDCED63DC80F36E7BD4BE0D3A19E20E3FED90F80F9E1584853B971B8E847C27027123B9AA19C3E90B41B3A643D3D5BE2FC134ADA8396D072D37E7101B64CE83E1802D0D5DDA9150B6C21564987950C9601FC2147F139C7A9906640A0883981B452F25AF7A0F32FAA2148ECDD9B04B93AFCED00F11AA0E6695C2F92676B8DB9E93172FD7779B9020D04530B05A7011000CAA1A8FF4BF9D0F0AC9EDBCA3B4D26E3E569DFEA04341F3E6ACE23AE5D87D62C2600DFF10B106144A1B52FF8B695A590D65C681F69DEE454800C235160EBE3FC1436193E1278D56C86E2BBB2187BEAAC1E1D04D40A392B1457471D10A2B6BF39CDF35D1A090A9406BCB06BDEF83A12A490C5E17D68884AD2686042669E2B458AD3CC0377DDA9C58D7070CE29A53E0E7C876D61B29A2DE2A9D73F914D0FF3B0E35E2ED361B60A8C3C3D4C7E77E17A939283BFDA2EC5725A2BFAAC18C6A64ACBEC776760D7086EA42BD93031E8B59FB8DFEFF77E5F80DBEB84ADE74B3A6F9E4D0F3140A8D0F576ED00548883C85271AA7F2450D1061F56CB839786038861D5A2473B7F58EBC00D2BB9EFEB1A2DF612A7B9087C326FBB08F2879102253316784272967A886089D61D5AB0FDB33737D35F27C2886ABB4D4E88F541D0BBAD04AEF7BD3ED66A1282B762BD6F8EEDC3760773B157C1A2D4E4586E43B28879C54E7599F9A34E1524E6E7F9B8EA13CC5A2DF5C1920AF74833EDDEC8EB9A8BE33196702DFD656D81ACBBFE3A10DA882EAA3065D9C9476C0A7B66C15D0063CB7AD1A2EB31537CB443F21B81642436943FE6C45E6AF9C2B595D4DFCB64B83F2CA6B4DD536726C6EC4761A340C18E32B2D7210640B9AB1D8E2165C0DD38BC9FD9DB6A30B380DF08C3F10002A6636FDC79CD2312B606F5F116AC665618A56BBE46C494FC7E23C7001101000189043E0418010200090502530B05A7021B02022909107BAF404C2DFAB4AEC15D200419010200060502530B05A7000A091024A26BAD7F29429187700FFE30ED1B7C96B3846AC7B363F9602D2886F7913A9C451C31E043AD75597024D460B59E6A60A6EE3D58E656901237A2465F8402169A816B38170AF550284EB420B7E827386D66852D68125A27FA6770F139EE7FCAEF43000673B7C7D168614877603C875AD593E333AE9237DB77065FB8375CE98FA1BF7FB1733034AAC61F1D23A3EFF8665702C10968C7991458F88D151B3448C7D9334059431A63D30A9C8E636A99D88DA8DB04CB8C64F1183AC873FF0942EF9555B6B3F192AD5F221AC9737F875CCAE21E88EC45CB35E40C0FF1AAF0A8FE44876D93A930A03CC4846A29102C956F39F2AC5808CCBCD7F4868A8E8E8B9A66EA18C275CEF9C371AB0592796ED57D757A3BAB31FF8E3887F6041E61BDA433E7D68CB2D5F28E81F57843D5032D73BF67119C137FC4CE8BEF4F705D690E47A530B1A85B8B6A09A4AE16A2973C11D69031B89BE92B0751DB7FE74F6F1C219C8B93E5C68EC1403856DF28E96E27737A7FB9C80F6EE9EC485A0609DC4EB8DF444F61C76A97F32ADFA2D8B4784DF3ABA4DE1B57894B9CF89934A143451308D73CF79ECC8BF382B8A34F24DC335238D8353767B363F5432D9A81C84F7D2FAB6E36E7188FA911120A905C67342A996251EBECAC13BD543A9B3C2C063AE294FDD15C66D5DD9224F3E936325F525700F2129D0B31CE8CCD4EBA5DEDB89F0A2BFC0C43E732F695161E4F33CE5DED14B1E98654547B110FFF7CBC2BA513721A96DD18964635069343FA8EEF4D492BFA55C930F9C78DF1F7454F1BDD40F4B04BDE9F9B9A9923A303D96D0CBFA361921AFEF13AED098D0CF70E84C0DDB20C58821351D2359B131671AAF5D2484717A4CAF385DB0CC19FBC37A3FC04F4F387D6934C1E84B9C1291231A14F69A1BF6708875C7DE00E3EFE3C7855A2459C96245C5F0D21FC00E87A0C18F80A3B79C0E28EA27493309C535254421BE7CDFBEFB5B44DAEA56B6859430FCCBEE766048F891AD5CB503866B98E521ED69B37E4165012A45E29836E2A0380728C1108E4C8A32EA186E1A855F78DA5506B6CF86DB888A87FAB6E15A90E3416469522DF5BD8872D729B35E6D82C974CD80076C26008015AB216C83FAF64E488F07D2BD01F51B0963F87BE0AB8392B442227BF7215148038B0C55189024D7C1B032DB1B3C56C66953E530C5B323634FC584A476CAD285EF1108011D14D9D180A75A9DFC936AFC7EF9E6C3F3CFEDD894894CE60358E7156B3A65ED7644DEA343A133F5D4DE4D33B74281086A0C20515AC4151CFED93C56DD574E578FDEE72C4115C25CAEC5EAD97C147F27F4EAE67FEFFEA0DC1CDF5D636AC331CB74DF477C9C3B3706F9DAF50C2E13AC8DE8CC9DD3C79E59EC779EE489D915CF22FDC53E3B3C7710FE8368DF11B9ACDF5F3CAE1F43CB7312E5E9F57F248692B3681CBA3E49207878FD33ED2A47CE9CE9B4E4A6EFD8F0AD2CD" + +// Init will initialize the IndexResource structure and will return it. +// It will take indexString as a paramenter. +func Init(indexString string, directory *paths.Path) *Resource { + if directory == nil { + log.Fatalf("configuration directory not provided") + } + if !directory.Exist() { + err := directory.Mkdir() + if err != nil { + log.Fatalf("cannot create config dir: %s", err) + } + err = hideFile(directory.String()) + if err != nil { + log.Printf("cannot make config dir hidden: %s", err) + } + } + indexParsed, err := url.Parse(indexString) + if err != nil { + log.Fatalf("cannot parse provided index: %s", indexString) + } + + indexFile := path.Base(indexParsed.Path) // == package_index.json + signatureFile := indexFile + ".sig" + + var ir = Resource{ + IndexURL: *indexParsed, + IndexFile: *directory.Join(indexFile), + IndexSignature: *directory.Join(signatureFile), + } + + if err := ir.DownloadAndVerify(); err != nil { + log.Fatalf("cannot download index: %s", err) + } + + return &ir +} + +// DownloadAndVerify will download an index file located at IndexURL and verify the signature +// if everything matches the files are overwritten +func (ir *Resource) DownloadAndVerify() error { + // Fetch the index + resp, err := http.Get(ir.IndexURL.String()) + if err != nil { + return err + } + defer resp.Body.Close() + + // Read the index body + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + // Fetch the signature + signature, err := http.Get(ir.IndexURL.String() + ".sig") + if err != nil { + return err + } + defer signature.Body.Close() + + // Read the signature body + signatureBody, err := io.ReadAll(signature.Body) + if err != nil { + return err + } + + err = checkGPGSig(bytes.NewReader(body), bytes.NewReader(signatureBody)) + if err != nil { + return err + } + + // we overwrite the files if the signature is valid + ir.IndexFile.WriteFile(body) + ir.IndexSignature.WriteFile(signatureBody) + + ir.LastRefresh = time.Now() + + return nil +} + +// checkGPGSign takes a signed io.Reader and a detached signature io.Reader +// and returns if the signature is valid +func checkGPGSig(signed, signature io.Reader) error { + publicKeyBin, err := hex.DecodeString(publicKeyHex) + if err != nil { + return err + } + keyring, _ := openpgp.ReadKeyRing(bytes.NewReader(publicKeyBin)) + + _, err = openpgp.CheckDetachedSignature(keyring, signed, signature) + return err +} + +// Read will read the index file. In case it doesn't exists or the latest downloaded +// version is older than 1 hour, it will be downloaded again. +func (ir *Resource) Read() ([]byte, error) { + if !ir.IndexFile.Exist() || time.Since(ir.LastRefresh) > 1*time.Hour { + // Download the file again and save it + if err := ir.DownloadAndVerify(); err != nil { + return nil, err + } + } + return ir.IndexFile.ReadFile() +} diff --git a/index/index_test.go b/index/index_test.go new file mode 100644 index 000000000..ea6433574 --- /dev/null +++ b/index/index_test.go @@ -0,0 +1,25 @@ +package index + +import ( + "net/url" + "testing" + + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/require" +) + +func TestInit(t *testing.T) { + indexURL := "https://downloads.arduino.cc/packages/package_staging_index.json" + // Instantiate Index + tempDir := paths.New(t.TempDir()).Join(".arduino-create") + Index := Init(indexURL, tempDir) + require.DirExists(t, tempDir.String()) + fileName := "package_staging_index.json" + signatureName := fileName + ".sig" + parsedURL, _ := url.Parse(indexURL) + require.Equal(t, Index.IndexURL, *parsedURL) + require.Contains(t, Index.IndexFile.String(), fileName) + require.Contains(t, Index.IndexSignature.String(), signatureName) + require.FileExists(t, tempDir.Join(fileName).String()) + require.FileExists(t, tempDir.Join(signatureName).String()) +} diff --git a/main.go b/main.go index 2d115f61a..671c6333e 100755 --- a/main.go +++ b/main.go @@ -36,6 +36,7 @@ import ( cert "github.com/arduino/arduino-create-agent/certificates" "github.com/arduino/arduino-create-agent/config" "github.com/arduino/arduino-create-agent/globals" + "github.com/arduino/arduino-create-agent/index" "github.com/arduino/arduino-create-agent/systray" "github.com/arduino/arduino-create-agent/tools" "github.com/arduino/arduino-create-agent/updater" @@ -48,11 +49,10 @@ import ( ) var ( - version = "x.x.x-dev" //don't modify it, Jenkins will take care - commit = "xxxxxxxx" //don't modify it, Jenkins will take care - port string - portSSL string - requiredToolsAPILevel = "v1" + version = "x.x.x-dev" //don't modify it, Jenkins will take care + commit = "xxxxxxxx" //don't modify it, Jenkins will take care + port string + portSSL string ) // regular flags @@ -99,6 +99,7 @@ var homeTemplateHTML string var ( Tools tools.Tools Systray systray.Systray + Index *index.Resource ) type logWriter struct{} @@ -176,17 +177,17 @@ func loop() { os.Exit(0) } - // Instantiate Tools - Tools = tools.Tools{ - Directory: config.GetDataDir().String(), - IndexURL: *indexURL, - Logger: func(msg string) { - mapD := map[string]string{"DownloadStatus": "Pending", "Msg": msg} - mapB, _ := json.Marshal(mapD) - h.broadcastSys <- mapB - }, + // Instantiate Index + Index = index.Init(*indexURL, config.GetDataDir()) + + logger := func(msg string) { + mapD := map[string]string{"DownloadStatus": "Pending", "Msg": msg} + mapB, _ := json.Marshal(mapD) + h.broadcastSys <- mapB } - Tools.Init(requiredToolsAPILevel) + + // Instantiate Tools + Tools = *tools.New(config.GetDataDir(), Index, logger) // Let's handle the config configDir := config.GetDefaultConfigDir() @@ -397,7 +398,7 @@ func loop() { r.POST("/update", updateHandler) // Mount goa handlers - goa := v2.Server(config.GetDataDir().String()) + goa := v2.Server(config.GetDataDir().String(), Index) r.Any("/v2/*path", gin.WrapH(goa)) go func() { diff --git a/main_test.go b/main_test.go index c2fb2489e..57c5b2f8e 100644 --- a/main_test.go +++ b/main_test.go @@ -29,6 +29,7 @@ import ( "github.com/arduino/arduino-create-agent/config" "github.com/arduino/arduino-create-agent/gen/tools" + "github.com/arduino/arduino-create-agent/index" "github.com/arduino/arduino-create-agent/upload" v2 "github.com/arduino/arduino-create-agent/v2" "github.com/gin-gonic/gin" @@ -87,8 +88,13 @@ func TestUploadHandlerAgainstEvilFileNames(t *testing.T) { } func TestInstallToolV2(t *testing.T) { + + indexURL := "https://downloads.arduino.cc/packages/package_staging_index.json" + // Instantiate Index + Index := index.Init(indexURL, config.GetDataDir()) + r := gin.New() - goa := v2.Server(config.GetDataDir().String()) + goa := v2.Server(config.GetDataDir().String(), Index) r.Any("/v2/*path", gin.WrapH(goa)) ts := httptest.NewServer(r) @@ -140,7 +146,7 @@ func TestInstallToolV2(t *testing.T) { {bossacInstallURLOK, http.StatusOK, "ok"}, {bossacInstallWrongSig, http.StatusInternalServerError, "verification error"}, {bossacInstallWrongCheck, http.StatusInternalServerError, "checksum doesn't match"}, - {bossacInstallNoURL, http.StatusBadRequest, "tool not found"}, //because the index is not added + {bossacInstallNoURL, http.StatusOK, "ok"}, } for _, test := range tests { diff --git a/tests/conftest.py b/tests/conftest.py index b39bbeb47..d2c59c7cc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -43,7 +43,7 @@ def agent(pytestconfig): # we give some time to the agent to start and listen to # incoming requests - time.sleep(.5) + time.sleep(1) # we block here until the test function using this fixture has returned yield runner diff --git a/tools/download.go b/tools/download.go index 939e7a304..76f4056c5 100644 --- a/tools/download.go +++ b/tools/download.go @@ -34,9 +34,6 @@ import ( "path/filepath" "runtime" "strings" - "time" - - "golang.org/x/crypto/openpgp" "github.com/arduino/arduino-create-agent/utilities" "github.com/arduino/arduino-create-agent/v2/pkgs" @@ -53,72 +50,6 @@ func mimeType(data []byte) (string, error) { return http.DetectContentType(data[0:512]), nil } -// gpg --export YOURKEYID --export-options export-minimal,no-export-attributes | hexdump /dev/stdin -v -e '/1 "%02X"' -var publicKeyHex string = "99020D0452FAA2FA011000D0C5604932111750628F171E4E612D599ABEA8E4309888B9B9E87CCBD3AAD014B27454B0AF08E7CDD019DA72D492B6CF882AD7FA8571E985C538582DA096C371E7FCD95B71BC00C0E92BDDC26801F1B11C86814E0EA849E5973F630FC426E6A5F262C22986CB489B5304005202BA729D519725E3E6042C9199C8ECE734052B7376CF40A864679C3594C93203EBFB3F82CD42CD956F961792233B4C7C1A28252360F48F1D6D8662F2CF93F87DB40A99304F61828AF8A3EB07239E984629DC0B1D5C6494C9AFB5C8F8B9A53F1324C254A1AEA4CD9219AB4DF8667653AC9A6E76C3DB37CE8F60B546F78ECA43A90CB82A2278A291D2E98D66753B56F0595280C6E33B274F631846806D97447DD5C9438E7EC85779D9FA2173E088CE6FA156E291FAFD432C4FC2B1EB251DAFD13C721FF6618F696B77C122FB75E3CBCB446FAAA7FFFDD071C81C6C3D2360D495964C623617352915BBB30FA7C903EA096BF01E77FC84C8B51C02EB11BC9F03F19C7E81254F1F786E64A7A9F7F438873583CFA40F49C0F041432EAECCEC7EE9BA465A30320306F0E2E65EBE01E533CBBD8B1C1C04222213D5D05F4B689193DB60A68A6F1FC8B2ADD9E58A104E482AAD3869CCC42236EDC9CBE8561E105837AB6F7A764DCE5D8CB62608E8133F0FDD5F8FAFBE3BC57EE551ADC7386AADD443B331716EC032ACF9C639BF9DFE62301D4F197221F10DEF0011010001B42041726475696E6F204C4C43203C737570706F72744061726475696E6F2E63633E890238041301020022050252FAA2FA021B03060B090807030206150802090A0B0416020301021E01021780000A09107BAF404C2DFAB4AEF8090FFE20C3B36BF786D692969DA2ECFD7BCA3961E735D3CBB5585D7AB04BB8A0B64B64528ED76DB4752FA24523AA1E07B69A6A66CDDAE074A6A572800228194DD5916A956BF22606D866C7FD81F32878E06FEC200DDB0703D805E1A61006EB0B5BDB3AA89C095BB259BD93C7AAE8BDB18468A6DBE30F85BD6A3271F5456EB22BC2BCE99DB3A054D9BCA8F562C01B99E6BF4C2136B62771EEF54CB2AE95F8E2FE543284C37EB77E5104D49939ABAEF323CA5F1A66CA48ED423DBB3A2CFF12792CCA71ACD1E3032186CC7D05A13E0D66A3258E443527AAF921B7EA70C6CC10E2A51FCAB4DD130A10D3D29B1B01FB4207EF6501D3A9186BDB652ECCC9F354599A114DD3F80F9ED3493AC51A5C4F1F3BB59049EE7EC61411E90E02F27789E87B18A860551DFDFFA870E8542F6128E167CE1875C5C5B1128259347B85265487006B173AA631F1CDA1EDC68C54978E1D0FE3B310CC0F49F9AE84F37B1472437B69DA125BAFDC99AE57C2245F70747E1EFD52849C40469247CF13CB679A31AF4700468E09ED1ECFE5A53F67C80C48A0B0C1334FAE9650584DFD406ADA30FFBEED659256D40924432B029BBB24CEF22195D389381F0B1EB964C6494942335E74A373D869D1FB0C7967F30F79D71AB06929CEBB660514C2567284BD9EC32470B263539B3AFF5D3FBA9A275D4665E6B502B4031B63F511C1DFDD16B617A6FB046FCEB018A7A01CEFB9020D0452FAA2FA011000D6DE1747395EB3836103D30FA5CF555F6FBC982FB8B0FD72389CD6E99A88ACA1BCBD8BAD35211929AB5AB7F656BA1AFFA8C9A5AF83436FC8FE36AB403453E3E6EC679371AD81657FA1506956B1165D8887E3FB7EF366EFCCA82EE543E0B22170D0164A6702EF5280398A901CB6262E63C0AE378FD8CA1957EEED9CE48AA3D481BD117A2CA0341C3E16FE20CB6A5C3130A19B364F656CDC45E2216DE7ACFAD429967D71D101CADE10BA64F4075801ED2E9E3A3293114543456A26236CCA459DC7700D2E9C692BADCA9BA0CDE7189CD594B20CA4D1F20A70B02B9B50F70CFC6F7697B1D500702CE29492C7CD28C5D555475788DDE57482BC39E8465A720E25866AC931D5D7030AB61136BF702B25BC850A5089D1E6F0F68B8AE894ADFC3C92BB836888E3DB5A940426DBE7BBC5BDD3DDD6F5123627D1CE6FD1845CC66A920094391BE783069CB05746C0A55DAFC869FDAF0A08F81099E4F4CD07D05C7269C538C341CF1EDB94114B8CD97B44214EA58EEDB93FAB772013A1D77A08B9208082F9617A6CFE39B56F0078406C6267ABF5CF1078C49B1AB9B60EA1451351CF889EF72D7D696B23B22F753B28979AF10237B579A350FA5596A3B22244FA91402562AE530E814EF19A9E3448F465F78C16220DE0663F7B97C7F0EF1629E2F64A76B21BB695A3DE505B22B09B3459A3CE2180424BD67C8482EBD5EBC8128F98634EEE8707001101000189021F041801020009050252FAA2FA021B0C000A09107BAF404C2DFAB4AE050B1000C1434E8CC0D6F8E60E2FB091AA5EA04E7612B29D3823E09914F704DE1835A7B202D3F619183BD3A16439BFA31A6AF342672E8F59184333C4F56D18AF3B7CE8326F655F7C8DD1D4B38A1964E6A4D7550D159CE1B5EC44BC2091B1097CABE724C0E8C4942C2CF82672E3F209322270D133313CF601E07756B705946A45235DAF7294BCD34292D989EFDFDA2F46AF0AEAEC72F55DC6B2940C7C6A409B7FAD3354D5CA30C3E4EE29F9218A56EF8D7FBA2A7BB8E6304110A21DF0C847C4B761CDE408CE156D53091535A800C1C522CA33C71105B11550A145FD0E41B464146B46D46F08DFAEF9B03D313D54A1E4A82E8749895AB78521DAA8E66EEF6F7B17A0CA4B4CBFCB937713B9806269556EBD88AE87996EFAC0846ACBA0D3412FC0A5E90923C261CD443E4D6C1AE93D83166937C5F606A14FD73DB4919A0ED416D4B3163420F57FACCE9C9347BD5501BE3FC830472B64068E5FF5B09E7425030625246720D21608DEE829F84E8365527F764C91DA93372C72AA4054B458104CAFC2BDCED63DC80F36E7BD4BE0D3A19E20E3FED90F80F9E1584853B971B8E847C27027123B9AA19C3E90B41B3A643D3D5BE2FC134ADA8396D072D37E7101B64CE83E1802D0D5DDA9150B6C21564987950C9601FC2147F139C7A9906640A0883981B452F25AF7A0F32FAA2148ECDD9B04B93AFCED00F11AA0E6695C2F92676B8DB9E93172FD7779B9020D04530B05A7011000CAA1A8FF4BF9D0F0AC9EDBCA3B4D26E3E569DFEA04341F3E6ACE23AE5D87D62C2600DFF10B106144A1B52FF8B695A590D65C681F69DEE454800C235160EBE3FC1436193E1278D56C86E2BBB2187BEAAC1E1D04D40A392B1457471D10A2B6BF39CDF35D1A090A9406BCB06BDEF83A12A490C5E17D68884AD2686042669E2B458AD3CC0377DDA9C58D7070CE29A53E0E7C876D61B29A2DE2A9D73F914D0FF3B0E35E2ED361B60A8C3C3D4C7E77E17A939283BFDA2EC5725A2BFAAC18C6A64ACBEC776760D7086EA42BD93031E8B59FB8DFEFF77E5F80DBEB84ADE74B3A6F9E4D0F3140A8D0F576ED00548883C85271AA7F2450D1061F56CB839786038861D5A2473B7F58EBC00D2BB9EFEB1A2DF612A7B9087C326FBB08F2879102253316784272967A886089D61D5AB0FDB33737D35F27C2886ABB4D4E88F541D0BBAD04AEF7BD3ED66A1282B762BD6F8EEDC3760773B157C1A2D4E4586E43B28879C54E7599F9A34E1524E6E7F9B8EA13CC5A2DF5C1920AF74833EDDEC8EB9A8BE33196702DFD656D81ACBBFE3A10DA882EAA3065D9C9476C0A7B66C15D0063CB7AD1A2EB31537CB443F21B81642436943FE6C45E6AF9C2B595D4DFCB64B83F2CA6B4DD536726C6EC4761A340C18E32B2D7210640B9AB1D8E2165C0DD38BC9FD9DB6A30B380DF08C3F10002A6636FDC79CD2312B606F5F116AC665618A56BBE46C494FC7E23C7001101000189043E0418010200090502530B05A7021B02022909107BAF404C2DFAB4AEC15D200419010200060502530B05A7000A091024A26BAD7F29429187700FFE30ED1B7C96B3846AC7B363F9602D2886F7913A9C451C31E043AD75597024D460B59E6A60A6EE3D58E656901237A2465F8402169A816B38170AF550284EB420B7E827386D66852D68125A27FA6770F139EE7FCAEF43000673B7C7D168614877603C875AD593E333AE9237DB77065FB8375CE98FA1BF7FB1733034AAC61F1D23A3EFF8665702C10968C7991458F88D151B3448C7D9334059431A63D30A9C8E636A99D88DA8DB04CB8C64F1183AC873FF0942EF9555B6B3F192AD5F221AC9737F875CCAE21E88EC45CB35E40C0FF1AAF0A8FE44876D93A930A03CC4846A29102C956F39F2AC5808CCBCD7F4868A8E8E8B9A66EA18C275CEF9C371AB0592796ED57D757A3BAB31FF8E3887F6041E61BDA433E7D68CB2D5F28E81F57843D5032D73BF67119C137FC4CE8BEF4F705D690E47A530B1A85B8B6A09A4AE16A2973C11D69031B89BE92B0751DB7FE74F6F1C219C8B93E5C68EC1403856DF28E96E27737A7FB9C80F6EE9EC485A0609DC4EB8DF444F61C76A97F32ADFA2D8B4784DF3ABA4DE1B57894B9CF89934A143451308D73CF79ECC8BF382B8A34F24DC335238D8353767B363F5432D9A81C84F7D2FAB6E36E7188FA911120A905C67342A996251EBECAC13BD543A9B3C2C063AE294FDD15C66D5DD9224F3E936325F525700F2129D0B31CE8CCD4EBA5DEDB89F0A2BFC0C43E732F695161E4F33CE5DED14B1E98654547B110FFF7CBC2BA513721A96DD18964635069343FA8EEF4D492BFA55C930F9C78DF1F7454F1BDD40F4B04BDE9F9B9A9923A303D96D0CBFA361921AFEF13AED098D0CF70E84C0DDB20C58821351D2359B131671AAF5D2484717A4CAF385DB0CC19FBC37A3FC04F4F387D6934C1E84B9C1291231A14F69A1BF6708875C7DE00E3EFE3C7855A2459C96245C5F0D21FC00E87A0C18F80A3B79C0E28EA27493309C535254421BE7CDFBEFB5B44DAEA56B6859430FCCBEE766048F891AD5CB503866B98E521ED69B37E4165012A45E29836E2A0380728C1108E4C8A32EA186E1A855F78DA5506B6CF86DB888A87FAB6E15A90E3416469522DF5BD8872D729B35E6D82C974CD80076C26008015AB216C83FAF64E488F07D2BD01F51B0963F87BE0AB8392B442227BF7215148038B0C55189024D7C1B032DB1B3C56C66953E530C5B323634FC584A476CAD285EF1108011D14D9D180A75A9DFC936AFC7EF9E6C3F3CFEDD894894CE60358E7156B3A65ED7644DEA343A133F5D4DE4D33B74281086A0C20515AC4151CFED93C56DD574E578FDEE72C4115C25CAEC5EAD97C147F27F4EAE67FEFFEA0DC1CDF5D636AC331CB74DF477C9C3B3706F9DAF50C2E13AC8DE8CC9DD3C79E59EC779EE489D915CF22FDC53E3B3C7710FE8368DF11B9ACDF5F3CAE1F43CB7312E5E9F57F248692B3681CBA3E49207878FD33ED2A47CE9CE9B4E4A6EFD8F0AD2CD" - -func checkGPGSig(fileName string, sigFileName string) error { - - // Get a Reader for the signature file - sigFile, err := os.Open(sigFileName) - if err != nil { - return err - } - defer sigFile.Close() - - // Get a Reader for the signature file - file, err := os.Open(fileName) - if err != nil { - return err - } - defer file.Close() - - publicKeyBin, err := hex.DecodeString(publicKeyHex) - if err != nil { - return err - } - - keyring, _ := openpgp.ReadKeyRing(bytes.NewReader(publicKeyBin)) - - _, err = openpgp.CheckDetachedSignature(keyring, file, sigFile) - - return err -} - -// DownloadPackageIndex will download a package_index file -func (t *Tools) DownloadPackageIndex(indexFile, signatureFile string) error { - // Fetch the index - resp, err := http.Get(t.IndexURL) - if err != nil { - return err - } - defer resp.Body.Close() - - // Read the body - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - // Fetch the signature - signature, err := http.Get(t.IndexURL + ".sig") - if err != nil { - return err - } - defer signature.Body.Close() - - // Read the body - signatureBody, err := io.ReadAll(signature.Body) - if err != nil { - return err - } - os.WriteFile(indexFile, body, 0644) - os.WriteFile(signatureFile, signatureBody, 0644) - - t.LastRefresh = time.Now() - - return nil -} - func pathExists(path string) bool { _, err := os.Stat(path) if err == nil { @@ -147,23 +78,7 @@ func pathExists(path string) bool { // if it already exists. func (t *Tools) Download(pack, name, version, behaviour string) error { - indexFile := path.Join(t.Directory, "package_index.json") - signatureFile := path.Join(t.Directory, "package_index.json.sig") - - if _, err := os.Stat(path.Join(t.Directory, "package_index.json")); err != nil || time.Since(t.LastRefresh) > 1*time.Hour { - // Download the file again and save it - err = t.DownloadPackageIndex(indexFile, signatureFile) - if err != nil { - return err - } - } - - err := checkGPGSig(indexFile, signatureFile) - if err != nil { - return err - } - - body, err := os.ReadFile(indexFile) + body, err := t.index.Read() if err != nil { return err } @@ -175,7 +90,7 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { correctTool, correctSystem := findTool(pack, name, version, data) if correctTool.Name == "" || correctSystem.URL == "" { - t.Logger("We couldn't find a tool with the name " + name + " and version " + version + " packaged by " + pack) + t.logger("We couldn't find a tool with the name " + name + " and version " + version + " packaged by " + pack) return nil } @@ -183,21 +98,17 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { // Check if it already exists if behaviour == "keep" { - t.mutex.RLock() - location, ok := t.installed[key] - t.mutex.RUnlock() + location, ok := t.getMapValue(key) if ok && pathExists(location) { // overwrite the default tool with this one - t.mutex.Lock() - t.installed[correctTool.Name] = location - t.mutex.Unlock() - t.Logger("The tool is already present on the system") + t.setMapValue(correctTool.Name, location) + t.logger("The tool is already present on the system") return t.writeMap() } } // Download the tool - t.Logger("Downloading tool " + name + " from " + correctSystem.URL) + t.logger("Downloading tool " + name + " from " + correctSystem.URL) resp, err := http.Get(correctSystem.URL) if err != nil { return err @@ -219,9 +130,9 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { } // Decompress - t.Logger("Unpacking tool " + name) + t.logger("Unpacking tool " + name) - location := path.Join(dir(), pack, correctTool.Name, correctTool.Version) + location := t.directory.Join(pack, correctTool.Name, correctTool.Version).String() err = os.RemoveAll(location) if err != nil { @@ -235,18 +146,18 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { switch srcType { case "application/zip": - location, err = extractZip(t.Logger, body, location) + location, err = extractZip(t.logger, body, location) case "application/x-bz2": case "application/octet-stream": - location, err = extractBz2(t.Logger, body, location) + location, err = extractBz2(t.logger, body, location) case "application/x-gzip": - location, err = extractTarGz(t.Logger, body, location) + location, err = extractTarGz(t.logger, body, location) default: return errors.New("Unknown extension for file " + correctSystem.URL) } if err != nil { - t.Logger("Error extracting the archive: " + err.Error()) + t.logger("Error extracting the archive: " + err.Error()) return err } @@ -256,15 +167,13 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { } // Ensure that the files are executable - t.Logger("Ensure that the files are executable") + t.logger("Ensure that the files are executable") // Update the tool map - t.Logger("Updating map with location " + location) + t.logger("Updating map with location " + location) - t.mutex.Lock() - t.installed[name] = location - t.installed[name+"-"+correctTool.Version] = location - t.mutex.Unlock() + t.setMapValue(name, location) + t.setMapValue(name+"-"+correctTool.Version, location) return t.writeMap() } @@ -560,11 +469,11 @@ func (t *Tools) installDrivers(location string) error { preamble = "./" } if _, err := os.Stat(filepath.Join(location, "post_install"+extension)); err == nil { - t.Logger("Installing drivers") + t.logger("Installing drivers") ok := MessageBox("Installing drivers", "We are about to install some drivers needed to use Arduino/Genuino boards\nDo you want to continue?") if ok == OkPressed { os.Chdir(location) - t.Logger(preamble + "post_install" + extension) + t.logger(preamble + "post_install" + extension) oscmd := exec.Command(preamble + "post_install" + extension) if OS != "linux" { // spawning a shell could be the only way to let the user type his password diff --git a/tools/hidefile_linux.go b/tools/shell_default.go similarity index 96% rename from tools/hidefile_linux.go rename to tools/shell_default.go index b9f04e4c9..24a607a5d 100644 --- a/tools/hidefile_linux.go +++ b/tools/shell_default.go @@ -13,16 +13,14 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +//go:build !windows + package tools import ( "os/exec" ) -func hideFile(path string) { - -} - // TellCommandNotToSpawnShell will now spawn a shell func TellCommandNotToSpawnShell(_ *exec.Cmd) { } diff --git a/tools/hidefile_windows.go b/tools/shell_windows.go similarity index 88% rename from tools/hidefile_windows.go rename to tools/shell_windows.go index 632b87b34..55f665dea 100644 --- a/tools/hidefile_windows.go +++ b/tools/shell_windows.go @@ -21,13 +21,6 @@ import ( "unsafe" ) -func hideFile(path string) { - cpath, cpathErr := syscall.UTF16PtrFromString(path) - if cpathErr != nil { - } - syscall.SetFileAttributes(cpath, syscall.FILE_ATTRIBUTE_HIDDEN) -} - // TellCommandNotToSpawnShell will now spawn a shell func TellCommandNotToSpawnShell(oscmd *exec.Cmd) { oscmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} diff --git a/tools/tools.go b/tools/tools.go index e2ad321c5..ac3e6109b 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -17,66 +17,89 @@ package tools import ( "encoding/json" - "fmt" - "os" - "os/user" - "path" "path/filepath" "strings" "sync" - "time" + "github.com/arduino/arduino-create-agent/index" + "github.com/arduino/go-paths-helper" "github.com/xrash/smetrics" ) // Tools handle the tools necessary for an upload on a board. // It provides a means to download a tool from the arduino servers. // -// - *Directory* contains the location where the tools are downloaded. -// - *IndexURL* contains the url where the tools description is contained. -// - *Logger* is a StdLogger used for reporting debug and info messages -// - *installed* contains a map of the tools and their exact location +// - *directory* contains the location where the tools are downloaded. +// - *indexURL* contains the url where the tools description is contained. +// - *logger* is a StdLogger used for reporting debug and info messages +// - *installed* contains a map[string]string of the tools installed and their exact location // // Usage: -// You have to instantiate the struct by passing it the required parameters: -// _tools := tools.Tools{ -// Directory: "/home/user/.arduino-create", -// IndexURL: "https://downloads.arduino.cc/packages/package_index.json" -// Logger: log.Logger -// } +// You have to call the New() function passing it the required parameters: +// +// index = index.Init("https://downloads.arduino.cc/packages/package_staging_index.json", dataDir) +// tools := tools.New(dataDir, index, logger) // Tools will represent the installed tools type Tools struct { - Directory string - IndexURL string - LastRefresh time.Time - Logger func(msg string) - installed map[string]string - mutex sync.RWMutex + directory *paths.Path + index *index.Resource + logger func(msg string) + installed map[string]string + mutex sync.RWMutex +} + +// New will return a Tool object, allowing the caller to execute operations on it. +// The New functions accept the directory to use to host the tools, +// an index (used to download the tools), +// and a logger to log the operations +func New(directory *paths.Path, index *index.Resource, logger func(msg string)) *Tools { + t := &Tools{ + directory: directory, + index: index, + logger: logger, + installed: map[string]string{}, + mutex: sync.RWMutex{}, + } + _ = t.readMap() + return t } -// Init creates the Installed map and populates it from a file in .arduino-create -func (t *Tools) Init(APIlevel string) { - createDir(t.Directory) +func (t *Tools) setMapValue(key, value string) { t.mutex.Lock() - t.installed = make(map[string]string) + t.installed[key] = value t.mutex.Unlock() - t.readMap() +} + +func (t *Tools) getMapValue(key string) (string, bool) { + t.mutex.RLock() + defer t.mutex.RUnlock() + value, ok := t.installed[key] + return value, ok +} + +// writeMap() writes installed map to the json file "installed.json" +func (t *Tools) writeMap() error { t.mutex.RLock() - if t.installed["apilevel"] != APIlevel { - t.mutex.RUnlock() - // wipe the folder and reinitialize the data - os.RemoveAll(t.Directory) - createDir(t.Directory) - t.mutex.Lock() - t.installed = make(map[string]string) - t.installed["apilevel"] = APIlevel - t.mutex.Unlock() - t.writeMap() - t.readMap() - } else { - t.mutex.RUnlock() + defer t.mutex.RUnlock() + b, err := json.Marshal(t.installed) + if err != nil { + return err + } + filePath := t.directory.Join("installed.json") + return filePath.WriteFile(b) +} + +// readMap() reads the installed map from json file "installed.json" +func (t *Tools) readMap() error { + t.mutex.Lock() + defer t.mutex.Unlock() + filePath := t.directory.Join("installed.json") + b, err := filePath.ReadFile() + if err != nil { + return err } + return json.Unmarshal(b, &t.installed) } // GetLocation extracts the toolname from a command like @@ -88,22 +111,16 @@ func (t *Tools) GetLocation(command string) (string, error) { var ok bool // Load installed - t.mutex.RLock() - fmt.Println(t.installed) - t.mutex.RUnlock() - err := t.readMap() if err != nil { return "", err } - t.mutex.RLock() - defer t.mutex.RUnlock() - fmt.Println(t.installed) - // use string similarity to resolve a runtime var with a "similar" map element - if location, ok = t.installed[command]; !ok { + if location, ok = t.getMapValue(command); !ok { maxSimilarity := 0.0 + t.mutex.RLock() + defer t.mutex.RUnlock() for i, candidate := range t.installed { similarity := smetrics.Jaro(command, i) if similarity > 0.8 && similarity > maxSimilarity { @@ -114,38 +131,3 @@ func (t *Tools) GetLocation(command string) (string, error) { } return filepath.ToSlash(location), nil } - -// writeMap() writes installed map to the json file "installed.json" -func (t *Tools) writeMap() error { - t.mutex.Lock() - b, err := json.Marshal(t.installed) - defer t.mutex.Unlock() - if err != nil { - return err - } - filePath := path.Join(dir(), "installed.json") - return os.WriteFile(filePath, b, 0644) -} - -// readMap() reads the installed map from json file "installed.json" -func (t *Tools) readMap() error { - t.mutex.Lock() - defer t.mutex.Unlock() - filePath := path.Join(dir(), "installed.json") - b, err := os.ReadFile(filePath) - if err != nil { - return err - } - return json.Unmarshal(b, &t.installed) -} - -func dir() string { - usr, _ := user.Current() - return path.Join(usr.HomeDir, ".arduino-create") -} - -// createDir creates the directory where the tools will be stored -func createDir(directory string) { - os.Mkdir(directory, 0777) - hideFile(directory) -} diff --git a/v2/http.go b/v2/http.go index 3e9c00965..bcfbc82aa 100644 --- a/v2/http.go +++ b/v2/http.go @@ -19,12 +19,10 @@ import ( "context" "encoding/json" "net/http" - "path/filepath" - indexessvr "github.com/arduino/arduino-create-agent/gen/http/indexes/server" toolssvr "github.com/arduino/arduino-create-agent/gen/http/tools/server" - indexessvc "github.com/arduino/arduino-create-agent/gen/indexes" toolssvc "github.com/arduino/arduino-create-agent/gen/tools" + "github.com/arduino/arduino-create-agent/index" "github.com/arduino/arduino-create-agent/v2/pkgs" "github.com/sirupsen/logrus" goahttp "goa.design/goa/v3/http" @@ -33,7 +31,7 @@ import ( ) // Server is the actual server -func Server(home string) http.Handler { +func Server(directory string, index *index.Resource) http.Handler { mux := goahttp.NewMuxer() // Instantiate logger @@ -41,22 +39,9 @@ func Server(home string) http.Handler { logger.SetLevel(logrus.DebugLevel) logAdapter := LogAdapter{Logger: logger} - // Mount indexes - indexesSvc := pkgs.Indexes{ - Log: logger, - Folder: filepath.Join(home, "indexes"), - } - indexesEndpoints := indexessvc.NewEndpoints(&indexesSvc) - indexesServer := indexessvr.New(indexesEndpoints, mux, goahttp.RequestDecoder, - goahttp.ResponseEncoder, errorHandler(logger), nil) - indexessvr.Mount(mux, indexesServer) - // Mount tools - toolsSvc := pkgs.Tools{ - Folder: home, - Indexes: &indexesSvc, - } - toolsEndpoints := toolssvc.NewEndpoints(&toolsSvc) + toolsSvc := pkgs.New(index, directory) + toolsEndpoints := toolssvc.NewEndpoints(toolsSvc) toolsServer := toolssvr.New(toolsEndpoints, mux, CustomRequestDecoder, goahttp.ResponseEncoder, errorHandler(logger), nil) toolssvr.Mount(mux, toolsServer) diff --git a/v2/pkgs/indexes.go b/v2/pkgs/indexes.go deleted file mode 100644 index ceb5eb65b..000000000 --- a/v2/pkgs/indexes.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2022 Arduino SA -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package pkgs - -import ( - "context" - b64 "encoding/base64" - "encoding/json" - "net/url" - "os" - "path/filepath" - "strings" - - "github.com/arduino/arduino-create-agent/gen/indexes" - "github.com/sirupsen/logrus" - "go.bug.st/downloader/v2" -) - -// Indexes is a client that implements github.com/arduino/arduino-create-agent/gen/indexes.Service interface -type Indexes struct { - Log *logrus.Logger - Folder string -} - -// Add downloads the index file found at the url contained in the payload, and saves it in the Indexes Folder. -// If called with an already existing index, it overwrites the file. -// It can fail if the payload is not defined, if it contains an invalid url. -func (c *Indexes) Add(ctx context.Context, payload *indexes.IndexPayload) (*indexes.Operation, error) { - // Parse url - indexURL, err := url.Parse(payload.URL) - if err != nil { - return nil, indexes.MakeInvalidURL(err) - } - - // Download tmp file - filename := b64.StdEncoding.EncodeToString([]byte(url.PathEscape(payload.URL))) - path := filepath.Join(c.Folder, filename+".tmp") - d, err := downloader.Download(path, indexURL.String()) - if err != nil { - return nil, err - } - err = d.Run() - if err != nil { - return nil, err - } - - // Move tmp file - err = os.Rename(path, filepath.Join(c.Folder, filename)) - if err != nil { - return nil, err - } - - return &indexes.Operation{Status: "ok"}, nil -} - -// Get reads the index file from the Indexes Folder, unmarshaling it -func (c *Indexes) Get(ctx context.Context, uri string) (index Index, err error) { - filename := b64.StdEncoding.EncodeToString([]byte(url.PathEscape(uri))) - path := filepath.Join(c.Folder, filename) - data, err := os.ReadFile(path) - if err != nil { - return index, err - } - - err = json.Unmarshal(data, &index) - if err != nil { - return index, err - } - - return index, nil -} - -// List reads from the Indexes Folder and returns the indexes that have been downloaded -func (c *Indexes) List(context.Context) ([]string, error) { - // Create folder if it doesn't exist - _ = os.MkdirAll(c.Folder, 0755) - // Read files - files, err := os.ReadDir(c.Folder) - - if err != nil { - return nil, err - } - - res := []string{} - for _, file := range files { - // Select only files that begin with http - decodedFileName, _ := b64.URLEncoding.DecodeString(file.Name()) - fileName := string(decodedFileName) - if !strings.HasPrefix(fileName, "http") { - continue - } - path, err := url.PathUnescape(fileName) - if err != nil { - c.Log.Warn(err) - } - res = append(res, path) - } - - return res, nil -} - -// Remove deletes the index file from the Indexes Folder -func (c *Indexes) Remove(ctx context.Context, payload *indexes.IndexPayload) (*indexes.Operation, error) { - filename := b64.StdEncoding.EncodeToString([]byte(url.PathEscape(payload.URL))) - err := os.RemoveAll(filepath.Join(c.Folder, filename)) - if err != nil { - return nil, err - } - return &indexes.Operation{Status: "ok"}, nil -} diff --git a/v2/pkgs/indexes_test.go b/v2/pkgs/indexes_test.go deleted file mode 100644 index 796a18a5a..000000000 --- a/v2/pkgs/indexes_test.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 Arduino SA -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package pkgs_test - -import ( - "context" - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/arduino/arduino-create-agent/gen/indexes" - "github.com/arduino/arduino-create-agent/v2/pkgs" -) - -// TestIndexes performs a series of operations about indexes, ensuring it behaves as expected. -func TestIndexes(t *testing.T) { - // Use local file as index - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "testdata/package_index.json") - })) - defer ts.Close() - - // Initialize indexes with a temp folder - tmp, err := os.MkdirTemp("", "") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - // Create extraneous folder in temp folder - os.MkdirAll(filepath.Join(tmp, "arduino"), 0755) - - service := pkgs.Indexes{ - Folder: tmp, - } - - ctx := context.Background() - - // List indexes, they should be 0 - list, err := service.List(ctx) - if err != nil { - t.Fatal(err) - } - if len(list) != 0 { - t.Fatalf("expected %d == %d (%s)", len(list), 0, "len(list)") - } - - // Add a faulty index - _, err = service.Add(ctx, &indexes.IndexPayload{URL: ":"}) - if err == nil || !strings.Contains(err.Error(), "missing protocol scheme") { - t.Fatalf("expected [%v] == [%v] (%s)", err, "missing protocol scheme", "err") - } - - // Add a new index - _, err = service.Add(ctx, &indexes.IndexPayload{URL: ts.URL}) - if err != nil { - t.Fatal(err) - } - - // List indexes, they should be 1 - list, err = service.List(ctx) - if err != nil { - t.Fatal(err) - } - if len(list) != 1 { - t.Fatalf("expected %d == %d (%s)", len(list), 1, "len(list)") - } - if list[0] != ts.URL { - t.Fatalf("expected %s == %s (%s)", list[0], "downloads.arduino.cc/packages/package_index.json", "list[0]") - } - - // Remove the index - _, err = service.Remove(ctx, &indexes.IndexPayload{URL: ts.URL}) - if err != nil { - t.Fatal(err) - } - - // List indexes, they should be 0 - list, err = service.List(ctx) - if err != nil { - t.Fatal(err) - } - if len(list) != 0 { - t.Fatalf("expected %d == %d (%s)", len(list), 0, "len(list)") - } -} diff --git a/v2/pkgs/tools.go b/v2/pkgs/tools.go index 2cb92553c..f9636f077 100644 --- a/v2/pkgs/tools.go +++ b/v2/pkgs/tools.go @@ -31,6 +31,7 @@ import ( "strings" "github.com/arduino/arduino-create-agent/gen/tools" + "github.com/arduino/arduino-create-agent/index" "github.com/arduino/arduino-create-agent/utilities" "github.com/codeclysm/extract/v3" ) @@ -47,36 +48,39 @@ import ( // └── 1.7.0 // └── bossac // -// It requires an Indexes client to list and read package index files: use the Indexes struct +// It requires an Index Resource to search for tools type Tools struct { - Indexes interface { - List(context.Context) ([]string, error) - Get(context.Context, string) (Index, error) + index *index.Resource + folder string +} + +// New will return a Tool object, allowing the caller to execute operations on it. +// The New function will accept an index as parameter (used to download the indexes) +// and a folder used to download the indexes +func New(index *index.Resource, folder string) *Tools { + return &Tools{ + index: index, + folder: folder, } - Folder string } // Available crawles the downloaded package index files and returns a list of tools that can be installed. -func (c *Tools) Available(ctx context.Context) (res tools.ToolCollection, err error) { - list, err := c.Indexes.List(ctx) +func (t *Tools) Available(ctx context.Context) (res tools.ToolCollection, err error) { + body, err := t.index.Read() if err != nil { return nil, err } - for _, url := range list { - index, err := c.Indexes.Get(ctx, url) - if err != nil { - return nil, err - } + var index Index + json.Unmarshal(body, &index) - for _, packager := range index.Packages { - for _, tool := range packager.Tools { - res = append(res, &tools.Tool{ - Packager: packager.Name, - Name: tool.Name, - Version: tool.Version, - }) - } + for _, packager := range index.Packages { + for _, tool := range packager.Tools { + res = append(res, &tools.Tool{ + Packager: packager.Name, + Name: tool.Name, + Version: tool.Version, + }) } } @@ -84,16 +88,16 @@ func (c *Tools) Available(ctx context.Context) (res tools.ToolCollection, err er } // Installed crawles the Tools Folder and finds the installed tools. -func (c *Tools) Installed(ctx context.Context) (tools.ToolCollection, error) { +func (t *Tools) Installed(ctx context.Context) (tools.ToolCollection, error) { res := tools.ToolCollection{} // Find packagers - packagers, err := os.ReadDir(c.Folder) + packagers, err := os.ReadDir(t.folder) if err != nil { if !strings.Contains(err.Error(), "no such file") { return nil, err } - err = os.MkdirAll(c.Folder, 0755) + err = os.MkdirAll(t.folder, 0755) if err != nil { return nil, err } @@ -105,14 +109,14 @@ func (c *Tools) Installed(ctx context.Context) (tools.ToolCollection, error) { } // Find tools - toolss, err := os.ReadDir(filepath.Join(c.Folder, packager.Name())) + toolss, err := os.ReadDir(filepath.Join(t.folder, packager.Name())) if err != nil { return nil, err } for _, tool := range toolss { // Find versions - path := filepath.Join(c.Folder, packager.Name(), tool.Name()) + path := filepath.Join(t.folder, packager.Name(), tool.Name()) versions, err := os.ReadDir(path) if err != nil { continue // we ignore errors because the folders could be dirty @@ -133,7 +137,7 @@ func (c *Tools) Installed(ctx context.Context) (tools.ToolCollection, error) { // Install crawles the Index folder, downloads the specified tool, extracts the archive in the Tools Folder. // It checks for the Signature specified in the package index. -func (c *Tools) Install(ctx context.Context, payload *tools.ToolPayload) (*tools.Operation, error) { +func (t *Tools) Install(ctx context.Context, payload *tools.ToolPayload) (*tools.Operation, error) { path := filepath.Join(payload.Packager, payload.Name, payload.Version) //if URL is defined and is signed we verify the signature and override the name, payload, version parameters @@ -142,34 +146,30 @@ func (c *Tools) Install(ctx context.Context, payload *tools.ToolPayload) (*tools if err != nil { return nil, err } - return c.install(ctx, path, *payload.URL, *payload.Checksum) + return t.install(ctx, path, *payload.URL, *payload.Checksum) } - // otherwise we install from the loaded indexes - list, err := c.Indexes.List(ctx) + // otherwise we install from the default index + body, err := t.index.Read() if err != nil { return nil, err } - for _, url := range list { - index, err := c.Indexes.Get(ctx, url) - if err != nil { - return nil, err - } + var index Index + json.Unmarshal(body, &index) - for _, packager := range index.Packages { - if packager.Name != payload.Packager { - continue - } + for _, packager := range index.Packages { + if packager.Name != payload.Packager { + continue + } - for _, tool := range packager.Tools { - if tool.Name == payload.Name && - tool.Version == payload.Version { + for _, tool := range packager.Tools { + if tool.Name == payload.Name && + tool.Version == payload.Version { - sys := tool.GetFlavourCompatibleWith(runtime.GOOS, runtime.GOARCH) + sys := tool.GetFlavourCompatibleWith(runtime.GOOS, runtime.GOARCH) - return c.install(ctx, path, sys.URL, sys.Checksum) - } + return t.install(ctx, path, sys.URL, sys.Checksum) } } } @@ -179,7 +179,7 @@ func (c *Tools) Install(ctx context.Context, payload *tools.ToolPayload) (*tools payload.Packager, payload.Name, payload.Version)) } -func (c *Tools) install(ctx context.Context, path, url, checksum string) (*tools.Operation, error) { +func (t *Tools) install(ctx context.Context, path, url, checksum string) (*tools.Operation, error) { // Download res, err := http.Get(url) if err != nil { @@ -191,7 +191,7 @@ func (c *Tools) install(ctx context.Context, path, url, checksum string) (*tools var buffer bytes.Buffer reader := io.TeeReader(res.Body, &buffer) - safePath, err := utilities.SafeJoin(c.Folder, path) + safePath, err := utilities.SafeJoin(t.folder, path) if err != nil { return nil, err } @@ -202,7 +202,7 @@ func (c *Tools) install(ctx context.Context, path, url, checksum string) (*tools return nil, err } - err = extract.Archive(ctx, reader, c.Folder, rename(path)) + err = extract.Archive(ctx, reader, t.folder, rename(path)) if err != nil { os.RemoveAll(safePath) return nil, err @@ -217,7 +217,7 @@ func (c *Tools) install(ctx context.Context, path, url, checksum string) (*tools } // Write installed.json for retrocompatibility with v1 - err = writeInstalled(c.Folder, path) + err = writeInstalled(t.folder, path) if err != nil { return nil, err } @@ -226,9 +226,9 @@ func (c *Tools) install(ctx context.Context, path, url, checksum string) (*tools } // Remove deletes the tool folder from Tools Folder -func (c *Tools) Remove(ctx context.Context, payload *tools.ToolPayload) (*tools.Operation, error) { +func (t *Tools) Remove(ctx context.Context, payload *tools.ToolPayload) (*tools.Operation, error) { path := filepath.Join(payload.Packager, payload.Name, payload.Version) - pathToRemove, err := utilities.SafeJoin(c.Folder, path) + pathToRemove, err := utilities.SafeJoin(t.folder, path) if err != nil { return nil, err } diff --git a/v2/pkgs/tools_test.go b/v2/pkgs/tools_test.go index 04198cb2f..44070c686 100644 --- a/v2/pkgs/tools_test.go +++ b/v2/pkgs/tools_test.go @@ -17,15 +17,14 @@ package pkgs_test import ( "context" - "net/http" - "net/http/httptest" "os" "runtime" "strings" "testing" - "github.com/arduino/arduino-create-agent/gen/indexes" + "github.com/arduino/arduino-create-agent/config" "github.com/arduino/arduino-create-agent/gen/tools" + "github.com/arduino/arduino-create-agent/index" "github.com/arduino/arduino-create-agent/v2/pkgs" "github.com/stretchr/testify/require" ) @@ -33,12 +32,6 @@ import ( // TestTools performs a series of operations about tools, ensuring it behaves as expected. // This test depends on the internet so it could fail unexpectedly func TestTools(t *testing.T) { - // Use local file as index - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "testdata/package_index.json") - })) - defer ts.Close() - // Initialize indexes with a temp folder tmp, err := os.MkdirTemp("", "") if err != nil { @@ -46,31 +39,20 @@ func TestTools(t *testing.T) { } defer os.RemoveAll(tmp) - indexesClient := pkgs.Indexes{ - Folder: tmp, - } + indexURL := "https://downloads.arduino.cc/packages/package_staging_index.json" + // Instantiate Index + Index := index.Init(indexURL, config.GetDataDir()) - service := pkgs.Tools{ - Folder: tmp, - Indexes: &indexesClient, - } + service := pkgs.New(Index, tmp) ctx := context.Background() - // Add a new index - _, err = indexesClient.Add(ctx, &indexes.IndexPayload{URL: ts.URL}) - if err != nil { - t.Fatal(err) - } - // List available tools available, err := service.Available(ctx) if err != nil { t.Fatal(err) } - if len(available) != 61 { - t.Fatalf("expected %d == %d (%s)", len(available), 61, "len(available)") - } + require.NotEmpty(t, available) // Try to install a non-existent tool _, err = service.Install(ctx, &tools.ToolPayload{}) @@ -138,12 +120,11 @@ func TestEvilFilename(t *testing.T) { // Initialize indexes with a temp folder tmp := t.TempDir() - service := pkgs.Tools{ - Folder: tmp, - Indexes: &pkgs.Indexes{ - Folder: tmp, - }, - } + indexURL := "https://downloads.arduino.cc/packages/package_staging_index.json" + // Instantiate Index + Index := index.Init(indexURL, config.GetDataDir()) + + service := pkgs.New(Index, tmp) ctx := context.Background()