Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add State methods for workload processes. #2674

Merged
merged 66 commits into from Jul 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
489bd74
Add a new state collection.
ericsnowcurrently Jun 22, 2015
9d6c1d7
Add stubs for WPM-related State methods.
ericsnowcurrently Jun 22, 2015
ebdd03b
Implement the business logic of state.
ericsnowcurrently Jun 22, 2015
d4437e4
Move the collection name into the right place.
ericsnowcurrently Jun 23, 2015
c80544f
Move persistence into own file.
ericsnowcurrently Jun 23, 2015
154e03f
Implement ensureDefinitions.
ericsnowcurrently Jun 23, 2015
f699707
Add infoSuite.newInfo.
ericsnowcurrently Jun 23, 2015
270b01d
Add Info.CharmID and Info.UnitID.
ericsnowcurrently Jun 23, 2015
5d837ea
Add Info.ID and Info.FullID.
ericsnowcurrently Jun 23, 2015
fff57a1
Validate Info.Details.
ericsnowcurrently Jun 23, 2015
aad9343
Add ParseID.
ericsnowcurrently Jun 23, 2015
3271148
Move ID generation into the persistence layer.
ericsnowcurrently Jun 23, 2015
6de5226
Implement insert (persistence).
ericsnowcurrently Jun 23, 2015
8392713
Serialize the compound values from charm.Process.
ericsnowcurrently Jun 23, 2015
41b46c3
Implement setStatus (persistence).
ericsnowcurrently Jun 23, 2015
7095d17
Implement list (persistence).
ericsnowcurrently Jun 23, 2015
fca23a0
Implement remove (persistence).
ericsnowcurrently Jun 23, 2015
19a9938
Add a processesPersistence interface.
ericsnowcurrently Jun 24, 2015
f345b83
Handle the case where the definition might collide.
ericsnowcurrently Jun 24, 2015
551c0df
Clean up setRawStatus ops.
ericsnowcurrently Jun 24, 2015
3876bc9
Add a couple TODOs.
ericsnowcurrently Jun 24, 2015
6a6c50b
Fix a couple typos.
ericsnowcurrently Jun 24, 2015
630dba8
Export the state implementation methods.
ericsnowcurrently Jun 25, 2015
5dde33a
Export the high-level persistence methods and clean them up.
ericsnowcurrently Jun 25, 2015
3850c06
Frame out the test suites.
ericsnowcurrently Jun 25, 2015
e923aa5
Add some suite helpers.
ericsnowcurrently Jun 25, 2015
e08ec95
Implement fakeProcsPersistence.
ericsnowcurrently Jun 25, 2015
2fc5ec4
Export ProcessDefintions and UnitProcesses.
ericsnowcurrently Jun 25, 2015
4e99f25
Fix an error return.
ericsnowcurrently Jun 25, 2015
c16a40d
Fix fakeProcsPersistence.
ericsnowcurrently Jun 25, 2015
3d72658
Implement tests for ProcessDefinitions.
ericsnowcurrently Jun 25, 2015
c55b5b2
Add a TODO.
ericsnowcurrently Jun 25, 2015
09b6df6
Fix an error return.
ericsnowcurrently Jun 25, 2015
32e2ed0
Add tests for unitProcesses.Register.
ericsnowcurrently Jun 25, 2015
d6fdd23
Add tests for unitProcesses.SetStatus.
ericsnowcurrently Jun 26, 2015
cee273b
Add tests for unitProcesses.List.
ericsnowcurrently Jun 26, 2015
00c0773
Add tests for unitProcesses.Unregister.
ericsnowcurrently Jun 26, 2015
21fedf1
Factor out the collection type.
ericsnowcurrently Jun 26, 2015
1a6ef64
Hide the collection.
ericsnowcurrently Jun 26, 2015
491ce97
Fix newProcsPersistence.
ericsnowcurrently Jun 26, 2015
32b05f2
Stub out procsPersistenceSuite and add fakeStatePersistence.
ericsnowcurrently Jun 26, 2015
9abb56f
Export the doc types.
ericsnowcurrently Jun 26, 2015
7231592
Add tests for procPersistence.EnsureDefinitions.
ericsnowcurrently Jun 27, 2015
ad94110
Add some tests for procPersistence.Insert.
ericsnowcurrently Jun 27, 2015
f58d6f8
Add remaining tests for procPersistence.Insert.
ericsnowcurrently Jun 27, 2015
71bf834
Add tests for procPersistence.SetStatus.
ericsnowcurrently Jun 29, 2015
bf94886
Add tests for procPersistence.List and ListAll.
ericsnowcurrently Jun 29, 2015
fc75d2f
Add tests for procPersistence.Remove.
ericsnowcurrently Jun 29, 2015
c2eef28
Clean up a little.
ericsnowcurrently Jun 29, 2015
557884b
Fix a test.
ericsnowcurrently Jun 29, 2015
8b8a5a9
Add charm-defined proc definitions when listing all.
ericsnowcurrently Jun 29, 2015
19ce034
Drop Info.FullID and the CharmID/UnitID fields.
ericsnowcurrently Jun 30, 2015
8d4d921
Fix a copy-and-paste error.
ericsnowcurrently Jun 30, 2015
7f9e174
Add a TODO.
ericsnowcurrently Jun 30, 2015
99d88df
Adjust some field/type names.
ericsnowcurrently Jun 30, 2015
4868625
Move the processes state code over under the process package.
ericsnowcurrently Jun 30, 2015
d941536
Register the component with state.
ericsnowcurrently Jun 30, 2015
45d24c5
Connect the state code to the API.
ericsnowcurrently Jul 1, 2015
589adbf
Add envUUID to $in queries.
ericsnowcurrently Jul 1, 2015
828e555
Add a DocKind field to process-related docs.
ericsnowcurrently Jul 1, 2015
e1cd0b4
Set found correctly.
ericsnowcurrently Jul 1, 2015
17b7a47
Convert a doc into a definition correctly.
ericsnowcurrently Jul 1, 2015
cbc3d74
Be more careful when comparing definitions.
ericsnowcurrently Jul 1, 2015
63be613
Track queried docs more accurately.
ericsnowcurrently Jul 1, 2015
66b6045
Add a functional test for the State methods.
ericsnowcurrently Jul 1, 2015
1368b17
Be careful about how we drop the environ UUID from doc IDs.
ericsnowcurrently Jul 2, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions component/all/process.go
Expand Up @@ -6,13 +6,15 @@ package all
import (
"github.com/juju/cmd"
"github.com/juju/errors"
"github.com/juju/names"

"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/process"
"github.com/juju/juju/process/api"
"github.com/juju/juju/process/api/server"
"github.com/juju/juju/process/context"
"github.com/juju/juju/process/plugin"
procstate "github.com/juju/juju/process/state"
"github.com/juju/juju/state"
"github.com/juju/juju/worker/uniter/runner"
"github.com/juju/juju/worker/uniter/runner/jujuc"
Expand All @@ -22,6 +24,7 @@ type workloadProcesses struct{}

func (c workloadProcesses) registerForServer() error {
c.registerHookContext()
c.registerState()
return nil
}

Expand Down Expand Up @@ -111,3 +114,13 @@ func (workloadProcesses) registerHookContextCommands() {
return cmd
})
}

