Skip to content

Commit

Permalink
Merge pull request #21 from silinternational/feature/config-verbosity
Browse files Browse the repository at this point in the history
add config option to set output verbosity
  • Loading branch information
briskt authored Nov 13, 2019
2 parents d7a9ff2 + 6f1737b commit 8b81a64
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 47 deletions.
2 changes: 1 addition & 1 deletion cmd/syncpeeps.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func main() {
}

// Perform sync and get results
changeResults := personnel_sync.SyncPeople(source, destination, appConfig.AttributeMap, appConfig.Runtime.DryRunMode)
changeResults := personnel_sync.SyncPeople(source, destination, appConfig)

log.Printf("Sync results: %v users added, %v users updated, %v users removed, %v errors\n",
changeResults.Created, changeResults.Updated, changeResults.Deleted, len(changeResults.Errors))
Expand Down
4 changes: 2 additions & 2 deletions config.example.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Runtime": {
"FailIfSinglePersonMissingCompareValue": false,
"DryRunMode": false
"DryRunMode": false,
"Verbosity": 1
},
"Source": {
"Type": "RestAPI",
Expand Down
51 changes: 32 additions & 19 deletions domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import (
"time"
)

const DefaultConfigFile = "./config.json"
const DestinationTypeGoogleGroups = "GoogleGroups"
const DestinationTypeGoogleUsers = "GoogleUsers"
const DestinationTypeWebHelpDesk = "WebHelpDesk"
const SourceTypeRestAPI = "RestAPI"
const (
DefaultConfigFile = "./config.json"
DefaultVerbosity = 5
DestinationTypeGoogleGroups = "GoogleGroups"
DestinationTypeGoogleUsers = "GoogleUsers"
DestinationTypeWebHelpDesk = "WebHelpDesk"
SourceTypeRestAPI = "RestAPI"
)

// LoadConfig looks for a config file if one is provided. Otherwise, it looks for
// a config file based on the CONFIG_PATH env var. If that is not set, it gets
Expand All @@ -36,7 +39,11 @@ func LoadConfig(configFile string) (AppConfig, error) {
return AppConfig{}, err
}

config := AppConfig{}
config := AppConfig{
Runtime: RuntimeConfig{
Verbosity: DefaultVerbosity,
},
}
err = json.Unmarshal(data, &config)
if err != nil {
log.Printf("unable to unmarshal application configuration file data, error: %s\n", err.Error())
Expand Down Expand Up @@ -114,17 +121,23 @@ func getPersonFromList(compareValue string, peopleList []Person) Person {
return Person{}
}

func personAttributesAreEqual(sp, dp Person, attributeMap []AttributeMap) bool {
caseSensitivityList := getCaseSensitivitySourceAttributeList(attributeMap)
func personAttributesAreEqual(sp, dp Person, config AppConfig) bool {
caseSensitivityList := getCaseSensitivitySourceAttributeList(config.AttributeMap)
equal := true
for key, val := range sp.Attributes {
if !stringsAreEqual(val, dp.Attributes[key], caseSensitivityList[key]) {
log.Printf("Attribute %s not equal for user %s. Case Sensitive: %v, Source: %s, Destination: %s \n",
key, sp.CompareValue, caseSensitivityList[key], val, dp.Attributes[key])
return false
if config.Runtime.Verbosity >= VerbosityMedium {
log.Printf(`User: "%s", "%s" not equal, CaseSensitive: "%t", Source: "%s", Dest: "%s"`+"\n",
sp.CompareValue, key, caseSensitivityList[key], val, dp.Attributes[key])
equal = false
} else {
log.Printf(`User: "%s" not equal`+"\n", key)
return false
}
}
}

return true
return equal
}

func stringsAreEqual(val1, val2 string, caseSensitive bool) bool {
Expand All @@ -149,7 +162,7 @@ func getCaseSensitivitySourceAttributeList(attributeMap []AttributeMap) map[stri
// (Create, Update and Delete) based on whether they are in the slice
// of destination Person instances.
// It skips all source Person instances that have DisableChanges set to true
func GenerateChangeSet(sourcePeople, destinationPeople []Person, attributeMap []AttributeMap, idField string) ChangeSet {
func GenerateChangeSet(sourcePeople, destinationPeople []Person, config AppConfig, idField string) ChangeSet {
var changeSet ChangeSet

// Find users who need to be created or updated
Expand All @@ -165,7 +178,7 @@ func GenerateChangeSet(sourcePeople, destinationPeople []Person, attributeMap []
continue
}

if !personAttributesAreEqual(sp, destinationPerson, attributeMap) {
if !personAttributesAreEqual(sp, destinationPerson, config) {
sp.ID = destinationPerson.Attributes["id"]
changeSet.Update = append(changeSet.Update, sp)
continue
Expand All @@ -189,8 +202,8 @@ func GenerateChangeSet(sourcePeople, destinationPeople []Person, attributeMap []
// - it gets the list of people from the destination
// - it generates the lists of people to change, update and delete
// - if dryRun is true, it prints those lists, but otherwise makes the associated changes
func SyncPeople(source Source, destination Destination, attributeMap []AttributeMap, dryRun bool) ChangeResults {
desiredAttrs := GetDesiredAttributes(attributeMap)
func SyncPeople(source Source, destination Destination, config AppConfig) ChangeResults {
desiredAttrs := GetDesiredAttributes(config.AttributeMap)
sourcePeople, err := source.ListUsers(desiredAttrs)
if err != nil {
return ChangeResults{
Expand All @@ -200,7 +213,7 @@ func SyncPeople(source Source, destination Destination, attributeMap []Attribute
log.Printf(" Found %v people in source", len(sourcePeople))

// remap source people to destination attributes for comparison
sourcePeople, err = RemapToDestinationAttributes(sourcePeople, attributeMap)
sourcePeople, err = RemapToDestinationAttributes(sourcePeople, config.AttributeMap)
if err != nil {
return ChangeResults{
Errors: []string{err.Error()},
Expand All @@ -215,10 +228,10 @@ func SyncPeople(source Source, destination Destination, attributeMap []Attribute
}
log.Printf(" Found %v people in destination", len(destinationPeople))

changeSet := GenerateChangeSet(sourcePeople, destinationPeople, attributeMap, destination.GetIDField())
changeSet := GenerateChangeSet(sourcePeople, destinationPeople, config, destination.GetIDField())

// If in DryRun mode only print out ChangeSet plans and return mocked change results based on plans
if dryRun {
if config.Runtime.DryRunMode {
printChangeSet(changeSet)
return ChangeResults{
Created: uint64(len(changeSet.Create)),
Expand Down
41 changes: 23 additions & 18 deletions domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,24 @@ func TestGenerateChangeSet(t *testing.T) {
},
}

attrMaps := []AttributeMap{
{
Source: "name",
Destination: "name",
CaseSensitive: true,
},
{
Source: "school",
Destination: "school",
CaseSensitive: false,
config := AppConfig{
AttributeMap: []AttributeMap{
{
Source: "name",
Destination: "name",
CaseSensitive: true,
},
{
Source: "school",
Destination: "school",
CaseSensitive: false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GenerateChangeSet(tt.args.sourcePeople, tt.args.destinationPeople, attrMaps, ""); !reflect.DeepEqual(got, tt.want) {
got := GenerateChangeSet(tt.args.sourcePeople, tt.args.destinationPeople, config, "")
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GenerateChangeSet() = %v, want %v", got, tt.want)
}
})
Expand Down Expand Up @@ -197,16 +200,18 @@ func TestIDSetForUpdate(t *testing.T) {
},
}

attributeMap := []AttributeMap{
{
Source: "email",
Destination: "email",
Required: true,
CaseSensitive: false,
config := AppConfig{
AttributeMap: []AttributeMap{
{
Source: "email",
Destination: "email",
Required: true,
CaseSensitive: false,
},
},
}

changeSet := GenerateChangeSet(sourcePeople, destinationPeople, attributeMap, "id")
changeSet := GenerateChangeSet(sourcePeople, destinationPeople, config, "id")
if len(changeSet.Create) != 1 {
t.Error("Change set should include one person to be created.")
}
Expand Down
4 changes: 2 additions & 2 deletions lambda-example/config.example.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Runtime": {
"FailIfSinglePersonMissingCompareValue": false,
"DryRunMode": false
"DryRunMode": false,
"Verbosity": 1
},
"Source": {
"Type": "RestAPI",
Expand Down
2 changes: 1 addition & 1 deletion lambda-example/personnelsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func handler(lambdaConfig LambdaConfig) error {
}

// Perform sync and get results
changeResults := personnel_sync.SyncPeople(source, destination, appConfig.AttributeMap, appConfig.Runtime.DryRunMode)
changeResults := personnel_sync.SyncPeople(source, destination, appConfig)

log.Printf("Sync results: %v users added, %v users updated, %v users removed, %v errors\n",
changeResults.Created, changeResults.Updated, changeResults.Deleted, len(changeResults.Errors))
Expand Down
7 changes: 7 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ type DestinationConfig struct {
ExtraJSON json.RawMessage
}

const (
VerbosityLow = 0
VerbosityMedium = 5
VerbosityHigh = 10
)

type RuntimeConfig struct {
DryRunMode bool
Verbosity int
}

type AppConfig struct {
Expand Down
6 changes: 2 additions & 4 deletions webhelpdesk/webhelpdesk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

"github.com/silinternational/personnel-sync/restapi"

"github.com/silinternational/personnel-sync"
personnel_sync "github.com/silinternational/personnel-sync"
)

func TestWebHelpDesk_ListUsers(t *testing.T) {
Expand Down Expand Up @@ -279,9 +279,7 @@ func TestCreateChangeSet(t *testing.T) {
sourcePeople, _ := source.ListUsers([]string{"email"})
log.Printf("found %v people in source", len(sourcePeople))

attributeMaps := testConfig.AttributeMap

changeSet := personnel_sync.GenerateChangeSet(sourcePeople, users, attributeMaps, "id")
changeSet := personnel_sync.GenerateChangeSet(sourcePeople, users, testConfig, "id")

log.Printf("ChangeSet ready %v to be created, %v to be deleted", len(changeSet.Create), len(changeSet.Delete))
}
Expand Down

0 comments on commit 8b81a64

Please sign in to comment.