Skip to content

Commit

Permalink
feat: Download settings (#19)
Browse files Browse the repository at this point in the history
* refactor: Rename downloader to classic

* feat: Implement outline for settings 2.0 download

* feat: Implement ListSchemas

* feat: Implement ListSettings

* feat: Write downloaded settings

* feat: added unit test for settings::Download

* feat: Add option to skip settings download

* ci: Make mocks before vet

* ci: Set up go for static-code-analysis workflow

* ci: Integration tests target requires mocks

Co-authored-by: David Laubreiter <[email protected]>
  • Loading branch information
2 people authored and UnseenWizzard committed Feb 14, 2023
1 parent 3b10d37 commit a3e2497
Show file tree
Hide file tree
Showing 18 changed files with 386 additions and 23 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/pr-static-code-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.x
uses: actions/setup-go@v3
with:
go-version: '~1.19'
id: go

- uses: actions/checkout@v3

- name: 🕵️ Go vet
run: make vet

- name: golangci-lint
uses: reviewdog/action-golangci-lint@v2
with:
Expand Down
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ mocks: setup
@echo "Generating mocks"
@go generate ./...

vet:
vet: mocks
@echo "Vetting files"
@go vet ./...

Expand Down Expand Up @@ -79,19 +79,19 @@ test: setup mocks lint
@echo "Testing ${BINARY}..."
@gotestsum ${testopts} -- -tags=unit -v ./...

integration-test: setup
integration-test: mocks
@gotestsum ${testopts} --format standard-verbose -- -tags=integration -timeout=30m -v ./...

integration-test-v1:setup
integration-test-v1:mocks
@gotestsum ${testopts} --format standard-verbose -- -tags=integration_v1 -timeout=30m -v ./...

download-restore-test: setup
download-restore-test: mocks
@gotestsum ${testopts} --format standard-verbose -- -tags=download_restore -timeout=30m -v ./...

clean-environments:
@gotestsum ${testopts} --format standard-verbose -- -tags=cleanup -v ./...

nightly-test:setup
nightly-test:mocks
@gotestsum ${testopts} --format standard-verbose -- -tags=nightly -timeout=60m -v ./...

# Build and Test a single package supplied via pgk variable, without using test cache
Expand Down
15 changes: 12 additions & 3 deletions cmd/monaco/download/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import (
"fmt"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/api"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/download"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/download/downloader"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/download/classic"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/download/settings"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/manifest"
project "github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/project/v2"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/project/v2/topologysort"
Expand Down Expand Up @@ -172,6 +173,7 @@ type downloadOptions struct {
apis api.ApiMap
forceOverwriteManifest bool
clientFactory dynatraceClientFactory
skipSettings bool
}

func (c downloadOptions) getDynatraceClient() (rest.DynatraceClient, error) {
Expand Down Expand Up @@ -243,8 +245,15 @@ func downloadConfigs(context downloadOptions) (project.ConfigsPerType, error) {
return nil, fmt.Errorf("failed to create Dynatrace client: %w", err)
}

downloadedConfigs := downloader.DownloadAllConfigs(context.apis, client, context.projectName)
return downloadedConfigs, nil
configObjects := classic.DownloadAllConfigs(context.apis, client, context.projectName)

if !context.skipSettings {
settingsObjects := settings.Download(client)

maps.Copy(configObjects, settingsObjects)
}

return configObjects, nil
}

func sumConfigs(configs project.ConfigsPerType) int {
Expand Down
1 change: 1 addition & 0 deletions cmd/monaco/download/download_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ func getTestingDownloadOptions(server *httptest.Server, projectName string, apiM
outputFolder: "out",
projectName: projectName,
apis: apiMap,
skipSettings: true,
clientFactory: func(environmentUrl, token string) (rest.DynatraceClient, error) {
return rest.NewDynatraceClientForTesting(environmentUrl, token, server.Client())
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ The process looks like this:
```
*/
package downloader
package classic
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package downloader
package classic

import (
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/api"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* limitations under the License.
*/

package downloader
package classic

import (
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/api"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package downloader
package classic

var apiSanitizeFunctions = map[string]func(properties map[string]interface{}) map[string]interface{}{
"service-detection-full-web-service": removeOrderProperty,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package downloader
package classic

import (
"gotest.tools/assert"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package downloader
package classic

import (
"encoding/json"
Expand Down Expand Up @@ -154,7 +154,7 @@ func findConfigsToDownload(currentApi api.Api, client rest.DynatraceClient) ([]a
return client.List(currentApi)
}

func downloadConfigsOfApi(theApi api.Api, values []api.Value, client rest.DynatraceClient, projectId string) []config.Config {
func downloadConfigsOfApi(theApi api.Api, values []api.Value, client rest.DynatraceClient, projectName string) []config.Config {
configs := make([]config.Config, 0, len(values))
configsMutex := sync.Mutex{}

Expand All @@ -166,7 +166,7 @@ func downloadConfigsOfApi(theApi api.Api, values []api.Value, client rest.Dynatr
value := value

go func() {
conf, skipConfig := downloadConfig(theApi, value, client, projectId)
conf, skipConfig := downloadConfig(theApi, value, client, projectName)

if !skipConfig {
configsMutex.Lock()
Expand All @@ -183,8 +183,8 @@ func downloadConfigsOfApi(theApi api.Api, values []api.Value, client rest.Dynatr
return configs
}

func downloadConfig(theApi api.Api, value api.Value, client rest.DynatraceClient, projectId string) (conf config.Config, skipConfig bool) {
return downloadConfigForTesting(theApi, value, client, projectId, shouldConfigBePersisted)
func downloadConfig(theApi api.Api, value api.Value, client rest.DynatraceClient, projectName string) (conf config.Config, skipConfig bool) {
return downloadConfigForTesting(theApi, value, client, projectName, shouldConfigBePersisted)
}

type shouldConfigBePersistedFunc func(a api.Api, json map[string]interface{}) bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package downloader
package classic

import (
"errors"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package downloader
package classic

import (
"encoding/json"
Expand Down
91 changes: 91 additions & 0 deletions pkg/download/settings/settings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package settings

import (
config "github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/config/v2"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/config/v2/coordinate"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/config/v2/parameter"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/config/v2/parameter/value"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/config/v2/template"
v2 "github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/project/v2"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/rest"
"github.com/dynatrace-oss/dynatrace-monitoring-as-code/pkg/util/log"
)

func Download(client rest.SettingsClient) v2.ConfigsPerType {

log.Debug("Fetching schemas to download")
schemas, err := client.ListSchemas()
if err != nil {
log.Error("Failed to fetch all known schemas. Skipping settings download. Reason: %s", err)
return nil
}

results := make(v2.ConfigsPerType)

for _, schema := range schemas {
log.Debug("Downloading all settings for schema %s", schema)
objects, err := client.ListSettings(schema.SchemaId)
if err != nil {
log.Error("Failed to fetch all settings for schema %s", schema)
continue
}

configs := convertAllObjects(objects)
results[schema.SchemaId] = configs
}

return results
}

func convertAllObjects(objects []rest.DownloadSettingsObject) []config.Config {
result := make([]config.Config, 0, len(objects))

for _, o := range objects {
result = append(result, convertObject(o))
}

return result
}

func convertObject(o rest.DownloadSettingsObject) config.Config {

content := string(*o.Value)

templ := template.NewDownloadTemplate(o.ObjectId, o.ObjectId, content)

return config.Config{
Template: templ,
Coordinate: coordinate.Coordinate{
Project: "project",
Type: o.SchemaId,
ConfigId: o.ObjectId, // we need a unique id -> use the objectId as it is unique
},
Type: config.Type{
SchemaId: o.SchemaId,
SchemaVersion: o.SchemaVersion,
},
Parameters: map[string]parameter.Parameter{
config.NameParameter: &value.ValueParameter{Value: o.ObjectId},
config.ScopeParameter: &value.ValueParameter{Value: o.Scope},
},
References: nil,
Skip: false,
}

}
Loading

0 comments on commit a3e2497

Please sign in to comment.