-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[infra-proxy-service] Add integration testing for infra-proxy-service #4690
Changes from all commits
116f206
3558cad
6b9ad42
8ed1e94
c033146
b71d313
8775e09
d58c8a7
73a6e21
f116bb4
d003757
e17ba8a
1565ae8
209363b
8efbd48
0d3c4c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
"os" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/spf13/viper" | ||
|
||
secrets "github.com/chef/automate/api/external/secrets" | ||
"github.com/chef/automate/api/interservice/authz" | ||
"github.com/chef/automate/components/infra-proxy-service/service" | ||
"github.com/chef/automate/components/infra-proxy-service/storage/postgres/migration" | ||
"github.com/chef/automate/lib/grpc/secureconn" | ||
"github.com/chef/automate/lib/logger" | ||
platform_config "github.com/chef/automate/lib/platform/config" | ||
"github.com/chef/automate/lib/tls/certs" | ||
) | ||
|
||
// Service config options | ||
type Service struct { | ||
GRPC string `mapstructure:"grpc"` | ||
LogFormat string `mapstructure:"log-format"` | ||
LogLevel string `mapstructure:"log-level"` | ||
certs.TLSConfig `mapstructure:"tls"` | ||
PGURL string `mapstructure:"pg_url"` | ||
Database string `mapstructure:"database"` | ||
MigrationsPath string `mapstructure:"migrations-path"` | ||
AuthzAddress string `mapstructure:"authz-address"` | ||
SecretsAddress string `mapstructure:"secrets-address"` | ||
} | ||
|
||
// ConfigFromViper returns a Service instance from the current viper config | ||
func ConfigFromViper(configFile string) (*service.Service, error) { | ||
// Set the file name of the configurations file | ||
viper.SetConfigName("config") | ||
// Set the configuration file type | ||
viper.SetConfigType("yaml") | ||
// Set the path to look for the configurations file | ||
viper.AddConfigPath("../dev") | ||
|
||
if err := viper.ReadInConfig(); err != nil { | ||
fail(errors.Wrap(err, `Could not read config file. Please pass a config file as the only argument to this command.`)) | ||
} | ||
|
||
cfg := Service{} | ||
if err := viper.Unmarshal(&cfg); err != nil { | ||
fail(errors.Wrap(err, "couldn't parse configuration file")) | ||
} | ||
|
||
pgURL, err := platform_config.PGURIFromEnvironment(cfg.Database) | ||
if err != nil { | ||
fail(errors.Wrap(err, "Failed to get pg uri")) | ||
} | ||
cfg.PGURL = pgURL | ||
|
||
l, err := logger.NewLogger(cfg.LogFormat, cfg.LogLevel) | ||
if err != nil { | ||
fail(errors.Wrap(err, "couldn't initialize logger")) | ||
} | ||
|
||
cfg.FixupRelativeTLSPaths(configFile) | ||
serviceCerts, err := cfg.ReadCerts() | ||
if err != nil { | ||
fail(errors.Wrap(err, "Could not read certs")) | ||
} | ||
connFactory := secureconn.NewFactory(*serviceCerts) | ||
|
||
mustBeADirectory(cfg.MigrationsPath) | ||
u, err := url.Parse(cfg.PGURL) | ||
if err != nil { | ||
fail(errors.Wrapf(err, "could not parse pg_url %s from config", cfg.PGURL)) | ||
} | ||
migrationConfig := migration.Config{ | ||
Path: cfg.MigrationsPath, | ||
PGURL: u, | ||
Logger: l, | ||
} | ||
|
||
if cfg.AuthzAddress == "" { | ||
fail(errors.New("missing required config authz_address")) | ||
} | ||
authzConn, err := connFactory.Dial("authz-service", cfg.AuthzAddress) | ||
if err != nil { | ||
fail(errors.Wrapf(err, "failed to dial authz-service at (%s)", cfg.AuthzAddress)) | ||
} | ||
authzClient := authz.NewAuthorizationServiceClient(authzConn) | ||
|
||
if cfg.SecretsAddress == "" { | ||
fail(errors.New("missing required config secrets_address")) | ||
} | ||
secretsConn, err := connFactory.Dial("secrets-service", cfg.SecretsAddress) | ||
if err != nil { | ||
fail(errors.Wrapf(err, "failed to dial secrets-service at (%s)", cfg.SecretsAddress)) | ||
} | ||
|
||
// gets secrets client | ||
secretsClient := secrets.NewSecretsServiceClient(secretsConn) | ||
|
||
service, err := service.Start(l, migrationConfig, connFactory, secretsClient, authzClient) | ||
if err != nil { | ||
fail(errors.Wrap(err, "could not initialize storage")) | ||
} | ||
|
||
return service, nil | ||
} | ||
|
||
// fail outputs the error and exits with a non-zero code | ||
func fail(err error) { | ||
// no error check: if this goes wrong, we're in trouble anyways | ||
fmt.Fprint(os.Stderr, err.Error()) // nolint: gas | ||
os.Exit(1) | ||
} | ||
|
||
func mustBeADirectory(path string) { | ||
stat, err := os.Stat(path) | ||
if err == nil && stat.IsDir() { | ||
return // everything's in its right place | ||
} else if err != nil { | ||
fail(errors.Wrapf(err, "open path %#v", path)) | ||
} | ||
fail(fmt.Errorf("path %#v is not a directory", path)) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,12 +4,12 @@ log-level: "info" | |
log-format: "text" | ||
|
||
tls: | ||
cert_path: ../../../dev/certs/infra-proxy-service.crt | ||
key_path: ../../../dev/certs/infra-proxy-service.key | ||
root_ca_path: ../../../dev/certs/Chef_Automate_FAKE_Dev.crt | ||
cert_path: /hab/svc/infra-proxy-service/config/service.crt | ||
key_path: /hab/svc/infra-proxy-service/config/service.key | ||
root_ca_path: /hab/svc/infra-proxy-service/config/root_ca.crt | ||
|
||
pg_url: "postgresql://[email protected]:5432/infra_proxy_test?sslmode=disable" | ||
database: infra_proxy_test | ||
migrations-path: storage/postgres/migration/sql/ | ||
database: chef_infra_proxy | ||
migrations-path: /src/components/infra-proxy-service/storage/postgres/migration/sql/ | ||
authz-address: "0.0.0.0:10130" | ||
secrets-address: "0.0.0.0:10131" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package integration_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/chef/automate/api/interservice/infra_proxy/request" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetClients(t *testing.T) { | ||
// rpc GetClients (request.Clients) returns (response.Clients) | ||
ctx := context.Background() | ||
req := &request.Clients{ | ||
ServerId: autoDeployedChefServerID, | ||
OrgId: autoDeployedChefOrganizationID, | ||
} | ||
res, err := infraProxy.GetClients(ctx, req) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, res) | ||
assert.Equal(t, 3, len(res.GetClients())) | ||
} | ||
|
||
func TestGetClient(t *testing.T) { | ||
// rpc GetClient (request.Client) returns (response.Client) | ||
ctx := context.Background() | ||
req := &request.Client{ | ||
ServerId: autoDeployedChefServerID, | ||
OrgId: autoDeployedChefOrganizationID, | ||
Name: "chef-load-1", | ||
} | ||
res, err := infraProxy.GetClient(ctx, req) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, res) | ||
assert.Equal(t, "chef-load-1", res.Name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package integration_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
) | ||
|
||
// Global variables | ||
var ( | ||
autoDeployedChefServerID = "local-dev" | ||
autoDeployedChefOrganizationID = "test-org" | ||
cFile = "/src/components/infra-proxy-service/dev/config" | ||
// This suite variable will be available for every single test as long as they | ||
// belong to the 'integration_test' package. | ||
suite = NewSuite() | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
// Global Setup hook: Here is where you can initialize anythings you need | ||
// for your tests to run, things like; Initialize ES indices, insert | ||
// nodes or runs, etc. | ||
suite.GlobalSetup() | ||
|
||
// Execute the test suite and record the exit code | ||
exitCode := m.Run() | ||
|
||
// Teardown hook: It says it all, this hook should clean documents | ||
// from ES so that the next test can run on a clean env. | ||
suite.GlobalTeardown() | ||
|
||
// call with result of m.Run() | ||
os.Exit(exitCode) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package integration_test | ||
|
||
import ( | ||
"github.com/chef/automate/components/infra-proxy-service/config" | ||
"github.com/chef/automate/components/infra-proxy-service/server" | ||
) | ||
|
||
// Global variables | ||
var ( | ||
// A global Infra Proxy Server instance to call any rpc function | ||
// | ||
// From any test you can directly call: | ||
// ``` | ||
// res, err := infraProxy.GetOrgs(ctx, &req) | ||
// ``` | ||
infraProxy *server.Server | ||
) | ||
|
||
type Suite struct{} | ||
|
||
// Just returns a new struct. You have to call GlobalSetup() to setup | ||
func NewSuite() *Suite { | ||
return new(Suite) | ||
} | ||
|
||
// GlobalSetup makes all connections. | ||
func (s *Suite) GlobalSetup() error { | ||
var err error | ||
// set global infraProxy | ||
infraProxy, err = newInfraProxyServer() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// GlobalTeardown is the place where you tear everything down after we have finished | ||
func (s *Suite) GlobalTeardown() {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please confirm if we need to close any open connections like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I can check in this method we have performed some data cleanup like Postgres data, elastic search indices, etc, not the service connections. will investigate more on this! |
||
|
||
// newInfraProxyServer initializes a InfraProxyServer with the default config | ||
func newInfraProxyServer() (*server.Server, error) { | ||
service, err := config.ConfigFromViper(cFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
gRPC := server.NewServer(service) | ||
|
||
return gRPC, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests assume that we have a predefined test data loaded to the server. This is fine at this point since we do not have the API to add the data. But this needs to be addressed later.