Skip to content

Commit

Permalink
updating fields for opslevel-go v2024, test needs fixing (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbloss authored Jan 12, 2024
1 parent 9471f82 commit 2c77a48
Show file tree
Hide file tree
Showing 15 changed files with 114 additions and 83 deletions.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CGO_ENABLED=1
CGO_CFLAGS='-I/opt/homebrew/include'
CGO_LDFLAGS='-L/opt/homebrew/lib'
1 change: 1 addition & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
# https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#cannot-connect-to-the-docker-daemon-at-unixvarrundockersock-is-the-docker-daemon-running
run: |
brew install docker
brew install jq
colima start
echo DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock" >> $GITHUB_ENV
- name: Login to Public ECR
Expand Down
19 changes: 14 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,17 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
- name: Run Tests
run: |-
cd src/
go test -race -coverprofile=coverage.txt -covermode=atomic -v ./...
go-version-file: src/go.mod
- name: Install Task
uses: arduino/setup-task@v1
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run quality checks and test code
run: task ci
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./src/coverage.txt
fail_ci_if_error: false
verbose: true
12 changes: 12 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

version: '3'

dotenv: ['.env']

env:
OPSLEVEL_GO_PKG: "github.com/opslevel/opslevel-go/v2023"
SRC_DIR: "{{.TASKFILE_DIR}}/src"
Expand All @@ -12,6 +14,7 @@ tasks:
cmds:
- task: workspace
- task: has-latest-opslevel-go
- which jq > /dev/null
- task: install-gofumpt
- task: install-golangci-lint
- task: lint
Expand Down Expand Up @@ -39,6 +42,7 @@ tasks:
cmds:
- cmd: echo "Installing development tools..."
silent: true
- task: brew-install-jq
- task: install-changie
- task: install-gofumpt
- task: install-golangci-lint
Expand Down Expand Up @@ -94,6 +98,14 @@ tasks:
# internal (not directly called) tasks

brew-install-jq:
internal: true
platforms: [darwin]
cmds: ["brew install jq"]
preconditions:
- sh: 'which brew'
msg: '"brew" needed to install "jq"- see https://brew.sh'

go-install-tool:
desc: go install '{{.GO_TOOL}}' and set GOBIN if not set
internal: true
Expand Down
2 changes: 2 additions & 0 deletions src/.goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ builds:
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
- -trimpath
ldflags:
- "-s -w"
goos:
- darwin
goarch:
Expand Down
6 changes: 4 additions & 2 deletions src/cmd/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@ func init() {
collectCmd.Flags().StringP("integration-url", "i", "", "OpsLevel integration url (OPSLEVEL_INTEGRATION_URL)")
collectCmd.Flags().IntVar(&collectResyncInterval, "resync", 24, "The amount (in hours) before a full resync of the kubernetes cluster happens with OpsLevel. [default: 24]")

viper.BindEnv("integration-url", "OPSLEVEL_INTEGRATION_URL")
err := viper.BindEnv("integration-url", "OPSLEVEL_INTEGRATION_URL")
cobra.CheckErr(err)
}

func PushPayloads(integrationUrl string, queue <-chan string) {
go func() {
restClient := createRestClient()
for {
for payload := range queue {
restClient.R().SetBody(payload).Post(integrationUrl)
_, err := restClient.R().SetBody(payload).Post(integrationUrl)
cobra.CheckErr(err)
}
}
}()
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ func init() {
configCmd.AddCommand(configSchemaCmd, configViewCmd, configSampleCmd)

configSampleCmd.Flags().Bool("simple", false, "Adjust the sample config to be less complex")
viper.BindPFlags(configSampleCmd.Flags())
err := viper.BindPFlags(configSampleCmd.Flags())
cobra.CheckErr(err)
}

func readConfig() []byte {
Expand Down
19 changes: 10 additions & 9 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ func init() {
rootCmd.PersistentFlags().StringP("output", "o", "text", "Output format. One of: json|text")
rootCmd.PersistentFlags().Bool("disable-service-create", false, "Turns off automatic service creation (service data will still be reconciled). Overrides environment variable 'OPSLEVEL_DISABLE_SERVICE_CREATE'.")

viper.BindPFlags(rootCmd.PersistentFlags())
viper.BindEnv("log-format", "OPSLEVEL_LOG_FORMAT", "OL_LOG_FORMAT", "OL_LOGFORMAT")
viper.BindEnv("log-level", "OPSLEVEL_LOG_LEVEL", "OL_LOG_LEVEL", "OL_LOGLEVEL")
viper.BindEnv("api-url", "OPSLEVEL_API_URL", "OL_API_URL", "OL_APIURL", "OPSLEVEL_APP_URL", "OL_APP_URL")
viper.BindEnv("api-token", "OPSLEVEL_API_TOKEN", "OL_API_TOKEN", "OL_APITOKEN")
viper.BindEnv("api-timeout", "OPSLEVEL_API_TIMEOUT")
viper.BindEnv("workers", "OPSLEVEL_WORKERS", "OL_WORKERS")
viper.BindEnv("disable-service-create", "OPSLEVEL_DISABLE_SERVICE_CREATE", "OL_DISABLE_SERVICE_CREATE")
cobra.CheckErr(viper.BindPFlags(rootCmd.PersistentFlags()))
cobra.CheckErr(viper.BindEnv("log-format", "OPSLEVEL_LOG_FORMAT", "OL_LOG_FORMAT", "OL_LOGFORMAT"))
cobra.CheckErr(viper.BindEnv("log-level", "OPSLEVEL_LOG_LEVEL", "OL_LOG_LEVEL", "OL_LOGLEVEL"))
cobra.CheckErr(viper.BindEnv("api-url", "OPSLEVEL_API_URL", "OL_API_URL", "OL_APIURL", "OPSLEVEL_APP_URL", "OL_APP_URL"))
cobra.CheckErr(viper.BindEnv("api-token", "OPSLEVEL_API_TOKEN", "OL_API_TOKEN", "OL_APITOKEN"))
cobra.CheckErr(viper.BindEnv("api-timeout", "OPSLEVEL_API_TIMEOUT"))
cobra.CheckErr(viper.BindEnv("workers", "OPSLEVEL_WORKERS", "OL_WORKERS"))
cobra.CheckErr(viper.BindEnv("disable-service-create", "OPSLEVEL_DISABLE_SERVICE_CREATE", "OL_DISABLE_SERVICE_CREATE"))
cobra.OnInitialize(func() {
setupEnv()
setupLogging()
Expand Down Expand Up @@ -117,7 +117,8 @@ func IsTextOutput() bool {
}

func setupConcurrency() {
maxprocs.Set(maxprocs.Logger(log.Debug().Msgf))
_, err := maxprocs.Set(maxprocs.Logger(log.Debug().Msgf))
cobra.CheckErr(err)

concurrency = viper.GetInt("workers")
if concurrency <= 0 {
Expand Down
64 changes: 32 additions & 32 deletions src/common/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,28 +73,28 @@ func (r *ServiceReconciler) ContainsAllTags(tagAssigns []opslevel.TagInput, serv
}

func (r *ServiceReconciler) ServiceNeedsUpdate(input opslevel.ServiceUpdateInput, service *opslevel.Service) bool {
if input.Name != "" && input.Name != service.Name {
if input.Name != nil && *input.Name != service.Name {
return true
}
if input.Product != "" && input.Product != service.Product {
if input.Product != nil && *input.Product != service.Product {
return true
}
if input.Description != "" && input.Description != service.Description {
if input.Description != nil && *input.Description != service.Description {
return true
}
if input.Language != "" && input.Language != service.Language {
if input.Language != nil && *input.Language != service.Language {
return true
}
if input.Framework != "" && input.Framework != service.Framework {
if input.Framework != nil && *input.Framework != service.Framework {
return true
}
if input.Tier != "" && input.Tier != service.Tier.Alias {
if input.TierAlias != nil && *input.TierAlias != service.Tier.Alias {
return true
}
if input.Lifecycle != "" && input.Lifecycle != service.Lifecycle.Alias {
if input.LifecycleAlias != nil && *input.LifecycleAlias != service.Lifecycle.Alias {
return true
}
if input.Owner != nil && *input.Owner.Alias != service.Owner.Alias {
if input.OwnerInput != nil && *input.OwnerInput.Alias != service.Owner.Alias {
return true
}
return false
Expand Down Expand Up @@ -162,26 +162,26 @@ func (r *ServiceReconciler) handleService(registration opslevel_jq_parser.Servic
func (r *ServiceReconciler) createService(registration opslevel_jq_parser.ServiceRegistration) (*opslevel.Service, error) {
serviceCreateInput := opslevel.ServiceCreateInput{
Name: registration.Name,
Product: registration.Product,
Description: registration.Description,
Language: registration.Language,
Framework: registration.Framework,
Product: opslevel.RefOf[string](registration.Product),
Description: opslevel.RefOf[string](registration.Description),
Language: opslevel.RefOf[string](registration.Language),
Framework: opslevel.RefOf[string](registration.Framework),
}
if registration.System != "" {
serviceCreateInput.Parent = opslevel.NewIdentifier(registration.System)
}
if v, ok := opslevel.Cache.TryGetTier(registration.Tier); ok {
serviceCreateInput.Tier = string(v.Alias)
serviceCreateInput.TierAlias = opslevel.RefOf(v.Alias)
} else if registration.Tier != "" {
log.Warn().Msgf("[%s] Unable to find 'Tier' with alias '%s'", registration.Name, registration.Tier)
}
if v, ok := opslevel.Cache.TryGetLifecycle(registration.Lifecycle); ok {
serviceCreateInput.Lifecycle = string(v.Alias)
serviceCreateInput.LifecycleAlias = opslevel.RefOf(v.Alias)
} else if registration.Lifecycle != "" {
log.Warn().Msgf("[%s] Unable to find 'Lifecycle' with alias '%s'", registration.Name, registration.Lifecycle)
}
if v, ok := opslevel.Cache.TryGetTeam(registration.Owner); ok {
serviceCreateInput.Owner = opslevel.NewIdentifier(v.Alias)
serviceCreateInput.OwnerInput = opslevel.NewIdentifier(v.Alias)
} else if registration.Owner != "" {
log.Warn().Msgf("[%s] Unable to find 'Team' with alias '%s'", registration.Name, registration.Owner)
}
Expand All @@ -196,27 +196,27 @@ func (r *ServiceReconciler) createService(registration opslevel_jq_parser.Servic

func (r *ServiceReconciler) updateService(service *opslevel.Service, registration opslevel_jq_parser.ServiceRegistration) {
updateServiceInput := opslevel.ServiceUpdateInput{
Id: service.Id,
Product: registration.Product,
Description: registration.Description,
Language: registration.Language,
Framework: registration.Framework,
Id: &service.Id,
Product: opslevel.RefOf[string](registration.Product),
Description: opslevel.RefOf[string](registration.Description),
Language: opslevel.RefOf[string](registration.Language),
Framework: opslevel.RefOf[string](registration.Framework),
}
if registration.System != "" {
updateServiceInput.Parent = opslevel.NewIdentifier(registration.System)
}
if v, ok := opslevel.Cache.TryGetTier(registration.Tier); ok {
updateServiceInput.Tier = string(v.Alias)
updateServiceInput.TierAlias = opslevel.RefOf(v.Alias)
} else if registration.Tier != "" {
log.Warn().Msgf("[%s] Unable to find 'Tier' with alias '%s'", service.Name, registration.Tier)
}
if v, ok := opslevel.Cache.TryGetLifecycle(registration.Lifecycle); ok {
updateServiceInput.Lifecycle = string(v.Alias)
updateServiceInput.LifecycleAlias = opslevel.RefOf(v.Alias)
} else if registration.Lifecycle != "" {
log.Warn().Msgf("[%s] Unable to find 'Lifecycle' with alias '%s'", service.Name, registration.Lifecycle)
}
if v, ok := opslevel.Cache.TryGetTeam(registration.Owner); ok {
updateServiceInput.Owner = opslevel.NewIdentifier(v.Alias)
updateServiceInput.OwnerInput = opslevel.NewIdentifier(v.Alias)
} else if registration.Owner != "" {
log.Warn().Msgf("[%s] Unable to find 'Team' with alias '%s'", service.Name, registration.Owner)
}
Expand Down Expand Up @@ -279,7 +279,7 @@ func (r *ServiceReconciler) handleCreateTags(service *opslevel.Service, registra
continue
}
input := opslevel.TagCreateInput{
Id: service.Id,
Id: &service.Id,
Key: tag.Key,
Value: tag.Value,
}
Expand All @@ -294,31 +294,31 @@ func (r *ServiceReconciler) handleCreateTags(service *opslevel.Service, registra

func (r *ServiceReconciler) handleTools(service *opslevel.Service, registration opslevel_jq_parser.ServiceRegistration) {
for _, tool := range registration.Tools {
if service.HasTool(tool.Category, tool.DisplayName, tool.Environment) {
log.Debug().Msgf("[%s] Tool '{Category: %s, Environment: %s, Name: %s}' already exists on service ... skipping", service.Name, tool.Category, tool.Environment, tool.DisplayName)
if service.HasTool(tool.Category, tool.DisplayName, *tool.Environment) {
log.Debug().Msgf("[%s] Tool '{Category: %s, Environment: %s, Name: %s}' already exists on service ... skipping", service.Name, tool.Category, *tool.Environment, tool.DisplayName)
continue
}
tool.ServiceId = service.Id
tool.ServiceId = &service.Id
err := r.client.CreateTool(tool)
if err != nil {
log.Error().Msgf("[%s] Failed assigning tool '{Category: %s, Environment: %s, Name: %s}'\n\tREASON: %v", service.Name, tool.Category, tool.Environment, tool.DisplayName, err.Error())
log.Error().Msgf("[%s] Failed assigning tool '{Category: %s, Environment: %s, Name: %s}'\n\tREASON: %v", service.Name, tool.Category, *tool.Environment, tool.DisplayName, err.Error())
} else {
log.Info().Msgf("[%s] Ensured tool '{Category: %s, Environment: %s, Name: %s}'", service.Name, tool.Category, tool.Environment, tool.DisplayName)
log.Info().Msgf("[%s] Ensured tool '{Category: %s, Environment: %s, Name: %s}'", service.Name, tool.Category, *tool.Environment, tool.DisplayName)
}
}
}

func (r *ServiceReconciler) handleRepositories(service *opslevel.Service, registration opslevel_jq_parser.ServiceRegistration) {
for _, repositoryCreate := range registration.Repositories {
repositoryAsString := fmt.Sprintf("{Alias: %s, Directory: %s, Name: %s}", *repositoryCreate.Repository.Alias, repositoryCreate.BaseDirectory, repositoryCreate.DisplayName)
repositoryAsString := fmt.Sprintf("{Alias: %s, Directory: %s, Name: %s}", *repositoryCreate.Repository.Alias, *repositoryCreate.BaseDirectory, *repositoryCreate.DisplayName)
foundRepository, foundRepositoryErr := r.client.GetRepositoryWithAlias(*repositoryCreate.Repository.Alias)
if foundRepositoryErr != nil {
log.Warn().Msgf("[%s] Repository with alias: '%s' not found so it cannot be attached to service ... skipping", service.Name, repositoryAsString)
continue
}
serviceRepository := foundRepository.GetService(service.Id, repositoryCreate.BaseDirectory)
serviceRepository := foundRepository.GetService(service.Id, *repositoryCreate.BaseDirectory)
if serviceRepository != nil {
if repositoryCreate.DisplayName != "" && serviceRepository.DisplayName != repositoryCreate.DisplayName {
if repositoryCreate.DisplayName != nil && serviceRepository.DisplayName != *repositoryCreate.DisplayName {
repositoryUpdate := opslevel.ServiceRepositoryUpdateInput{
Id: serviceRepository.Id,
DisplayName: repositoryCreate.DisplayName,
Expand Down
28 changes: 14 additions & 14 deletions src/common/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ func TestReconcilerReconcile(t *testing.T) {
Aliases: []string{"test1", "test2", "test3"},
TagAssigns: []opslevel.TagInput{{Key: "foo", Value: "bar"}, {Key: "hello", Value: "world"}},
TagCreates: []opslevel.TagInput{{Key: "env", Value: "test"}},
Tools: []opslevel.ToolCreateInput{{Category: opslevel.ToolCategoryCode, DisplayName: "test", Url: "https://example.com", Environment: "test"}},
Repositories: []opslevel.ServiceRepositoryCreateInput{{Service: *opslevel.NewIdentifier(""), Repository: *opslevel.NewIdentifier(""), DisplayName: "", BaseDirectory: ""}},
Tools: []opslevel.ToolCreateInput{{Category: opslevel.ToolCategoryCode, DisplayName: "test", Url: "https://example.com", Environment: opslevel.RefOf("test")}},
Repositories: []opslevel.ServiceRepositoryCreateInput{{Service: *opslevel.NewIdentifier(""), Repository: *opslevel.NewIdentifier(""), DisplayName: opslevel.RefOf(""), BaseDirectory: opslevel.RefOf("")}},
}
cases := map[string]TestCase{
"Missing Aliases Should Error": {
Expand Down Expand Up @@ -350,48 +350,48 @@ func Test_Reconciler_ServiceNeedsUpdate(t *testing.T) {
cases := map[string]TestCase{
"Is True When Input Differs 1": {
input: opslevel.ServiceUpdateInput{
Name: "Test1",
Name: opslevel.RefOf("Test1"),
},
service: service1,
result: true,
},
"Is True When Input Differs 2": {
input: opslevel.ServiceUpdateInput{
Name: "Test",
Language: "Python",
Tier: "tier_2",
Name: opslevel.RefOf("Test"),
Language: opslevel.RefOf("Python"),
TierAlias: opslevel.RefOf("tier_2"),
},
service: service1,
result: true,
},
"Is True When Input Differs 3": {
input: opslevel.ServiceUpdateInput{
Name: "Test",
Language: "Python",
Owner: opslevel.NewIdentifier("platform"),
Name: opslevel.RefOf("Test"),
Language: opslevel.RefOf("Python"),
OwnerInput: opslevel.NewIdentifier("platform"),
},
service: service1,
result: true,
},
"Is False When Input Matches 1": {
input: opslevel.ServiceUpdateInput{
Id: "XXX",
Id: opslevel.NewID("XXX"),
},
service: service2,
result: false,
},
"Is False When Input Matches 2": {
input: opslevel.ServiceUpdateInput{
Name: "Test",
Name: opslevel.RefOf("Test"),
},
service: service2,
result: false,
},
"Is False When Input Matches 3": {
input: opslevel.ServiceUpdateInput{
Name: "Test",
Language: "Python",
Tier: "tier_1",
Name: opslevel.RefOf("Test"),
Language: opslevel.RefOf("Python"),
TierAlias: opslevel.RefOf("tier_1"),
},
service: service2,
result: false,
Expand Down
Loading

0 comments on commit 2c77a48

Please sign in to comment.