Skip to content

Commit

Permalink
Persist user email who locked or reserved a machine in DB #303 (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
vknabel committed Aug 11, 2022
1 parent f81e576 commit 0f9a9d3
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 1 deletion.
1 change: 1 addition & 0 deletions cmd/metal-api/internal/metal/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var (
type MachineState struct {
Value MState `rethinkdb:"value" json:"value"`
Description string `rethinkdb:"description" json:"description"`
Issuer string `rethinkdb:"issuer" json:"issuer,omitempty"`
MetalHammerVersion string `rethinkdb:"metal_hammer_version" json:"metal_hammer_version"`
}

Expand Down
11 changes: 11 additions & 0 deletions cmd/metal-api/internal/service/machine-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,16 @@ func (r *machineResource) setMachineState(request *restful.Request, response *re
return
}

user, err := r.userGetter.User(request.Request)
if err != nil {
r.sendError(request, response, defaultError(err))
return
}
userEMail := user.EMail
if machineState == metal.AvailableState {
userEMail = ""
}

id := request.PathParameter("id")
oldMachine, err := r.ds.FindMachineByID(id)
if err != nil {
Expand All @@ -640,6 +650,7 @@ func (r *machineResource) setMachineState(request *restful.Request, response *re
newMachine.State = metal.MachineState{
Value: machineState,
Description: requestPayload.Description,
Issuer: userEMail,
}

err = r.ds.UpdateMachine(oldMachine, &newMachine)
Expand Down
58 changes: 57 additions & 1 deletion cmd/metal-api/internal/service/machine-service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/metal-stack/metal-api/cmd/metal-api/internal/testdata"
"github.com/metal-stack/metal-lib/bus"
"github.com/metal-stack/metal-lib/httperrors"
"github.com/metal-stack/security"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
Expand Down Expand Up @@ -45,6 +46,14 @@ func (p *emptyPublisher) CreateTopic(topic string) error {

func (p *emptyPublisher) Stop() {}

type mockUserGetter struct {
user *security.User
}

func (m mockUserGetter) User(rq *http.Request) (*security.User, error) {
return m.user, nil
}

func TestGetMachines(t *testing.T) {
ds, mock := datastore.InitMockDB(t)
testdata.InitMockDBData(mock)
Expand Down Expand Up @@ -488,7 +497,12 @@ func TestSetMachineState(t *testing.T) {
testdata.InitMockDBData(mock)
log := zaptest.NewLogger(t).Sugar()

machineservice, err := NewMachine(log, ds, &emptyPublisher{}, bus.DirectEndpoints(), ipam.New(goipam.New()), nil, nil, nil, 0)
userGetter := mockUserGetter{&security.User{
EMail: "anonymous@metal-stack.io",
Name: "anonymous",
}}

machineservice, err := NewMachine(log, ds, &emptyPublisher{}, bus.DirectEndpoints(), ipam.New(goipam.New()), nil, nil, userGetter, 0)
require.NoError(t, err)

container := restful.NewContainer().Add(machineservice)
Expand Down Expand Up @@ -516,6 +530,48 @@ func TestSetMachineState(t *testing.T) {
require.Equal(t, "1", result.ID)
require.Equal(t, string(metal.ReservedState), result.State.Value)
require.Equal(t, "blubber", result.State.Description)
require.Equal(t, "anonymous@metal-stack.io", result.State.Issuer)
}

func TestSetMachineStateIssuerResetWhenAvailable(t *testing.T) {
ds, mock := datastore.InitMockDB(t)
testdata.InitMockDBData(mock)
log := zaptest.NewLogger(t).Sugar()

userGetter := mockUserGetter{&security.User{
EMail: "anonymous@metal-stack.io",
Name: "anonymous",
}}

machineservice, err := NewMachine(log, ds, &emptyPublisher{}, bus.DirectEndpoints(), ipam.New(goipam.New()), nil, nil, userGetter, 0)
require.NoError(t, err)

container := restful.NewContainer().Add(machineservice)

stateRequest := v1.MachineState{
Value: string(metal.AvailableState),
Description: "",
}
js, err := json.Marshal(stateRequest)
require.NoError(t, err)
body := bytes.NewBuffer(js)
req := httptest.NewRequest("POST", "/v1/machine/1/state", body)
req.Header.Add("Content-Type", "application/json")
container = injectEditor(log, container, req)
w := httptest.NewRecorder()
container.ServeHTTP(w, req)

resp := w.Result()
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode, w.Body.String())
var result v1.MachineResponse
err = json.NewDecoder(resp.Body).Decode(&result)

require.NoError(t, err)
require.Equal(t, "1", result.ID)
require.Equal(t, string(metal.AvailableState), result.State.Value)
require.Equal(t, "", result.State.Description)
require.Equal(t, "", result.State.Issuer)
}

func TestGetMachine(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions cmd/metal-api/internal/service/v1/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type MachineHardware struct {
type MachineState struct {
Value string `json:"value" enum:"RESERVED|LOCKED|" description:"the state of this machine. empty means available for all"`
Description string `json:"description" description:"a description why this machine is in the given state"`
Issuer string `json:"issuer,omitempty" optional:"true" description:"the user that changed the state"`
MetalHammerVersion string `json:"metal_hammer_version" description:"the version of metal hammer which put the machine in waiting state"`
}

Expand Down Expand Up @@ -504,6 +505,7 @@ func NewMachineResponse(m *metal.Machine, s *metal.Size, p *metal.Partition, i *
State: MachineState{
Value: string(m.State.Value),
Description: m.State.Description,
Issuer: m.State.Issuer,
MetalHammerVersion: m.State.MetalHammerVersion,
},
LEDState: ChassisIdentifyLEDState{
Expand Down
4 changes: 4 additions & 0 deletions spec/metal-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -2915,6 +2915,10 @@
"description": "a description why this machine is in the given state",
"type": "string"
},
"issuer": {
"description": "the user that changed the state",
"type": "string"
},
"metal_hammer_version": {
"description": "the version of metal hammer which put the machine in waiting state",
"type": "string"
Expand Down

0 comments on commit 0f9a9d3

Please sign in to comment.