Profiling endpoints for mcs (#1)
start and stop profiling endpoints, test includes and many fixes for policies deleting duplicated file
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -19,4 +19,6 @@ vendor/
|
||||
# Ignore executables
|
||||
target/
|
||||
mcs-server
|
||||
mcs
|
||||
!mcs/
|
||||
!mcs-server/
|
||||
|
||||
8
Makefile
8
Makefile
@@ -7,11 +7,17 @@ mcs:
|
||||
|
||||
swagger-gen:
|
||||
@echo "Generating swagger server code from yaml"
|
||||
@swagger generate server -A mcs -f ./swagger.yml -r minio_copyright.txt
|
||||
@swagger generate server -A mcs -f ./swagger.yml -r NOTICE
|
||||
|
||||
build:
|
||||
@(cd portal-ui; yarn install; make build; cd ..)
|
||||
@(CGO_ENABLED=0 go build --tags kqueue --ldflags "-s -w" -o mcs ./cmd/mcs-server)
|
||||
|
||||
test:
|
||||
@(go test ./restapi -v)
|
||||
|
||||
coverage:
|
||||
@(go test ./restapi -v -coverprofile=coverage.out && go tool cover -html=coverage.out && open coverage.html)
|
||||
|
||||
clean:
|
||||
@rm -vf mcs
|
||||
|
||||
95
models/profiler_type.go
Normal file
95
models/profiler_type.go
Normal file
@@ -0,0 +1,95 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// ProfilerType profiler type
|
||||
//
|
||||
// swagger:model profilerType
|
||||
type ProfilerType string
|
||||
|
||||
const (
|
||||
|
||||
// ProfilerTypeCPU captures enum value "cpu"
|
||||
ProfilerTypeCPU ProfilerType = "cpu"
|
||||
|
||||
// ProfilerTypeMem captures enum value "mem"
|
||||
ProfilerTypeMem ProfilerType = "mem"
|
||||
|
||||
// ProfilerTypeBlock captures enum value "block"
|
||||
ProfilerTypeBlock ProfilerType = "block"
|
||||
|
||||
// ProfilerTypeMutex captures enum value "mutex"
|
||||
ProfilerTypeMutex ProfilerType = "mutex"
|
||||
|
||||
// ProfilerTypeTrace captures enum value "trace"
|
||||
ProfilerTypeTrace ProfilerType = "trace"
|
||||
|
||||
// ProfilerTypeThreads captures enum value "threads"
|
||||
ProfilerTypeThreads ProfilerType = "threads"
|
||||
|
||||
// ProfilerTypeGoroutines captures enum value "goroutines"
|
||||
ProfilerTypeGoroutines ProfilerType = "goroutines"
|
||||
)
|
||||
|
||||
// for schema
|
||||
var profilerTypeEnum []interface{}
|
||||
|
||||
func init() {
|
||||
var res []ProfilerType
|
||||
if err := json.Unmarshal([]byte(`["cpu","mem","block","mutex","trace","threads","goroutines"]`), &res); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, v := range res {
|
||||
profilerTypeEnum = append(profilerTypeEnum, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (m ProfilerType) validateProfilerTypeEnum(path, location string, value ProfilerType) error {
|
||||
if err := validate.Enum(path, location, value, profilerTypeEnum); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate validates this profiler type
|
||||
func (m ProfilerType) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
// value enum
|
||||
if err := m.validateProfilerTypeEnum("", "body", m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
83
models/profiling_start_request.go
Normal file
83
models/profiling_start_request.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// ProfilingStartRequest profiling start request
|
||||
//
|
||||
// swagger:model profilingStartRequest
|
||||
type ProfilingStartRequest struct {
|
||||
|
||||
// type
|
||||
// Required: true
|
||||
Type ProfilerType `json:"type"`
|
||||
}
|
||||
|
||||
// Validate validates this profiling start request
|
||||
func (m *ProfilingStartRequest) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateType(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ProfilingStartRequest) validateType(formats strfmt.Registry) error {
|
||||
|
||||
if err := m.Type.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("type")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *ProfilingStartRequest) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *ProfilingStartRequest) UnmarshalBinary(b []byte) error {
|
||||
var res ProfilingStartRequest
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
66
models/start_profiling_item.go
Normal file
66
models/start_profiling_item.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// StartProfilingItem start profiling item
|
||||
//
|
||||
// swagger:model startProfilingItem
|
||||
type StartProfilingItem struct {
|
||||
|
||||
// error
|
||||
Error string `json:"error,omitempty"`
|
||||
|
||||
// node name
|
||||
NodeName string `json:"nodeName,omitempty"`
|
||||
|
||||
// success
|
||||
Success bool `json:"success,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this start profiling item
|
||||
func (m *StartProfilingItem) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *StartProfilingItem) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *StartProfilingItem) UnmarshalBinary(b []byte) error {
|
||||
var res StartProfilingItem
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
100
models/start_profiling_list.go
Normal file
100
models/start_profiling_list.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// StartProfilingList start profiling list
|
||||
//
|
||||
// swagger:model startProfilingList
|
||||
type StartProfilingList struct {
|
||||
|
||||
// start results
|
||||
StartResults []*StartProfilingItem `json:"startResults"`
|
||||
|
||||
// number of start results
|
||||
Total int64 `json:"total,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this start profiling list
|
||||
func (m *StartProfilingList) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateStartResults(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StartProfilingList) validateStartResults(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.StartResults) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.StartResults); i++ {
|
||||
if swag.IsZero(m.StartResults[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.StartResults[i] != nil {
|
||||
if err := m.StartResults[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("startResults" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *StartProfilingList) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *StartProfilingList) UnmarshalBinary(b []byte) error {
|
||||
var res StartProfilingList
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -111,8 +111,7 @@ func parseRawPolicy(rawPolicy *rawPolicy) *models.Policy {
|
||||
// listPolicies() converts the map[string][]byte returned by client.listPolicies()
|
||||
// to []*models.Policy by iterating over each key in policyRawMap and
|
||||
// then using Unmarshal on the raw bytes to create a *models.Policy
|
||||
func listPolicies(client MinioAdmin) ([]*models.Policy, error) {
|
||||
ctx := context.Background()
|
||||
func listPolicies(ctx context.Context, client MinioAdmin) ([]*models.Policy, error) {
|
||||
policyRawMap, err := client.listPolicies(ctx)
|
||||
var policies []*models.Policy
|
||||
if err != nil {
|
||||
@@ -132,6 +131,7 @@ func listPolicies(client MinioAdmin) ([]*models.Policy, error) {
|
||||
|
||||
// getListPoliciesResponse performs listPolicies() and serializes it to the handler's output
|
||||
func getListPoliciesResponse() (*models.ListPoliciesResponse, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
@@ -141,7 +141,7 @@ func getListPoliciesResponse() (*models.ListPoliciesResponse, error) {
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
policies, err := listPolicies(adminClient)
|
||||
policies, err := listPolicies(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error listing policies:", err)
|
||||
return nil, err
|
||||
@@ -155,8 +155,7 @@ func getListPoliciesResponse() (*models.ListPoliciesResponse, error) {
|
||||
}
|
||||
|
||||
// removePolicy() calls MinIO server to remove a policy based on name.
|
||||
func removePolicy(client MinioAdmin, name string) error {
|
||||
ctx := context.Background()
|
||||
func removePolicy(ctx context.Context, client MinioAdmin, name string) error {
|
||||
err := client.removePolicy(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -166,6 +165,7 @@ func removePolicy(client MinioAdmin, name string) error {
|
||||
|
||||
// getRemovePolicyResponse() performs removePolicy() and serializes it to the handler's output
|
||||
func getRemovePolicyResponse(params admin_api.RemovePolicyParams) error {
|
||||
ctx := context.Background()
|
||||
if params.Name == "" {
|
||||
log.Println("error policy name not in request")
|
||||
return errors.New(500, "error policy name not in request")
|
||||
@@ -179,7 +179,7 @@ func getRemovePolicyResponse(params admin_api.RemovePolicyParams) error {
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := removePolicy(adminClient, params.Name); err != nil {
|
||||
if err := removePolicy(ctx, adminClient, params.Name); err != nil {
|
||||
log.Println("error removing policy:", err)
|
||||
return err
|
||||
}
|
||||
@@ -190,12 +190,11 @@ func getRemovePolicyResponse(params admin_api.RemovePolicyParams) error {
|
||||
// addPolicy() takes name and policy in string format, policy
|
||||
// policy must be string in json format, in the future this will change
|
||||
// to a Policy struct{} - https://github.com/minio/minio/issues/9171
|
||||
func addPolicy(client MinioAdmin, name, policy string) (*models.Policy, error) {
|
||||
ctx := context.Background()
|
||||
func addPolicy(ctx context.Context, client MinioAdmin, name, policy string) (*models.Policy, error) {
|
||||
if err := client.addPolicy(ctx, name, policy); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policyObject, err := policyInfo(client, name)
|
||||
policyObject, err := policyInfo(ctx, client, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -204,6 +203,7 @@ func addPolicy(client MinioAdmin, name, policy string) (*models.Policy, error) {
|
||||
|
||||
// getAddPolicyResponse performs addPolicy() and serializes it to the handler's output
|
||||
func getAddPolicyResponse(params *models.AddPolicyRequest) (*models.Policy, error) {
|
||||
ctx := context.Background()
|
||||
if params == nil {
|
||||
log.Println("error AddPolicy body not in request")
|
||||
return nil, errors.New(500, "error AddPolicy body not in request")
|
||||
@@ -217,7 +217,7 @@ func getAddPolicyResponse(params *models.AddPolicyRequest) (*models.Policy, erro
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
policy, err := addPolicy(adminClient, *params.Name, params.Definition)
|
||||
policy, err := addPolicy(ctx, adminClient, *params.Name, params.Definition)
|
||||
if err != nil {
|
||||
log.Println("error adding policy")
|
||||
return nil, err
|
||||
@@ -229,8 +229,7 @@ func getAddPolicyResponse(params *models.AddPolicyRequest) (*models.Policy, erro
|
||||
// policyInfo() takes a policy name, obtains an []byte (represents a string in JSON format)
|
||||
// from the MinIO server and then convert it to *models.Policy , in the future this will change
|
||||
// to a Policy struct{} - https://github.com/minio/minio/issues/9171
|
||||
func policyInfo(client MinioAdmin, name string) (*models.Policy, error) {
|
||||
ctx := context.Background()
|
||||
func policyInfo(ctx context.Context, client MinioAdmin, name string) (*models.Policy, error) {
|
||||
policyRaw, err := client.getPolicy(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -246,6 +245,7 @@ func policyInfo(client MinioAdmin, name string) (*models.Policy, error) {
|
||||
|
||||
// getPolicyInfoResponse performs policyInfo() and serializes it to the handler's output
|
||||
func getPolicyInfoResponse(params admin_api.PolicyInfoParams) (*models.Policy, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
@@ -254,7 +254,7 @@ func getPolicyInfoResponse(params admin_api.PolicyInfoParams) (*models.Policy, e
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
policy, err := policyInfo(adminClient, params.Name)
|
||||
policy, err := policyInfo(ctx, adminClient, params.Name)
|
||||
if err != nil {
|
||||
log.Println("error getting group info:", err)
|
||||
return nil, err
|
||||
@@ -263,12 +263,11 @@ func getPolicyInfoResponse(params admin_api.PolicyInfoParams) (*models.Policy, e
|
||||
}
|
||||
|
||||
// setPolicy() calls MinIO server to assign policy to a group or user.
|
||||
func setPolicy(client MinioAdmin, name, entityName string, entityType models.PolicyEntity) error {
|
||||
func setPolicy(ctx context.Context, client MinioAdmin, name, entityName string, entityType models.PolicyEntity) error {
|
||||
isGroup := false
|
||||
if entityType == "group" {
|
||||
isGroup = true
|
||||
}
|
||||
ctx := context.Background()
|
||||
if err := client.setPolicy(ctx, name, entityName, isGroup); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -277,6 +276,7 @@ func setPolicy(client MinioAdmin, name, entityName string, entityType models.Pol
|
||||
|
||||
// getSetPolicyResponse() performs setPolicy() and serializes it to the handler's output
|
||||
func getSetPolicyResponse(name string, params *models.SetPolicyRequest) error {
|
||||
ctx := context.Background()
|
||||
if name == "" {
|
||||
log.Println("error policy name not in request")
|
||||
return errors.New(500, "error policy name not in request")
|
||||
@@ -290,7 +290,7 @@ func getSetPolicyResponse(name string, params *models.SetPolicyRequest) error {
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := setPolicy(adminClient, name, *params.EntityName, params.EntityType); err != nil {
|
||||
if err := setPolicy(ctx, adminClient, name, *params.EntityName, params.EntityType); err != nil {
|
||||
log.Println("error setting policy:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ func (ac adminClientMock) setPolicy(ctx context.Context, policyName, entityName
|
||||
}
|
||||
|
||||
func TestListPolicies(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
assert := assert.New(t)
|
||||
adminClient := adminClientMock{}
|
||||
mockPoliciesList := map[string][]byte{
|
||||
@@ -116,7 +117,7 @@ func TestListPolicies(t *testing.T) {
|
||||
}
|
||||
// Test-1 : listPolicies() Get response from minio client with three Canned Policies and return the same number on listPolicies()
|
||||
function := "listPolicies()"
|
||||
policiesList, err := listPolicies(adminClient)
|
||||
policiesList, err := listPolicies(ctx, adminClient)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
@@ -147,7 +148,7 @@ func TestListPolicies(t *testing.T) {
|
||||
minioListPoliciesMock = func() (map[string][]byte, error) {
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
_, err = listPolicies(adminClient)
|
||||
_, err = listPolicies(ctx, adminClient)
|
||||
if assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
@@ -158,13 +159,15 @@ func TestListPolicies(t *testing.T) {
|
||||
}
|
||||
return malformedData, nil
|
||||
}
|
||||
_, err = listPolicies(adminClient)
|
||||
_, err = listPolicies(ctx, adminClient)
|
||||
if assert.Error(err) {
|
||||
assert.NotEmpty(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovePolicy(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
assert := assert.New(t)
|
||||
adminClient := adminClientMock{}
|
||||
// Test-1 : removePolicy() remove an existing policy
|
||||
@@ -173,19 +176,20 @@ func TestRemovePolicy(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
function := "removePolicy()"
|
||||
if err := removePolicy(adminClient, policyToRemove); err != nil {
|
||||
if err := removePolicy(ctx, adminClient, policyToRemove); err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
// Test-2 : removePolicy() Return error and see that the error is handled correctly and returned
|
||||
minioRemovePolicyMock = func(name string) error {
|
||||
return errors.New("error")
|
||||
}
|
||||
if err := removePolicy(adminClient, policyToRemove); assert.Error(err) {
|
||||
if err := removePolicy(ctx, adminClient, policyToRemove); assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddPolicy(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
assert := assert.New(t)
|
||||
adminClient := adminClientMock{}
|
||||
policyName := "new-policy"
|
||||
@@ -209,7 +213,7 @@ func TestAddPolicy(t *testing.T) {
|
||||
}
|
||||
// Test-1 : addPolicy() adds a new policy
|
||||
function := "addPolicy()"
|
||||
policy, err := addPolicy(adminClient, policyName, policyDefinition)
|
||||
policy, err := addPolicy(ctx, adminClient, policyName, policyDefinition)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
@@ -220,7 +224,7 @@ func TestAddPolicy(t *testing.T) {
|
||||
minioAddPolicyMock = func(name, policy string) error {
|
||||
return errors.New("error")
|
||||
}
|
||||
if _, err := addPolicy(adminClient, policyName, policyDefinition); assert.Error(err) {
|
||||
if _, err := addPolicy(ctx, adminClient, policyName, policyDefinition); assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
// Test-3 : addPolicy() got an error while retrieving policy
|
||||
@@ -230,19 +234,20 @@ func TestAddPolicy(t *testing.T) {
|
||||
minioGetPolicyMock = func(name string) (bytes []byte, err error) {
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
if _, err := addPolicy(adminClient, policyName, policyDefinition); assert.Error(err) {
|
||||
if _, err := addPolicy(ctx, adminClient, policyName, policyDefinition); assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
// Test-4 : addPolicy() got an error while parsing policy
|
||||
minioGetPolicyMock = func(name string) (bytes []byte, err error) {
|
||||
return []byte("eaeaeaeae"), nil
|
||||
}
|
||||
if _, err := addPolicy(adminClient, policyName, policyDefinition); assert.Error(err) {
|
||||
if _, err := addPolicy(ctx, adminClient, policyName, policyDefinition); assert.Error(err) {
|
||||
assert.NotEmpty(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetPolicy(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
assert := assert.New(t)
|
||||
adminClient := adminClientMock{}
|
||||
policyName := "readOnly"
|
||||
@@ -253,13 +258,13 @@ func TestSetPolicy(t *testing.T) {
|
||||
}
|
||||
// Test-1 : setPolicy() set policy to user
|
||||
function := "setPolicy()"
|
||||
err := setPolicy(adminClient, policyName, entityName, entityObject)
|
||||
err := setPolicy(ctx, adminClient, policyName, entityName, entityObject)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
// Test-2 : setPolicy() set policy to group
|
||||
entityObject = models.PolicyEntityGroup
|
||||
err = setPolicy(adminClient, policyName, entityName, entityObject)
|
||||
err = setPolicy(ctx, adminClient, policyName, entityName, entityObject)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
@@ -268,7 +273,7 @@ func TestSetPolicy(t *testing.T) {
|
||||
minioSetPolicyMock = func(policyName, entityName string, isGroup bool) error {
|
||||
return errors.New("error")
|
||||
}
|
||||
if err := setPolicy(adminClient, policyName, entityName, entityObject); assert.Error(err) {
|
||||
if err := setPolicy(ctx, adminClient, policyName, entityName, entityObject); assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
// Test-4 : setPolicy() set policy to group and get error
|
||||
@@ -276,7 +281,7 @@ func TestSetPolicy(t *testing.T) {
|
||||
minioSetPolicyMock = func(policyName, entityName string, isGroup bool) error {
|
||||
return errors.New("error")
|
||||
}
|
||||
if err := setPolicy(adminClient, policyName, entityName, entityObject); assert.Error(err) {
|
||||
if err := setPolicy(ctx, adminClient, policyName, entityName, entityObject); assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
118
restapi/admin_profiliing_test.go
Normal file
118
restapi/admin_profiliing_test.go
Normal file
@@ -0,0 +1,118 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/minio/m3/mcs/models"
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var minioStartProfiling func(profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error)
|
||||
var minioStopProfiling func() (io.ReadCloser, error)
|
||||
|
||||
// mock function of startProfiling()
|
||||
func (ac adminClientMock) startProfiling(ctx context.Context, profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
|
||||
return minioStartProfiling(profiler)
|
||||
}
|
||||
|
||||
// mock function of stopProfiling()
|
||||
func (ac adminClientMock) stopProfiling(ctx context.Context) (io.ReadCloser, error) {
|
||||
return minioStopProfiling()
|
||||
}
|
||||
|
||||
func TestStartProfiling(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
assert := assert.New(t)
|
||||
adminClient := adminClientMock{}
|
||||
// Test-1 : startProfiling() Get response from Minio server with one profiling object
|
||||
// mock function response from startProfiling()
|
||||
minioStartProfiling = func(profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
|
||||
return []madmin.StartProfilingResult{
|
||||
{
|
||||
NodeName: "http://127.0.0.1:9000/",
|
||||
Success: true,
|
||||
Error: "",
|
||||
},
|
||||
{
|
||||
NodeName: "http://127.0.0.1:9001/",
|
||||
Success: true,
|
||||
Error: "",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
function := "startProfiling()"
|
||||
cpuProfiler := models.ProfilerType("cpu")
|
||||
startProfilingResults, err := startProfiling(ctx, adminClient, cpuProfiler)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
assert.Equal(2, len(startProfilingResults))
|
||||
//Test-2 : startProfiling() Correctly handles errors returned by Minio
|
||||
//mock function response from startProfiling()
|
||||
minioStartProfiling = func(profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
_, err = startProfiling(ctx, adminClient, cpuProfiler)
|
||||
if assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Implementing fake closingBuffer need it to mock stopProfiling() (io.ReadCloser, error)
|
||||
type ClosingBuffer struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
// Implementing a fake Close function for io.ReadCloser
|
||||
func (cb *ClosingBuffer) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestStopProfiling(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
assert := assert.New(t)
|
||||
adminClient := adminClientMock{}
|
||||
// Test-1 : stopProfiling() Get response from Minio server and that response is a readCloser interface
|
||||
// mock function response from startProfiling()
|
||||
minioStopProfiling = func() (io.ReadCloser, error) {
|
||||
return &ClosingBuffer{bytes.NewBufferString("In memory string eaeae")}, nil
|
||||
}
|
||||
function := "stopProfiling()"
|
||||
readCloserInterface, err := stopProfiling(ctx, adminClient)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
// Check return type of stopProfiling is io.ReadCloser by doing a cast
|
||||
assert.NotPanics(func() { readCloserInterface.(io.ReadCloser).Close() })
|
||||
// Test-2 : stopProfiling() Correctly handles errors returned by Minio
|
||||
// mock function response from stopProfiling()
|
||||
minioStopProfiling = func() (io.ReadCloser, error) {
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
_, err = stopProfiling(ctx, adminClient)
|
||||
if assert.Error(err) {
|
||||
assert.Equal("error", err.Error())
|
||||
}
|
||||
}
|
||||
146
restapi/admin_profiling.go
Normal file
146
restapi/admin_profiling.go
Normal file
@@ -0,0 +1,146 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/m3/mcs/models"
|
||||
"github.com/minio/m3/mcs/restapi/operations"
|
||||
"github.com/minio/m3/mcs/restapi/operations/admin_api"
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
)
|
||||
|
||||
func registerProfilingHandler(api *operations.McsAPI) {
|
||||
// Start Profiling
|
||||
api.AdminAPIProfilingStartHandler = admin_api.ProfilingStartHandlerFunc(func(params admin_api.ProfilingStartParams, principal interface{}) middleware.Responder {
|
||||
profilingStartResponse, err := getProfilingStartResponse(params.Body)
|
||||
if err != nil {
|
||||
return admin_api.NewProfilingStartDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
return admin_api.NewProfilingStartCreated().WithPayload(profilingStartResponse)
|
||||
})
|
||||
// Stop and download profiling data
|
||||
api.AdminAPIProfilingStopHandler = admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, principal interface{}) middleware.Responder {
|
||||
profilingStopResponse, err := getProfilingStopResponse()
|
||||
if err != nil {
|
||||
return admin_api.NewProfilingStopDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
// Custom response writer to set the content-disposition header to tell the
|
||||
// HTTP client the name and extension of the file we are returning
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, _ runtime.Producer) {
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=profile.zip")
|
||||
if _, err := io.Copy(w, profilingStopResponse); err != nil {
|
||||
log.Println(err)
|
||||
} else {
|
||||
if err := profilingStopResponse.Close(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// startProfiling() starts the profiling on the Minio server
|
||||
// Enable 1 of the 7 profiling mechanisms: "cpu","mem","block","mutex","trace","threads","goroutines"
|
||||
// in the Minio server, returns []*models.StartProfilingItem that contains individual status of this operation
|
||||
// for each Minio node, ie:
|
||||
//
|
||||
// {
|
||||
// "Success": true,
|
||||
// "nodeName": "127.0.0.1:9000"
|
||||
// "error": ""
|
||||
// }
|
||||
func startProfiling(ctx context.Context, client MinioAdmin, profilerType models.ProfilerType) ([]*models.StartProfilingItem, error) {
|
||||
profilingResults, err := client.startProfiling(ctx, madmin.ProfilerType(profilerType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var items []*models.StartProfilingItem
|
||||
for _, result := range profilingResults {
|
||||
items = append(items, &models.StartProfilingItem{
|
||||
Success: result.Success,
|
||||
Error: result.Error,
|
||||
NodeName: result.NodeName,
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// getProfilingStartResponse performs startProfiling() and serializes it to the handler's output
|
||||
func getProfilingStartResponse(params *models.ProfilingStartRequest) (*models.StartProfilingList, error) {
|
||||
ctx := context.Background()
|
||||
if params == nil {
|
||||
log.Println("error profiling type not in body request")
|
||||
return nil, errors.New(500, "error AddPolicy body not in request")
|
||||
}
|
||||
mAdmin, err := newMAdminClient()
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
profilingItems, err := startProfiling(ctx, adminClient, params.Type)
|
||||
if err != nil {
|
||||
log.Println("error starting profiling:", err)
|
||||
return nil, err
|
||||
}
|
||||
profilingList := &models.StartProfilingList{
|
||||
StartResults: profilingItems,
|
||||
Total: int64(len(profilingItems)),
|
||||
}
|
||||
return profilingList, nil
|
||||
}
|
||||
|
||||
// stopProfiling() stop the profiling on the Minio server and returns
|
||||
// the generated Zip file as io.ReadCloser
|
||||
func stopProfiling(ctx context.Context, client MinioAdmin) (io.ReadCloser, error) {
|
||||
profilingData, err := client.stopProfiling(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return profilingData, nil
|
||||
}
|
||||
|
||||
// getProfilingStopResponse() performs setPolicy() and serializes it to the handler's output
|
||||
func getProfilingStopResponse() (io.ReadCloser, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
profilingData, err := stopProfiling(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error stopping profiling:", err)
|
||||
return nil, err
|
||||
}
|
||||
return profilingData, nil
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"hash/fnv"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -141,7 +142,7 @@ type MinioAdmin interface {
|
||||
addUser(ctx context.Context, acessKey, SecretKey string) error
|
||||
listGroups(ctx context.Context) ([]string, error)
|
||||
updateGroupMembers(ctx context.Context, greq madmin.GroupAddRemove) error
|
||||
getGroupDescription(ctx context.Context, grouo string) (*madmin.GroupDesc, error)
|
||||
getGroupDescription(ctx context.Context, group string) (*madmin.GroupDesc, error)
|
||||
setGroupStatus(ctx context.Context, group string, status madmin.GroupStatus) error
|
||||
listPolicies(ctx context.Context) (map[string][]byte, error)
|
||||
getPolicy(ctx context.Context, name string) ([]byte, error)
|
||||
@@ -153,6 +154,8 @@ type MinioAdmin interface {
|
||||
setConfigKV(ctx context.Context, kv string) (err error)
|
||||
serviceRestart(ctx context.Context) error
|
||||
serverInfo(ctx context.Context) (madmin.InfoMessage, error)
|
||||
startProfiling(ctx context.Context, profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error)
|
||||
stopProfiling(ctx context.Context) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// Interface implementation
|
||||
@@ -243,6 +246,16 @@ func (ac adminClient) serverInfo(ctx context.Context) (madmin.InfoMessage, error
|
||||
return ac.client.ServerInfo(ctx)
|
||||
}
|
||||
|
||||
// implements madmin.StartProfiling()
|
||||
func (ac adminClient) startProfiling(ctx context.Context, profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
|
||||
return ac.client.StartProfiling(ctx, profiler)
|
||||
}
|
||||
|
||||
// implements madmin.DownloadProfilingData()
|
||||
func (ac adminClient) stopProfiling(ctx context.Context) (io.ReadCloser, error) {
|
||||
return ac.client.DownloadProfilingData(ctx)
|
||||
}
|
||||
|
||||
func newMAdminClient() (*madmin.AdminClient, error) {
|
||||
endpoint := getMinIOServer()
|
||||
accessKeyID := getAccessKey()
|
||||
|
||||
@@ -83,6 +83,8 @@ func configureAPI(api *operations.McsAPI) http.Handler {
|
||||
registerBucketEventsHandlers(api)
|
||||
// Register service handlers
|
||||
registerServiceHandlers(api)
|
||||
// Register profiling handlers
|
||||
registerProfilingHandler(api)
|
||||
|
||||
api.PreServerShutdown = func() {}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
// - application/json
|
||||
//
|
||||
// Produces:
|
||||
// - application/octet-stream
|
||||
// - application/json
|
||||
//
|
||||
// swagger:meta
|
||||
|
||||
@@ -701,6 +701,65 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/profiling/start": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"AdminAPI"
|
||||
],
|
||||
"summary": "Start recording profile data",
|
||||
"operationId": "ProfilingStart",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/profilingStartRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/startProfilingList"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/profiling/stop": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/octet-stream"
|
||||
],
|
||||
"tags": [
|
||||
"AdminAPI"
|
||||
],
|
||||
"summary": "Stop and download profile data",
|
||||
"operationId": "ProfilingStop",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/service/restart": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1185,6 +1244,29 @@ func init() {
|
||||
"principal": {
|
||||
"type": "string"
|
||||
},
|
||||
"profilerType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"cpu",
|
||||
"mem",
|
||||
"block",
|
||||
"mutex",
|
||||
"trace",
|
||||
"threads",
|
||||
"goroutines"
|
||||
]
|
||||
},
|
||||
"profilingStartRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"$ref": "#/definitions/profilerType"
|
||||
}
|
||||
}
|
||||
},
|
||||
"setBucketPolicyRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -1230,6 +1312,36 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"startProfilingItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"nodeName": {
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"startProfilingList": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"startResults": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/startProfilingItem"
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"title": "number of start results"
|
||||
}
|
||||
}
|
||||
},
|
||||
"statement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1970,6 +2082,65 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/profiling/start": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"AdminAPI"
|
||||
],
|
||||
"summary": "Start recording profile data",
|
||||
"operationId": "ProfilingStart",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/profilingStartRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/startProfilingList"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/profiling/stop": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/octet-stream"
|
||||
],
|
||||
"tags": [
|
||||
"AdminAPI"
|
||||
],
|
||||
"summary": "Stop and download profile data",
|
||||
"operationId": "ProfilingStop",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/service/restart": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -2454,6 +2625,29 @@ func init() {
|
||||
"principal": {
|
||||
"type": "string"
|
||||
},
|
||||
"profilerType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"cpu",
|
||||
"mem",
|
||||
"block",
|
||||
"mutex",
|
||||
"trace",
|
||||
"threads",
|
||||
"goroutines"
|
||||
]
|
||||
},
|
||||
"profilingStartRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"$ref": "#/definitions/profilerType"
|
||||
}
|
||||
}
|
||||
},
|
||||
"setBucketPolicyRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -2499,6 +2693,36 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"startProfilingItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"nodeName": {
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"startProfilingList": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"startResults": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/startProfilingItem"
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"title": "number of start results"
|
||||
}
|
||||
}
|
||||
},
|
||||
"statement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
88
restapi/operations/admin_api/profiling_start.go
Normal file
88
restapi/operations/admin_api/profiling_start.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// ProfilingStartHandlerFunc turns a function with the right signature into a profiling start handler
|
||||
type ProfilingStartHandlerFunc func(ProfilingStartParams, interface{}) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn ProfilingStartHandlerFunc) Handle(params ProfilingStartParams, principal interface{}) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// ProfilingStartHandler interface for that can handle valid profiling start params
|
||||
type ProfilingStartHandler interface {
|
||||
Handle(ProfilingStartParams, interface{}) middleware.Responder
|
||||
}
|
||||
|
||||
// NewProfilingStart creates a new http.Handler for the profiling start operation
|
||||
func NewProfilingStart(ctx *middleware.Context, handler ProfilingStartHandler) *ProfilingStart {
|
||||
return &ProfilingStart{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*ProfilingStart swagger:route POST /api/v1/profiling/start AdminAPI profilingStart
|
||||
|
||||
Start recording profile data
|
||||
|
||||
*/
|
||||
type ProfilingStart struct {
|
||||
Context *middleware.Context
|
||||
Handler ProfilingStartHandler
|
||||
}
|
||||
|
||||
func (o *ProfilingStart) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewProfilingStartParams()
|
||||
|
||||
uprinc, aCtx, err := o.Context.Authorize(r, route)
|
||||
if err != nil {
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
if aCtx != nil {
|
||||
r = aCtx
|
||||
}
|
||||
var principal interface{}
|
||||
if uprinc != nil {
|
||||
principal = uprinc
|
||||
}
|
||||
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params, principal) // actually handle the request
|
||||
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
94
restapi/operations/admin_api/profiling_start_parameters.go
Normal file
94
restapi/operations/admin_api/profiling_start_parameters.go
Normal file
@@ -0,0 +1,94 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
|
||||
"github.com/minio/m3/mcs/models"
|
||||
)
|
||||
|
||||
// NewProfilingStartParams creates a new ProfilingStartParams object
|
||||
// no default values defined in spec.
|
||||
func NewProfilingStartParams() ProfilingStartParams {
|
||||
|
||||
return ProfilingStartParams{}
|
||||
}
|
||||
|
||||
// ProfilingStartParams contains all the bound params for the profiling start operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters ProfilingStart
|
||||
type ProfilingStartParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Body *models.ProfilingStartRequest
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewProfilingStartParams() beforehand.
|
||||
func (o *ProfilingStartParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.ProfilingStartRequest
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("body", "body"))
|
||||
} else {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
}
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = append(res, errors.Required("body", "body"))
|
||||
}
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
133
restapi/operations/admin_api/profiling_start_responses.go
Normal file
133
restapi/operations/admin_api/profiling_start_responses.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/m3/mcs/models"
|
||||
)
|
||||
|
||||
// ProfilingStartCreatedCode is the HTTP code returned for type ProfilingStartCreated
|
||||
const ProfilingStartCreatedCode int = 201
|
||||
|
||||
/*ProfilingStartCreated A successful response.
|
||||
|
||||
swagger:response profilingStartCreated
|
||||
*/
|
||||
type ProfilingStartCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.StartProfilingList `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewProfilingStartCreated creates ProfilingStartCreated with default headers values
|
||||
func NewProfilingStartCreated() *ProfilingStartCreated {
|
||||
|
||||
return &ProfilingStartCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the profiling start created response
|
||||
func (o *ProfilingStartCreated) WithPayload(payload *models.StartProfilingList) *ProfilingStartCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the profiling start created response
|
||||
func (o *ProfilingStartCreated) SetPayload(payload *models.StartProfilingList) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *ProfilingStartCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*ProfilingStartDefault Generic error response.
|
||||
|
||||
swagger:response profilingStartDefault
|
||||
*/
|
||||
type ProfilingStartDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewProfilingStartDefault creates ProfilingStartDefault with default headers values
|
||||
func NewProfilingStartDefault(code int) *ProfilingStartDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &ProfilingStartDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the profiling start default response
|
||||
func (o *ProfilingStartDefault) WithStatusCode(code int) *ProfilingStartDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the profiling start default response
|
||||
func (o *ProfilingStartDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the profiling start default response
|
||||
func (o *ProfilingStartDefault) WithPayload(payload *models.Error) *ProfilingStartDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the profiling start default response
|
||||
func (o *ProfilingStartDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *ProfilingStartDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
101
restapi/operations/admin_api/profiling_start_urlbuilder.go
Normal file
101
restapi/operations/admin_api/profiling_start_urlbuilder.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
)
|
||||
|
||||
// ProfilingStartURL generates an URL for the profiling start operation
|
||||
type ProfilingStartURL struct {
|
||||
_basePath string
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *ProfilingStartURL) WithBasePath(bp string) *ProfilingStartURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *ProfilingStartURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *ProfilingStartURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/api/v1/profiling/start"
|
||||
|
||||
_basePath := o._basePath
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *ProfilingStartURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *ProfilingStartURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *ProfilingStartURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on ProfilingStartURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on ProfilingStartURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *ProfilingStartURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
88
restapi/operations/admin_api/profiling_stop.go
Normal file
88
restapi/operations/admin_api/profiling_stop.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// ProfilingStopHandlerFunc turns a function with the right signature into a profiling stop handler
|
||||
type ProfilingStopHandlerFunc func(ProfilingStopParams, interface{}) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn ProfilingStopHandlerFunc) Handle(params ProfilingStopParams, principal interface{}) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// ProfilingStopHandler interface for that can handle valid profiling stop params
|
||||
type ProfilingStopHandler interface {
|
||||
Handle(ProfilingStopParams, interface{}) middleware.Responder
|
||||
}
|
||||
|
||||
// NewProfilingStop creates a new http.Handler for the profiling stop operation
|
||||
func NewProfilingStop(ctx *middleware.Context, handler ProfilingStopHandler) *ProfilingStop {
|
||||
return &ProfilingStop{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*ProfilingStop swagger:route POST /api/v1/profiling/stop AdminAPI profilingStop
|
||||
|
||||
Stop and download profile data
|
||||
|
||||
*/
|
||||
type ProfilingStop struct {
|
||||
Context *middleware.Context
|
||||
Handler ProfilingStopHandler
|
||||
}
|
||||
|
||||
func (o *ProfilingStop) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewProfilingStopParams()
|
||||
|
||||
uprinc, aCtx, err := o.Context.Authorize(r, route)
|
||||
if err != nil {
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
if aCtx != nil {
|
||||
r = aCtx
|
||||
}
|
||||
var principal interface{}
|
||||
if uprinc != nil {
|
||||
principal = uprinc
|
||||
}
|
||||
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params, principal) // actually handle the request
|
||||
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
62
restapi/operations/admin_api/profiling_stop_parameters.go
Normal file
62
restapi/operations/admin_api/profiling_stop_parameters.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// NewProfilingStopParams creates a new ProfilingStopParams object
|
||||
// no default values defined in spec.
|
||||
func NewProfilingStopParams() ProfilingStopParams {
|
||||
|
||||
return ProfilingStopParams{}
|
||||
}
|
||||
|
||||
// ProfilingStopParams contains all the bound params for the profiling stop operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters ProfilingStop
|
||||
type ProfilingStopParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewProfilingStopParams() beforehand.
|
||||
func (o *ProfilingStopParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
132
restapi/operations/admin_api/profiling_stop_responses.go
Normal file
132
restapi/operations/admin_api/profiling_stop_responses.go
Normal file
@@ -0,0 +1,132 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/m3/mcs/models"
|
||||
)
|
||||
|
||||
// ProfilingStopCreatedCode is the HTTP code returned for type ProfilingStopCreated
|
||||
const ProfilingStopCreatedCode int = 201
|
||||
|
||||
/*ProfilingStopCreated A successful response.
|
||||
|
||||
swagger:response profilingStopCreated
|
||||
*/
|
||||
type ProfilingStopCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload io.ReadCloser `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewProfilingStopCreated creates ProfilingStopCreated with default headers values
|
||||
func NewProfilingStopCreated() *ProfilingStopCreated {
|
||||
|
||||
return &ProfilingStopCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the profiling stop created response
|
||||
func (o *ProfilingStopCreated) WithPayload(payload io.ReadCloser) *ProfilingStopCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the profiling stop created response
|
||||
func (o *ProfilingStopCreated) SetPayload(payload io.ReadCloser) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *ProfilingStopCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
|
||||
/*ProfilingStopDefault Generic error response.
|
||||
|
||||
swagger:response profilingStopDefault
|
||||
*/
|
||||
type ProfilingStopDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewProfilingStopDefault creates ProfilingStopDefault with default headers values
|
||||
func NewProfilingStopDefault(code int) *ProfilingStopDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &ProfilingStopDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the profiling stop default response
|
||||
func (o *ProfilingStopDefault) WithStatusCode(code int) *ProfilingStopDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the profiling stop default response
|
||||
func (o *ProfilingStopDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the profiling stop default response
|
||||
func (o *ProfilingStopDefault) WithPayload(payload *models.Error) *ProfilingStopDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the profiling stop default response
|
||||
func (o *ProfilingStopDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *ProfilingStopDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
101
restapi/operations/admin_api/profiling_stop_urlbuilder.go
Normal file
101
restapi/operations/admin_api/profiling_stop_urlbuilder.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
)
|
||||
|
||||
// ProfilingStopURL generates an URL for the profiling stop operation
|
||||
type ProfilingStopURL struct {
|
||||
_basePath string
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *ProfilingStopURL) WithBasePath(bp string) *ProfilingStopURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *ProfilingStopURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *ProfilingStopURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/api/v1/profiling/stop"
|
||||
|
||||
_basePath := o._basePath
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *ProfilingStopURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *ProfilingStopURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *ProfilingStopURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on ProfilingStopURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on ProfilingStopURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *ProfilingStopURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -59,6 +59,7 @@ func NewMcsAPI(spec *loads.Document) *McsAPI {
|
||||
|
||||
JSONConsumer: runtime.JSONConsumer(),
|
||||
|
||||
BinProducer: runtime.ByteStreamProducer(),
|
||||
JSONProducer: runtime.JSONProducer(),
|
||||
|
||||
AdminAPIAddGroupHandler: admin_api.AddGroupHandlerFunc(func(params admin_api.AddGroupParams, principal interface{}) middleware.Responder {
|
||||
@@ -115,6 +116,12 @@ func NewMcsAPI(spec *loads.Document) *McsAPI {
|
||||
AdminAPIPolicyInfoHandler: admin_api.PolicyInfoHandlerFunc(func(params admin_api.PolicyInfoParams, principal interface{}) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.PolicyInfo has not yet been implemented")
|
||||
}),
|
||||
AdminAPIProfilingStartHandler: admin_api.ProfilingStartHandlerFunc(func(params admin_api.ProfilingStartParams, principal interface{}) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.ProfilingStart has not yet been implemented")
|
||||
}),
|
||||
AdminAPIProfilingStopHandler: admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, principal interface{}) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.ProfilingStop has not yet been implemented")
|
||||
}),
|
||||
AdminAPIRemoveGroupHandler: admin_api.RemoveGroupHandlerFunc(func(params admin_api.RemoveGroupParams, principal interface{}) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.RemoveGroup has not yet been implemented")
|
||||
}),
|
||||
@@ -168,6 +175,9 @@ type McsAPI struct {
|
||||
// - application/json
|
||||
JSONConsumer runtime.Consumer
|
||||
|
||||
// BinProducer registers a producer for the following mime types:
|
||||
// - application/octet-stream
|
||||
BinProducer runtime.Producer
|
||||
// JSONProducer registers a producer for the following mime types:
|
||||
// - application/json
|
||||
JSONProducer runtime.Producer
|
||||
@@ -215,6 +225,10 @@ type McsAPI struct {
|
||||
UserAPIMakeBucketHandler user_api.MakeBucketHandler
|
||||
// AdminAPIPolicyInfoHandler sets the operation handler for the policy info operation
|
||||
AdminAPIPolicyInfoHandler admin_api.PolicyInfoHandler
|
||||
// AdminAPIProfilingStartHandler sets the operation handler for the profiling start operation
|
||||
AdminAPIProfilingStartHandler admin_api.ProfilingStartHandler
|
||||
// AdminAPIProfilingStopHandler sets the operation handler for the profiling stop operation
|
||||
AdminAPIProfilingStopHandler admin_api.ProfilingStopHandler
|
||||
// AdminAPIRemoveGroupHandler sets the operation handler for the remove group operation
|
||||
AdminAPIRemoveGroupHandler admin_api.RemoveGroupHandler
|
||||
// AdminAPIRemovePolicyHandler sets the operation handler for the remove policy operation
|
||||
@@ -289,6 +303,9 @@ func (o *McsAPI) Validate() error {
|
||||
unregistered = append(unregistered, "JSONConsumer")
|
||||
}
|
||||
|
||||
if o.BinProducer == nil {
|
||||
unregistered = append(unregistered, "BinProducer")
|
||||
}
|
||||
if o.JSONProducer == nil {
|
||||
unregistered = append(unregistered, "JSONProducer")
|
||||
}
|
||||
@@ -351,6 +368,12 @@ func (o *McsAPI) Validate() error {
|
||||
if o.AdminAPIPolicyInfoHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.PolicyInfoHandler")
|
||||
}
|
||||
if o.AdminAPIProfilingStartHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.ProfilingStartHandler")
|
||||
}
|
||||
if o.AdminAPIProfilingStopHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.ProfilingStopHandler")
|
||||
}
|
||||
if o.AdminAPIRemoveGroupHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.RemoveGroupHandler")
|
||||
}
|
||||
@@ -423,6 +446,8 @@ func (o *McsAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
|
||||
result := make(map[string]runtime.Producer, len(mediaTypes))
|
||||
for _, mt := range mediaTypes {
|
||||
switch mt {
|
||||
case "application/octet-stream":
|
||||
result["application/octet-stream"] = o.BinProducer
|
||||
case "application/json":
|
||||
result["application/json"] = o.JSONProducer
|
||||
}
|
||||
@@ -537,6 +562,14 @@ func (o *McsAPI) initHandlerCache() {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/api/v1/policies/{name}"] = admin_api.NewPolicyInfo(o.context, o.AdminAPIPolicyInfoHandler)
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["POST"]["/api/v1/profiling/start"] = admin_api.NewProfilingStart(o.context, o.AdminAPIProfilingStartHandler)
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["POST"]["/api/v1/profiling/stop"] = admin_api.NewProfilingStop(o.context, o.AdminAPIProfilingStopHandler)
|
||||
if o.handlers["DELETE"] == nil {
|
||||
o.handlers["DELETE"] = make(map[string]http.Handler)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ func login(mc McCmd, accessKey, secretKey *string) (*string, error) {
|
||||
// Probe the credentials
|
||||
cfg, pErr := mc.BuildS3Config(getMinIOServer(), *accessKey, *secretKey, "", "auto")
|
||||
if pErr != nil {
|
||||
log.Println(pErr)
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
// if we made it here, the credentials work, generate a session
|
||||
|
||||
79
swagger.yml
79
swagger.yml
@@ -270,7 +270,7 @@ paths:
|
||||
tags:
|
||||
- AdminAPI
|
||||
delete:
|
||||
summary: Remove group
|
||||
summary: Remove group
|
||||
operationId: RemoveGroup
|
||||
parameters:
|
||||
- name: name
|
||||
@@ -536,6 +536,44 @@ paths:
|
||||
security: []
|
||||
tags:
|
||||
- UserAPI
|
||||
/api/v1/profiling/start:
|
||||
post:
|
||||
summary: Start recording profile data
|
||||
operationId: ProfilingStart
|
||||
parameters:
|
||||
- name: body
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/profilingStartRequest'
|
||||
responses:
|
||||
201:
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/startProfilingList'
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
/api/v1/profiling/stop:
|
||||
post:
|
||||
summary: Stop and download profile data
|
||||
operationId: ProfilingStop
|
||||
produces:
|
||||
- application/octet-stream
|
||||
responses:
|
||||
201:
|
||||
description: A successful response.
|
||||
schema:
|
||||
type: file
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
definitions:
|
||||
bucketAccess:
|
||||
type: string
|
||||
@@ -819,7 +857,7 @@ definitions:
|
||||
- access
|
||||
properties:
|
||||
access:
|
||||
$ref: "#/definitions/bucketAccess"
|
||||
$ref: "#/definitions/bucketAccess"
|
||||
loginDetails:
|
||||
type: object
|
||||
properties:
|
||||
@@ -846,3 +884,40 @@ definitions:
|
||||
# Structure that holds the `Bearer {TOKEN}` present on authenticated requests
|
||||
principal:
|
||||
type: string
|
||||
startProfilingItem:
|
||||
type: object
|
||||
properties:
|
||||
nodeName:
|
||||
type: string
|
||||
success:
|
||||
type: boolean
|
||||
error:
|
||||
type: string
|
||||
startProfilingList:
|
||||
type: object
|
||||
properties:
|
||||
total:
|
||||
type: integer
|
||||
format: int64
|
||||
title: number of start results
|
||||
startResults:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/startProfilingItem"
|
||||
profilerType:
|
||||
type: string
|
||||
enum:
|
||||
- cpu
|
||||
- mem
|
||||
- block
|
||||
- mutex
|
||||
- trace
|
||||
- threads
|
||||
- goroutines
|
||||
profilingStartRequest:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
properties:
|
||||
type:
|
||||
$ref: "#/definitions/profilerType"
|
||||
Reference in New Issue
Block a user