diff --git a/Makefile b/Makefile index ce0734ef..d724190e 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,7 @@ test: @echo "" @echo "Running tests." # TODO: e2e tests are taking too long to be enabled by default. They need to be sped up. - @go test ./... -count=1 -coverprofile=coverage.out -skip 'TestInventoryAPIGRPC_*|Test_ACMKafkaConsumer' + @go test ./... -count=1 -coverprofile=coverage.out -skip 'TestInventoryAPIGRPC_*|TestInventoryAPIHTTP_*|Test_ACMKafkaConsumer' @echo "Overall test coverage:" @go tool cover -func=coverage.out | grep total: | awk '{print $$3}' @rm coverage.out diff --git a/go.mod b/go.mod index a38cf984..8f6def13 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22.5 require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240717164558-a6c49f84cc0f.2 - github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 + github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b github.com/bufbuild/protovalidate-go v0.6.5 github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2 v2.0.0-20240718090307-5f0cc73d49ff github.com/cloudevents/sdk-go/v2 v2.15.2 @@ -15,6 +15,7 @@ require ( github.com/google/uuid v1.6.0 github.com/google/wire v0.6.0 github.com/patrickmn/go-cache v2.1.0+incompatible + github.com/project-kessel/inventory-client-go v0.0.0-20240918112335-d9c72f85b234 github.com/project-kessel/relations-api v0.0.0-20240912181134-54bbd73bdde7 github.com/prometheus/client_golang v1.20.3 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index b959e6b7..0697b5ac 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 h1:bQeIwWWRI9bl93poTqpix4sYHi+gnXUPK7N6bMtXzBE= -github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403/go.mod h1:s3qC7V7XIbiNWERv7Lfljy/Lx25/V1Qlexb0WJuA8uQ= +github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b h1:wbh8IK+aMLTCey9sZasO7b6BWLAJnHHvb79fvWCXwxw= +github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b/go.mod h1:s3qC7V7XIbiNWERv7Lfljy/Lx25/V1Qlexb0WJuA8uQ= github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= github.com/aws/aws-sdk-go-v2/config v1.27.10 h1:PS+65jThT0T/snC5WjyfHHyUgG+eBoupSDV+f838cro= @@ -348,6 +348,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/project-kessel/inventory-client-go v0.0.0-20240918112335-d9c72f85b234 h1:Ms0bb3nq9slmvRIRhPxTocC/nVJtUrRDlEnmcXgP7as= +github.com/project-kessel/inventory-client-go v0.0.0-20240918112335-d9c72f85b234/go.mod h1:ghVJESku3BJcPp3A8RTuHIErM0RptidPKoi0xGTlgrk= github.com/project-kessel/relations-api v0.0.0-20240912181134-54bbd73bdde7 h1:8Jn9Tkz2zP5gMhzBWCRa49Od8VBqJCFBapaAY0fTVUU= github.com/project-kessel/relations-api v0.0.0-20240912181134-54bbd73bdde7/go.mod h1:KbgiAPnLEqlEbRda41lGTX7+ojnMlqg+B2DeqDCgjFo= github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= diff --git a/test/e2e-batch.yaml b/test/e2e-batch.yaml index 99342c6d..0dfa5816 100644 --- a/test/e2e-batch.yaml +++ b/test/e2e-batch.yaml @@ -9,8 +9,8 @@ spec: - name: inventory-e2e-tests image: localhost/inventory-e2e-tests:latest env: - - name: INV_GRPC_URL - value: "inventory.multicluster-global-hub.svc.cluster.local:9081" + - name: INV_HTTP_URL + value: "inventory.multicluster-global-hub.svc.cluster.local:8081" - name: KAFKA_BOOTSTRAP_SERVERS value: "kafka-kafka-bootstrap.multicluster-global-hub:9092" restartPolicy: Never diff --git a/test/e2e/inventory_test.go b/test/e2e/grpc/inventory_grpc_test.go similarity index 99% rename from test/e2e/inventory_test.go rename to test/e2e/grpc/inventory_grpc_test.go index 09325c08..4041f8f0 100644 --- a/test/e2e/inventory_test.go +++ b/test/e2e/grpc/inventory_grpc_test.go @@ -1,4 +1,4 @@ -package e2e +package grpc import ( "context" @@ -6,7 +6,6 @@ import ( "github.com/go-kratos/kratos/v2/log" v1 "github.com/project-kessel/inventory-api/api/kessel/inventory/v1" "github.com/project-kessel/inventory-api/api/kessel/inventory/v1beta1/resources" - "github.com/stretchr/testify/assert" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" diff --git a/test/e2e/inventory_http_test.go b/test/e2e/inventory_http_test.go new file mode 100644 index 00000000..68e60b4c --- /dev/null +++ b/test/e2e/inventory_http_test.go @@ -0,0 +1,154 @@ +package e2e + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "github.com/go-kratos/kratos/v2/log" + "github.com/project-kessel/inventory-api/api/kessel/inventory/v1beta1/resources" + "github.com/project-kessel/inventory-client-go/v1beta1" + "github.com/stretchr/testify/assert" + "os" + "strconv" + "testing" +) + +var inventoryapi_http_url string +var tlsConfig *tls.Config +var insecure bool + +func TestMain(m *testing.M) { + inventoryapi_http_url = os.Getenv("INV_HTTP_URL") + if inventoryapi_http_url == "" { + err := fmt.Errorf("INV_HTTP_URL environment variable not set") + log.Error(err) + inventoryapi_http_url = "localhost:8081" + } + + insecure = true + + insecureTLSstr := os.Getenv("INV_TLS_INSECURE") + if insecureTLSstr != "" { + var err error + insecure, err = strconv.ParseBool(insecureTLSstr) + if err != nil { + log.Errorf("faild to parse bool INV_TLS_INSECURE %s", err) + } + } + + certFile := os.Getenv("INV_TLS_CERT_FILE") + keyFile := os.Getenv("INV_TLS_KEY_FILE") + caFile := os.Getenv("INV_TLS_CA_FILE") + if certFile != "" && keyFile != "" && caFile != "" { + // Load client cert + cert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + log.Errorf("failed to load client certificate: %v", err) + } + + // Load CA cert + caCert, err := os.ReadFile(caFile) + if err != nil { + log.Errorf("failed to read CA certificate: %v", err) + } + + caCertPool := x509.NewCertPool() + if !caCertPool.AppendCertsFromPEM(caCert) { + log.Errorf("failed to append CA certificate") + } + + tlsConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCertPool, + } + } else { + insecure = true + log.Info("TLS environment variables not set") + } + + result := m.Run() + os.Exit(result) +} + +func TestInventoryAPIHTTP_CreateRHELHost(t *testing.T) { + t.Parallel() + c := v1beta1.NewConfig( + v1beta1.WithHTTPUrl(inventoryapi_http_url), + v1beta1.WithTLSInsecure(insecure), + v1beta1.WithHTTPTLSConfig(tlsConfig), + ) + client, err := v1beta1.NewHttpClient(context.Background(), c) + if err != nil { + t.Error(err) + } + request := resources.CreateRhelHostRequest{RhelHost: &resources.RhelHost{ + Metadata: &resources.Metadata{ + ResourceType: "rhel-host", + Workspace: "workspace1", + }, + ReporterData: &resources.ReporterData{ + ReporterInstanceId: "user@example.com", + ReporterType: resources.ReporterData_OCM, + ConsoleHref: "www.example.com", + ApiHref: "www.example.com", + LocalResourceId: "1", + ReporterVersion: "0.1", + }, + }} + _, err = client.RhelHostServiceClient.CreateRhelHost(context.Background(), &request) + assert.NoError(t, err) + +} + +func TestInventoryAPIHTTP_K8SCluster_CreateK8SCluster(t *testing.T) { + t.Parallel() + client, err := v1beta1.New(v1beta1.NewConfig( + v1beta1.WithHTTPUrl(inventoryapi_http_url), + v1beta1.WithTLSInsecure(insecure), + v1beta1.WithHTTPTLSConfig(tlsConfig), + )) + if err != nil { + t.Error(err) + } + request := resources.CreateK8SClusterRequest{ + K8SCluster: &resources.K8SCluster{ + Metadata: &resources.Metadata{ + ResourceType: "k8s-cluster", + Workspace: "", + }, + ResourceData: &resources.K8SClusterDetail{ + ExternalClusterId: "1234", + ClusterStatus: resources.K8SClusterDetail_READY, + KubeVersion: "1.31", + KubeVendor: resources.K8SClusterDetail_OPENSHIFT, + VendorVersion: "4.16", + CloudPlatform: resources.K8SClusterDetail_AWS_UPI, + Nodes: []*resources.K8SClusterDetailNodesInner{ + { + Name: "www.example.com", + Cpu: "7500m", + Memory: "30973224Ki", + Labels: []*resources.ResourceLabel{ + { + Key: "has_monster_gpu", + Value: "yes", + }, + }, + }, + }, + }, + ReporterData: &resources.ReporterData{ + ReporterInstanceId: "user@example.com", + ReporterType: resources.ReporterData_ACM, + ConsoleHref: "www.example.com", + ApiHref: "www.example.com", + LocalResourceId: "1", + ReporterVersion: "0.1", + }, + }, + } + + _, err = client.K8sClusterService.CreateK8SCluster(context.Background(), &request) + assert.NoError(t, err) +} diff --git a/test/e2e/kafkaconsumer_test.go b/test/e2e/kafkaconsumer_test.go index 37d00276..9c3ff33d 100644 --- a/test/e2e/kafkaconsumer_test.go +++ b/test/e2e/kafkaconsumer_test.go @@ -90,6 +90,10 @@ func Test_ACMKafkaConsumer(t *testing.T) { kafkaCaLocation := os.Getenv("KAFKA_SSL_CA_LOCATION") kafkaCertLocation := os.Getenv("KAFKA_SSL_CERT_LOCATION") kafkaKeyLocation := os.Getenv("KAFKA_SSL_KEY_LOCATION") + kafkaKeyPassword := os.Getenv("KAFKA_SSL_KEY_PASSWORD") + kafkaClientCert := os.Getenv("KAFKA_CLIENT_CERT") // Client cert for mutual authentication + kafkaClientKey := os.Getenv("KAFKA_CLIENT_KEY") // Client private key for mutual authentication + topic := getEnvOrDefault("KAFKA_TOPIC", "kessel-inventory") config := &kafka.ConfigMap{ @@ -99,28 +103,53 @@ func Test_ACMKafkaConsumer(t *testing.T) { } if kafkaSecProtocol != "" { - if kafkaCaLocation == "" || kafkaCertLocation == "" || kafkaKeyLocation == "" { - log.Fatalf("SSL configuration is incomplete. Please provide KAFKA_SSL_CA_LOCATION, KAFKA_SSL_CERT_LOCATION, and KAFKA_SSL_KEY_LOCATION.") - } err := config.SetKey("security.protocol", kafkaSecProtocol) if err != nil { err = fmt.Errorf("please provide KAFKA_SECURITY_PROTOCOL to set security.protocol") log.Error(err) } - err = config.SetKey("ssl.ca.location", kafkaCaLocation) - if err != nil { - err = fmt.Errorf("please provide KAFKA_SSL_CA_LOCATION to set ssl.ca.location") - log.Error(err) + if kafkaCaLocation != "" { + err = config.SetKey("ssl.ca.location", kafkaCaLocation) + if err != nil { + err = fmt.Errorf("please provide KAFKA_SSL_CA_LOCATION to set ssl.ca.location") + log.Error(err) + } } - err = config.SetKey("ssl.certificate.location", kafkaCertLocation) - if err != nil { - err = fmt.Errorf("please provide KAFKA_SSL_CERT_LOCATION to set ssl.certificate.location") - log.Error(err) + if kafkaCertLocation != "" { + err = config.SetKey("ssl.certificate.location", kafkaCertLocation) + if err != nil { + err = fmt.Errorf("please provide KAFKA_SSL_CERT_LOCATION to set ssl.certificate.location") + log.Error(err) + } } - err = config.SetKey("ssl.key.location", kafkaKeyLocation) - if err != nil { - err = fmt.Errorf("please provide KAFKA_SSL_KEY_LOCATION to set ssl.key.location") - log.Error(err) + if kafkaKeyLocation != "" { + err = config.SetKey("ssl.key.location", kafkaKeyLocation) + if err != nil { + err = fmt.Errorf("please provide KAFKA_SSL_KEY_LOCATION to set ssl.key.location") + log.Error(err) + } + } + if kafkaKeyPassword != "" { + err = config.SetKey("ssl.key.password", kafkaKeyPassword) + if err != nil { + err = fmt.Errorf("please provide KAFKA_SSL_KEY_PASSWORD to set ssl.key.password") + log.Error(err) + } + } + + if kafkaClientCert != "" { + err = config.SetKey("ssl.keystore.location", kafkaClientCert) // Client certificate + if err != nil { + err = fmt.Errorf("please provide KAFKA_CLIENT_CERT to set ssl.keystore.location") + log.Error(err) + } + } + if kafkaClientKey != "" { + err = config.SetKey("ssl.keystore.password", kafkaClientKey) // Client key + if err != nil { + err = fmt.Errorf("please provide KAFKA_CLIENT_KEY to set ssl.keystore.password") + log.Error(err) + } } }