github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/common/password_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/names.v2"
    13  
    14  	"github.com/juju/juju/apiserver/common"
    15  	"github.com/juju/juju/apiserver/params"
    16  	apiservertesting "github.com/juju/juju/apiserver/testing"
    17  	"github.com/juju/juju/state"
    18  )
    19  
    20  type passwordSuite struct{}
    21  
    22  var _ = gc.Suite(&passwordSuite{})
    23  
    24  type entityWithError interface {
    25  	state.Entity
    26  	error() error
    27  }
    28  
    29  type fakeState struct {
    30  	entities map[names.Tag]entityWithError
    31  }
    32  
    33  func (st *fakeState) FindEntity(tag names.Tag) (state.Entity, error) {
    34  	entity, ok := st.entities[tag]
    35  	if !ok {
    36  		return nil, errors.NotFoundf("entity %q", tag)
    37  	}
    38  	if err := entity.error(); err != nil {
    39  		return nil, err
    40  	}
    41  	return entity, nil
    42  }
    43  
    44  type fetchError string
    45  
    46  func (f fetchError) error() error {
    47  	if f == "" {
    48  		return nil
    49  	}
    50  	return fmt.Errorf("%s", string(f))
    51  }
    52  
    53  type fakeAuthenticator struct {
    54  	// Any Authenticator methods we don't implement on fakeAuthenticator
    55  	// will fall back to this and panic because it's always nil.
    56  	state.Authenticator
    57  	state.Entity
    58  	err  error
    59  	pass string
    60  	fetchError
    61  }
    62  
    63  func (a *fakeAuthenticator) SetPassword(pass string) error {
    64  	if a.err != nil {
    65  		return a.err
    66  	}
    67  	a.pass = pass
    68  	return nil
    69  }
    70  
    71  // fakeUnitAuthenticator simulates a unit entity.
    72  type fakeUnitAuthenticator struct {
    73  	fakeAuthenticator
    74  	mongoPass string
    75  }
    76  
    77  func (a *fakeUnitAuthenticator) Tag() names.Tag {
    78  	return names.NewUnitTag("fake/0")
    79  }
    80  
    81  func (a *fakeUnitAuthenticator) SetMongoPassword(pass string) error {
    82  	if a.err != nil {
    83  		return a.err
    84  	}
    85  	a.mongoPass = pass
    86  	return nil
    87  }
    88  
    89  // fakeMachineAuthenticator simulates a machine entity.
    90  type fakeMachineAuthenticator struct {
    91  	fakeUnitAuthenticator
    92  	jobs []state.MachineJob
    93  }
    94  
    95  func (a *fakeMachineAuthenticator) Jobs() []state.MachineJob {
    96  	return a.jobs
    97  }
    98  
    99  func (a *fakeMachineAuthenticator) Tag() names.Tag {
   100  	return names.NewMachineTag("0")
   101  }
   102  
   103  func (*passwordSuite) TestSetPasswords(c *gc.C) {
   104  	st := &fakeState{
   105  		entities: map[names.Tag]entityWithError{
   106  			u("x/0"): &fakeAuthenticator{},
   107  			u("x/1"): &fakeAuthenticator{},
   108  			u("x/2"): &fakeAuthenticator{
   109  				err: fmt.Errorf("x2 error"),
   110  			},
   111  			u("x/3"): &fakeAuthenticator{
   112  				fetchError: "x3 error",
   113  			},
   114  			u("x/4"): &fakeUnitAuthenticator{},
   115  			u("x/5"): &fakeMachineAuthenticator{jobs: []state.MachineJob{state.JobHostUnits}},
   116  			u("x/6"): &fakeMachineAuthenticator{jobs: []state.MachineJob{state.JobManageModel}},
   117  		},
   118  	}
   119  	getCanChange := func() (common.AuthFunc, error) {
   120  		return func(tag names.Tag) bool {
   121  			return tag != names.NewUnitTag("x/0")
   122  		}, nil
   123  	}
   124  	pc := common.NewPasswordChanger(st, getCanChange)
   125  	var changes []params.EntityPassword
   126  	for i := 0; i < len(st.entities); i++ {
   127  		tag := fmt.Sprintf("unit-x-%d", i)
   128  		changes = append(changes, params.EntityPassword{
   129  			Tag:      tag,
   130  			Password: fmt.Sprintf("%spass", tag),
   131  		})
   132  	}
   133  	results, err := pc.SetPasswords(params.EntityPasswords{
   134  		Changes: changes,
   135  	})
   136  	c.Assert(err, jc.ErrorIsNil)
   137  	c.Assert(results, jc.DeepEquals, params.ErrorResults{
   138  		Results: []params.ErrorResult{
   139  			{apiservertesting.ErrUnauthorized},
   140  			{nil},
   141  			{&params.Error{Message: "x2 error"}},
   142  			{&params.Error{Message: "x3 error"}},
   143  			{nil},
   144  			{nil},
   145  			{nil},
   146  		},
   147  	})
   148  	c.Check(st.entities[u("x/0")].(*fakeAuthenticator).pass, gc.Equals, "")
   149  	c.Check(st.entities[u("x/1")].(*fakeAuthenticator).pass, gc.Equals, "unit-x-1pass")
   150  	c.Check(st.entities[u("x/2")].(*fakeAuthenticator).pass, gc.Equals, "")
   151  	c.Check(st.entities[u("x/4")].(*fakeUnitAuthenticator).pass, gc.Equals, "unit-x-4pass")
   152  	c.Check(st.entities[u("x/4")].(*fakeUnitAuthenticator).mongoPass, gc.Equals, "")
   153  	c.Check(st.entities[u("x/5")].(*fakeMachineAuthenticator).pass, gc.Equals, "unit-x-5pass")
   154  	c.Check(st.entities[u("x/5")].(*fakeMachineAuthenticator).mongoPass, gc.Equals, "")
   155  	c.Check(st.entities[u("x/6")].(*fakeMachineAuthenticator).pass, gc.Equals, "unit-x-6pass")
   156  	c.Check(st.entities[u("x/6")].(*fakeMachineAuthenticator).mongoPass, gc.Equals, "unit-x-6pass")
   157  }
   158  
   159  func (*passwordSuite) TestSetPasswordsError(c *gc.C) {
   160  	getCanChange := func() (common.AuthFunc, error) {
   161  		return nil, fmt.Errorf("splat")
   162  	}
   163  	pc := common.NewPasswordChanger(&fakeState{}, getCanChange)
   164  	var changes []params.EntityPassword
   165  	for i := 0; i < 4; i++ {
   166  		tag := fmt.Sprintf("x%d", i)
   167  		changes = append(changes, params.EntityPassword{
   168  			Tag:      tag,
   169  			Password: fmt.Sprintf("%spass", tag),
   170  		})
   171  	}
   172  	_, err := pc.SetPasswords(params.EntityPasswords{Changes: changes})
   173  	c.Assert(err, gc.ErrorMatches, "splat")
   174  }
   175  
   176  func (*passwordSuite) TestSetPasswordsNoArgsNoError(c *gc.C) {
   177  	getCanChange := func() (common.AuthFunc, error) {
   178  		return nil, fmt.Errorf("splat")
   179  	}
   180  	pc := common.NewPasswordChanger(&fakeState{}, getCanChange)
   181  	result, err := pc.SetPasswords(params.EntityPasswords{})
   182  	c.Assert(err, jc.ErrorIsNil)
   183  	c.Assert(result.Results, gc.HasLen, 0)
   184  }