github.com/esnet/gdg@v0.6.1-0.20240412190737-6b6eba9c14d8/test/common_test.go (about) 1 package test 2 3 import ( 4 "context" 5 "fmt" 6 "github.com/esnet/gdg/internal/config" 7 "github.com/esnet/gdg/internal/service" 8 "github.com/google/uuid" 9 "github.com/testcontainers/testcontainers-go" 10 "github.com/testcontainers/testcontainers-go/wait" 11 "golang.org/x/exp/maps" 12 "gopkg.in/yaml.v3" 13 "log" 14 "log/slog" 15 "os" 16 "slices" 17 "sync" 18 "time" 19 20 "strings" 21 "testing" 22 23 "github.com/spf13/viper" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 var minioContainer testcontainers.Container 28 var grafnaContainer testcontainers.Container 29 30 type Containers struct { 31 Cancel context.CancelFunc 32 Container testcontainers.Container 33 } 34 35 func setupMinioContainer(wg *sync.WaitGroup, channels chan Containers) { 36 // pulls an image, creates a container based on it and runs it 37 defer wg.Done() 38 39 ctx := context.Background() 40 req := testcontainers.ContainerRequest{ 41 Image: "bitnami/minio:latest", 42 ExposedPorts: []string{"9000/tcp"}, 43 Env: map[string]string{"MINIO_ROOT_USER": "test", "MINIO_ROOT_PASSWORD": "secretsss"}, 44 WaitingFor: wait.ForListeningPort("9000/tcp"), 45 } 46 minioC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ 47 ContainerRequest: req, 48 Started: true, 49 }) 50 if err != nil { 51 panic(err) 52 } 53 54 slog.Info("Minio container is up and running") 55 cancel := func() { 56 if err := minioC.Terminate(ctx); err != nil { 57 panic(err) 58 } else { 59 slog.Info("Minio container has been terminated") 60 } 61 } 62 result := Containers{ 63 Cancel: cancel, 64 Container: minioC, 65 } 66 channels <- result 67 68 } 69 70 func setupGrafanaContainer(wg *sync.WaitGroup, channels chan Containers) { 71 // pulls an image, creates a container based on it and runs it 72 defer wg.Done() 73 ctx := context.Background() 74 req := testcontainers.ContainerRequest{ 75 Image: "grafana/grafana:10.0.0-ubuntu", 76 ExposedPorts: []string{"3000/tcp"}, 77 Env: map[string]string{ 78 "GF_INSTALL_PLUGINS": "grafana-googlesheets-datasource", 79 "GF_AUTH_ANONYMOUS_ENABLED": "true", 80 }, 81 WaitingFor: wait.ForListeningPort("3000/tcp"), 82 } 83 grafanaC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ 84 ContainerRequest: req, 85 Started: true, 86 }) 87 if err != nil { 88 panic(err) 89 } 90 cancel := func() { 91 if err := grafanaC.Terminate(ctx); err != nil { 92 panic(err) 93 } else { 94 slog.Info("Grafana Container has been terminated") 95 } 96 } 97 result := Containers{ 98 Cancel: cancel, 99 Container: grafanaC, 100 } 101 channels <- result 102 103 } 104 105 func TestMain(m *testing.M) { 106 channels := make(chan Containers, 2) 107 var wg = new(sync.WaitGroup) 108 wg.Add(2) 109 slog.Info("Starting at", "time", time.Now().String()) 110 go setupMinioContainer(wg, channels) 111 go setupGrafanaContainer(wg, channels) 112 wg.Wait() 113 close(channels) 114 slog.Info("Ending at", "end", time.Now().String()) 115 116 for entry := range channels { 117 defer entry.Cancel() 118 str, err := entry.Container.Ports(context.Background()) 119 if err != nil { 120 slog.Error("unable to obtain bound ports for container") 121 continue 122 } 123 keys := maps.Keys(str) 124 if slices.Contains(keys, "9000/tcp") { 125 minioContainer = entry.Container 126 } 127 if slices.Contains(keys, "3000/tcp") { 128 grafnaContainer = entry.Container 129 130 } 131 132 } 133 exitVal := m.Run() 134 135 os.Exit(exitVal) 136 } 137 138 func initTest(t *testing.T, cfgName *string) (service.GrafanaService, *viper.Viper, func() error) { 139 apiClient, v := createSimpleClient(t, cfgName) 140 noOp := func() error { return nil } 141 142 if os.Getenv("TEST_TOKEN_CONFIG") != "1" { 143 return apiClient, v, noOp 144 } 145 146 testData, _ := os.ReadFile(v.ConfigFileUsed()) 147 data := map[string]interface{}{} 148 err := yaml.Unmarshal(testData, &data) 149 assert.Nil(t, err) 150 151 apiClient.DeleteAllTokens() //Remove any old data 152 tokenName, _ := uuid.NewUUID() 153 newKey, err := apiClient.CreateAPIKey(tokenName.String(), "admin", 0) 154 assert.Nil(t, err) 155 156 wrapper := map[string]*config.GrafanaConfig{} 157 _ = wrapper 158 159 level1 := data["contexts"].(map[string]interface{}) 160 level2 := level1["testing"].(map[string]interface{}) 161 level2["token"] = newKey.Key 162 level2["user_name"] = "" 163 level2["password"] = "" 164 165 updatedCfg, err := yaml.Marshal(data) 166 assert.Nil(t, err) 167 tokenCfg, err := os.CreateTemp("config", "token*.yml") 168 assert.Nil(t, err, "Unable to create token configuration file") 169 newCfg := tokenCfg.Name() 170 err = os.WriteFile(newCfg, updatedCfg, 0644) 171 assert.Nil(t, err) 172 173 cleanUp := func() error { 174 return os.Remove(newCfg) 175 } 176 177 apiClient, v = createSimpleClient(t, &newCfg) 178 return apiClient, v, cleanUp 179 180 } 181 182 func createSimpleClient(t *testing.T, cfgName *string) (service.GrafanaService, *viper.Viper) { 183 if cfgName == nil { 184 cfgName = new(string) 185 *cfgName = "testing.yml" 186 } 187 188 actualPort, err := grafnaContainer.Endpoint(context.Background(), "") 189 err = os.Setenv("GDG_CONTEXTS__TESTING__URL", fmt.Sprintf("http://%s", actualPort)) 190 assert.Nil(t, err) 191 192 config.InitGdgConfig(*cfgName, "'") 193 conf := config.Config().GetViperConfig(config.ViperGdgConfig) 194 assert.NotNil(t, conf) 195 //Hack for Local testing 196 contextName := conf.GetString("context_name") 197 conf.Set(fmt.Sprintf("context.%s.url", contextName), fmt.Sprintf("http://localhost:%s", actualPort)) 198 assert.Equal(t, contextName, "testing") 199 client := service.NewApiService("dummy") 200 path, _ := os.Getwd() 201 if strings.Contains(path, "test") { 202 err := os.Chdir("..") 203 if err != nil { 204 slog.Warn("unable to set directory to parent") 205 } 206 } 207 return client, conf 208 } 209 210 func SetupCloudFunction(params []string) (context.Context, service.GrafanaService) { 211 _ = os.Setenv(service.InitBucket, "true") 212 bucketName := params[1] 213 214 actualPort, err := minioContainer.Endpoint(context.Background(), "") 215 var m = map[string]string{ 216 service.InitBucket: "true", 217 service.CloudType: params[0], 218 service.Prefix: "dummy", 219 service.AccessId: "test", 220 service.SecretKey: "secretsss", 221 service.BucketName: bucketName, 222 service.Kind: "cloud", 223 service.Custom: "true", 224 service.Endpoint: fmt.Sprintf("http://%s", actualPort), 225 service.SSLEnabled: "false", 226 } 227 228 cfgObj := config.Config().GetGDGConfig() 229 defaultCfg := config.Config().GetDefaultGrafanaConfig() 230 defaultCfg.Storage = "test" 231 cfgObj.StorageEngine["test"] = m 232 apiClient := service.NewApiService("dummy") 233 234 ctx := context.Background() 235 ctx = context.WithValue(ctx, service.StorageContext, m) 236 configMap := map[string]string{} 237 for key, value := range m { 238 configMap[key] = fmt.Sprintf("%v", value) 239 } 240 241 s, err := service.NewCloudStorage(ctx) 242 if err != nil { 243 log.Fatalf("Could not instantiate cloud storage for type: %s", params[0]) 244 } 245 dash := apiClient.(*service.DashNGoImpl) 246 dash.SetStorage(s) 247 248 return ctx, apiClient 249 }