func (c workloadProcesses) registerState() {
newUnitProcesses := func(persist state.Persistence, unit names.UnitTag, charm names.CharmTag) (state.UnitProcesses, error) {
return procstate.NewUnitProcesses(persist, unit, &charm), nil
}
newProcessDefinitions := func(persist state.Persistence, charm names.CharmTag) (state.ProcessDefinitions, error) {
return procstate.NewDefinitions(persist, charm), nil
}
state.SetProcessesComponent(newUnitProcesses, newProcessDefinitions)
}
15 changes: 5 additions & 10 deletions process/api/server/hookcontext.go
Expand Up @@ -3,6 +3,8 @@

package server

// TODO(ericsnow) Eliminate the apiserver/common import if possible.

import (
"github.com/juju/errors"
"github.com/juju/loggo"
Expand Down Expand Up @@ -59,8 +61,7 @@ func (a HookContextAPI) RegisterProcesses(args api.RegisterProcessesArgs) (api.P
for _, apiProc := range args.Processes {
info := api.API2Proc(apiProc)
res := api.ProcessResult{
ID: info.Name + "/" + info.Details.ID,
//ID: info.ID(),
ID: info.ID(),
}
if err := st.Register(info); err != nil {
res.Error = common.ServerError(errors.Trace(err))
Expand Down Expand Up @@ -94,12 +95,7 @@ func (a HookContextAPI) ListProcesses(args api.ListProcessesArgs) (api.ListProce

if len(ids) == 0 {
for _, proc := range procs {
id := proc.Name
if proc.Details.ID != "" {
id += "/" + proc.Details.ID
}
ids = append(ids, id)
//ids = append(ids, info.ID())
ids = append(ids, proc.ID())
}
}

Expand All @@ -114,8 +110,7 @@ func (a HookContextAPI) ListProcesses(args api.ListProcessesArgs) (api.ListProce
if proc.Details.ID != "" {
procID += "/" + proc.Details.ID
}
//if id == proc.ID() {
if id == procID {
if id == proc.ID() {
res.Info = api.Proc2api(proc)
found = true
break
Expand Down
28 changes: 28 additions & 0 deletions process/info.go
Expand Up @@ -4,7 +4,9 @@
package process

import (
"fmt"
"reflect"
"strings"

"github.com/juju/errors"
"gopkg.in/juju/charm.v5"
Expand All @@ -24,6 +26,8 @@ type Info struct {
Details Details
}

// TODO(ericsnow) Eliminate NewInfoUnvalidated.

// NewInfoUnvalidated builds a new Info object with the provided
// values. The returned Info may be invalid if the given values cause
// that result. The Validate method can be used to check.
Expand All @@ -36,12 +40,36 @@ func NewInfoUnvalidated(name, procType string) *Info {
}
}

// ID composes a unique ID for the process (relative to the unit/charm).
func (info Info) ID() string {
id := info.Process.Name
if info.Details.ID != "" {
id = fmt.Sprintf("%s/%s", id, info.Details.ID)
}
return id
}

// ParseID extracts the process name and details ID from the provided string.
func ParseID(id string) (string, string) {
parts := strings.SplitN(id, "/", 2)
if len(parts) == 2 {
return parts[0], parts[1]
}
return id, ""
}

// Validate checks the process info to ensure it is correct.
func (info Info) Validate() error {
if err := info.Process.Validate(); err != nil {
return errors.Trace(err)
}

if !reflect.DeepEqual(info.Details, Details{}) {
if err := info.Details.Validate(); err != nil {
return errors.Trace(err)
}
}

return nil
}

Expand Down
70 changes: 66 additions & 4 deletions process/info_test.go
Expand Up @@ -6,6 +6,7 @@ package process_test
import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"
"gopkg.in/juju/charm.v5"

"github.com/juju/juju/process"
"github.com/juju/juju/testing"
Expand All @@ -17,30 +18,91 @@ type infoSuite struct {

var _ = gc.Suite(&infoSuite{})

func (s *infoSuite) newInfo(name, procType string) *process.Info {
return &process.Info{
Process: charm.Process{
Name: name,
Type: procType,
},
}
}

func (s *infoSuite) TestIDFull(c *gc.C) {
info := s.newInfo("a-proc", "docker")
info.Details.ID = "my-proc"
id := info.ID()

c.Check(id, gc.Equals, "a-proc/my-proc")
}

func (s *infoSuite) TestIDMissingDetailsID(c *gc.C) {
info := s.newInfo("a-proc", "docker")
id := info.ID()

c.Check(id, gc.Equals, "a-proc")
}

func (s *infoSuite) TestIDNameOnly(c *gc.C) {
info := s.newInfo("a-proc", "docker")
id := info.ID()

c.Check(id, gc.Equals, "a-proc")
}

func (s *infoSuite) TestParseIDFull(c *gc.C) {
name, id := process.ParseID("a-proc/my-proc")

c.Check(name, gc.Equals, "a-proc")
c.Check(id, gc.Equals, "my-proc")
}

func (s *infoSuite) TestParseIDNameOnly(c *gc.C) {
name, id := process.ParseID("a-proc")

c.Check(name, gc.Equals, "a-proc")
c.Check(id, gc.Equals, "")
}

func (s *infoSuite) TestParseIDExtras(c *gc.C) {
name, id := process.ParseID("somecharm/0/a-proc/my-proc")

c.Check(name, gc.Equals, "somecharm")
c.Check(id, gc.Equals, "0/a-proc/my-proc")
}

func (s *infoSuite) TestValidateOkay(c *gc.C) {
info := process.NewInfoUnvalidated("a proc", "docker")
info := s.newInfo("a proc", "docker")
err := info.Validate()

c.Check(err, jc.ErrorIsNil)
}

func (s *infoSuite) TestValidateBadMetadata(c *gc.C) {
info := process.NewInfoUnvalidated("a proc", "")
info := s.newInfo("a proc", "")
err := info.Validate()

c.Check(err, gc.ErrorMatches, ".*type: name is required")
}

func (s *infoSuite) TestValidateBadDetails(c *gc.C) {
info := s.newInfo("a proc", "docker")
info.Details.ID = "my-proc"
err := info.Validate()

c.Check(err, gc.ErrorMatches, ".*Label cannot be empty.*")
}

func (s *infoSuite) TestIsRegisteredTrue(c *gc.C) {
info := process.NewInfoUnvalidated("a proc", "docker")
info := s.newInfo("a proc", "docker")
info.Details.ID = "abc123"
info.Details.Status.Label = "running"
isRegistered := info.IsRegistered()

c.Check(isRegistered, jc.IsTrue)
}

func (s *infoSuite) TestIsRegisteredFalse(c *gc.C) {
info := process.NewInfoUnvalidated("a proc", "docker")
info := s.newInfo("a proc", "docker")
isRegistered := info.IsRegistered()

c.Check(isRegistered, jc.IsFalse)
Expand Down
87 changes: 87 additions & 0 deletions process/persistence/base_test.go
@@ -0,0 +1,87 @@
// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package persistence_test

import (
"fmt"

"github.com/juju/names"
gitjujutesting "github.com/juju/testing"
"github.com/juju/utils"
gc "gopkg.in/check.v1"
"gopkg.in/juju/charm.v5"

"github.com/juju/juju/process"
"github.com/juju/juju/testing"
)

type baseProcessesSuite struct {
testing.BaseSuite

stub *gitjujutesting.Stub
charm names.CharmTag
unit names.UnitTag
}

func (s *baseProcessesSuite) SetUpTest(c *gc.C) {
s.BaseSuite.SetUpTest(c)

s.stub = &gitjujutesting.Stub{}
s.charm = names.NewCharmTag("local:series/dummy-1")
s.unit = names.NewUnitTag("a-unit/0")
}

func (s *baseProcessesSuite) setUnit(id string) {
if id == "" {
s.unit = names.UnitTag{}
} else {
s.unit = names.NewUnitTag(id)
}
}

func (s *baseProcessesSuite) setCharm(id string) {
if id == "" {
s.charm = names.CharmTag{}
} else {
s.charm = names.NewCharmTag(id)
}
}

func (s *baseProcessesSuite) newDefinitions(pType string, names ...string) []charm.Process {
var definitions []charm.Process
for _, name := range names {
definitions = append(definitions, charm.Process{
Name: name,
Type: pType,
})
}
return definitions
}

func (s *baseProcessesSuite) newProcesses(pType string, names ...string) []process.Info {
var ids []string
for i, name := range names {
name, id := process.ParseID(name)
names[i] = name
if id == "" {
id = fmt.Sprintf("%s-%s", name, utils.MustNewUUID())
}
ids = append(ids, id)
}

var processes []process.Info
for i, definition := range s.newDefinitions(pType, names...) {
id := ids[i]
processes = append(processes, process.Info{
Process: definition,
Details: process.Details{
ID: id,
Status: process.Status{
Label: "running",
},
},
})
}
return processes
}