mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
20f7c85382
GITHUB_PR_NUMBER: 7426 GITHUB_PR_URL: https://github.com/hasura/graphql-engine/pull/7426 PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2173 Co-authored-by: Ajay Tripathi <24985760+atb00ker@users.noreply.github.com> Co-authored-by: Kali Vara Purushotham Santhati <72007599+purush7@users.noreply.github.com> Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: 1030d24c9e6c7d0c7062b6f0e98f8464950529d3
309 lines
11 KiB
Go
309 lines
11 KiB
Go
package commands
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
"github.com/hasura/graphql-engine/cli/v2"
|
|
|
|
"github.com/Pallinder/go-randomdata"
|
|
"github.com/hasura/graphql-engine/cli/v2/internal/testutil"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
. "github.com/onsi/gomega/gexec"
|
|
)
|
|
|
|
var commonDeployCommandsTest = func(projectDirectory string, databaseFlags ...string) {
|
|
Context("should apply metadata, run migrations and reload metadata", func() {
|
|
// Run Deploy
|
|
session := testutil.Hasura(testutil.CmdOpts{
|
|
Args: []string{"deploy"},
|
|
WorkingDirectory: projectDirectory,
|
|
})
|
|
Eventually(session, timeout).Should(Exit(0))
|
|
deployOutput := session.Err.Contents()
|
|
Expect(deployOutput).Should(ContainSubstring("Metadata applied"))
|
|
Expect(deployOutput).Should(ContainSubstring("migrations applied"))
|
|
// incase of config_v3
|
|
if len(databaseFlags) != 0 {
|
|
Expect(deployOutput).Should(ContainSubstring("Metadata reloaded"))
|
|
}
|
|
|
|
// Ensure metadata is applied
|
|
metadataSession := testutil.Hasura(testutil.CmdOpts{
|
|
Args: []string{"metadata", "inconsistency", "status"},
|
|
WorkingDirectory: projectDirectory,
|
|
})
|
|
Eventually(metadataSession, timeout).Should(Exit(0))
|
|
metadataOutput := string(metadataSession.Err.Contents())
|
|
Expect(metadataOutput).Should(ContainSubstring("metadata is consistent"))
|
|
|
|
// Ensure migrations are applied
|
|
migrateSession := testutil.Hasura(testutil.CmdOpts{
|
|
Args: append([]string{"migrate", "status"}, databaseFlags...),
|
|
WorkingDirectory: projectDirectory,
|
|
})
|
|
Eventually(migrateSession, timeout).Should(Exit(0))
|
|
migrateOutput := string(migrateSession.Out.Contents())
|
|
Expect(migrateOutput).Should(ContainSubstring("Present Present"))
|
|
})
|
|
}
|
|
|
|
var _ = Describe("hasura deploy config v3", func() {
|
|
var projectDirectory string
|
|
var teardown func()
|
|
sourceName := randomdata.SillyName()
|
|
|
|
BeforeEach(func() {
|
|
projectDirectory = testutil.RandDirName()
|
|
hgeEndPort, teardownHGE := testutil.StartHasura(GinkgoT(), testutil.HasuraDockerImage)
|
|
hgeEndpoint := fmt.Sprintf("http://0.0.0.0:%s", hgeEndPort)
|
|
|
|
connectionString, teardownPG := testutil.StartPGContainer(GinkgoT())
|
|
testutil.AddPGSourceToHasura(GinkgoT(), hgeEndpoint, connectionString, sourceName)
|
|
copyTestConfigV3Project(projectDirectory)
|
|
editEndpointInConfig(filepath.Join(projectDirectory, defaultConfigFilename), hgeEndpoint)
|
|
editSourceNameInConfigV3ProjectTemplate(projectDirectory, sourceName, connectionString)
|
|
|
|
teardown = func() {
|
|
os.RemoveAll(projectDirectory)
|
|
teardownPG()
|
|
teardownHGE()
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
teardown()
|
|
})
|
|
|
|
It("deploy", func() {
|
|
commonDeployCommandsTest(projectDirectory, "--database-name", sourceName)
|
|
})
|
|
})
|
|
|
|
var _ = Describe("hasura deploy config v2", func() {
|
|
var projectDirectory string
|
|
var teardown func()
|
|
|
|
BeforeEach(func() {
|
|
projectDirectory = testutil.RandDirName()
|
|
hgeEndPort, teardownHGE := testutil.StartHasura(GinkgoT(), testutil.HasuraDockerImage)
|
|
hgeEndpoint := fmt.Sprintf("http://0.0.0.0:%s", hgeEndPort)
|
|
copyTestConfigV2Project(projectDirectory)
|
|
editEndpointInConfig(filepath.Join(projectDirectory, defaultConfigFilename), hgeEndpoint)
|
|
|
|
teardown = func() {
|
|
os.RemoveAll(projectDirectory)
|
|
teardownHGE()
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
teardown()
|
|
})
|
|
|
|
It("deploy", func() {
|
|
commonDeployCommandsTest(projectDirectory)
|
|
})
|
|
})
|
|
|
|
var _ = Describe("fsm state transitions: config v2", func() {
|
|
|
|
var projectDirectory string
|
|
var teardown, teardownHGE func()
|
|
|
|
BeforeEach(func() {
|
|
projectDirectory = testutil.RandDirName()
|
|
var hgeEndPort string
|
|
hgeEndPort, teardownHGE = testutil.StartHasura(GinkgoT(), testutil.HasuraDockerImage)
|
|
hgeEndpoint := fmt.Sprintf("http://0.0.0.0:%s", hgeEndPort)
|
|
copyTestConfigV2Project(projectDirectory)
|
|
editEndpointInConfig(filepath.Join(projectDirectory, defaultConfigFilename), hgeEndpoint)
|
|
|
|
teardown = func() {
|
|
os.RemoveAll(projectDirectory)
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
teardown()
|
|
})
|
|
It("should make correct state transitions", func() {
|
|
ctx := &deployCtx{
|
|
err: nil,
|
|
}
|
|
ctx.ec = cli.NewExecutionContext()
|
|
ctx.ec.Viper = viper.New()
|
|
ctx.ec.ExecutionDirectory = projectDirectory
|
|
//ctx.ec.LogLevel = "DEBUG"
|
|
Expect(ctx.ec.Prepare()).Should(BeNil())
|
|
//ctx.ec.Stderr = io.Discard
|
|
Expect(ctx.ec.Validate()).Should(BeNil())
|
|
ctx.logger = ctx.ec.Logger
|
|
|
|
// bad sql migration
|
|
configV2FSM := newConfigV2DeployFSM()
|
|
migrationFilePath := filepath.Join(projectDirectory, "migrations", "1620138136207_create_table_public_t1/up.sql")
|
|
upSQL, err := ioutil.ReadFile(migrationFilePath)
|
|
Expect(err).To(BeNil())
|
|
badUpSQL := []byte(string(upSQL) + "SOME GARBAGE;")
|
|
Expect(ioutil.WriteFile(migrationFilePath, badUpSQL, 0755)).To(BeNil())
|
|
|
|
Expect(configV2FSM.SendEvent(applyMigrations, ctx)).To(BeNil())
|
|
Expect(configV2FSM.Current).Should(Equal(failedOperation))
|
|
Expect(configV2FSM.Previous).Should(Equal(applyingMigrationsFailed))
|
|
ctx.ec.Logger.Debugf("error: %v", ctx.err)
|
|
Expect(ctx.err).Should(Not(BeNil()))
|
|
// reset file contents
|
|
Expect(ioutil.WriteFile(migrationFilePath, upSQL, 0755)).To(BeNil())
|
|
|
|
// bad metadata yaml file
|
|
tablesYamlFilepath := filepath.Join(projectDirectory, "metadata", "tables.yaml")
|
|
tablesYaml, err := ioutil.ReadFile(tablesYamlFilepath)
|
|
Expect(err).To(BeNil())
|
|
|
|
// user error in tables.yaml
|
|
configV2FSM = newConfigV2DeployFSM()
|
|
badTablesYaml := []byte(`some: key`)
|
|
Expect(ioutil.WriteFile(tablesYamlFilepath, badTablesYaml, 0755)).To(BeNil())
|
|
Expect(configV2FSM.SendEvent(applyMigrations, ctx)).To(BeNil())
|
|
Expect(configV2FSM.Current).Should(Equal(failedOperation))
|
|
Expect(configV2FSM.Previous).Should(Equal(applyingMetadataFailed))
|
|
ctx.ec.Logger.Debugf("error: %v", ctx.err)
|
|
Expect(ctx.err).Should(Not(BeNil()))
|
|
|
|
// validation error from server
|
|
configV2FSM = newConfigV2DeployFSM()
|
|
badTablesYaml = []byte(`
|
|
- table:
|
|
schema: public
|
|
# this should be a string not a number
|
|
name: 1
|
|
`)
|
|
Expect(ioutil.WriteFile(tablesYamlFilepath, badTablesYaml, 0755)).To(BeNil())
|
|
Expect(configV2FSM.SendEvent(applyMigrations, ctx)).To(BeNil())
|
|
ctx.ec.Logger.Debugf("error: %v", ctx.err)
|
|
Expect(configV2FSM.Current).Should(Equal(failedOperation))
|
|
Expect(configV2FSM.Previous).Should(Equal(applyingMetadataFailed))
|
|
Expect(ctx.err).Should(Not(BeNil()))
|
|
// reset file contents
|
|
Expect(ioutil.WriteFile(tablesYamlFilepath, tablesYaml, 0755)).To(BeNil())
|
|
|
|
// happy path
|
|
configV2FSM = newConfigV2DeployFSM()
|
|
Expect(configV2FSM.SendEvent(applyMigrations, ctx)).To(BeNil())
|
|
Expect(configV2FSM.Current).Should(Equal(reloadingMetadata))
|
|
|
|
// unreachable HGE
|
|
teardownHGE()
|
|
configV2FSM = newConfigV2DeployFSM()
|
|
Expect(configV2FSM.SendEvent(applyMigrations, ctx)).To(BeNil())
|
|
Expect(configV2FSM.Current).Should(Equal(failedOperation))
|
|
})
|
|
})
|
|
|
|
var _ = Describe("fsm state transitions: config v3", func() {
|
|
var projectDirectory string
|
|
var teardown, teardownHGE func()
|
|
|
|
sourceName := randomdata.SillyName()
|
|
BeforeEach(func() {
|
|
projectDirectory = testutil.RandDirName()
|
|
var hgeEndPort string
|
|
hgeEndPort, teardownHGE = testutil.StartHasuraWithMetadataDatabase(GinkgoT(), testutil.HasuraDockerImage)
|
|
hgeEndpoint := fmt.Sprintf("http://0.0.0.0:%s", hgeEndPort)
|
|
|
|
connectionString, teardownPG := testutil.StartPGContainer(GinkgoT())
|
|
testutil.AddPGSourceToHasura(GinkgoT(), hgeEndpoint, connectionString, sourceName)
|
|
copyTestConfigV3Project(projectDirectory)
|
|
editEndpointInConfig(filepath.Join(projectDirectory, defaultConfigFilename), hgeEndpoint)
|
|
editSourceNameInConfigV3ProjectTemplate(projectDirectory, sourceName, connectionString)
|
|
|
|
teardown = func() {
|
|
os.RemoveAll(projectDirectory)
|
|
teardownPG()
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
teardown()
|
|
})
|
|
It("should make correct state transitions", func() {
|
|
ctx := &deployCtx{
|
|
err: nil,
|
|
}
|
|
ctx.ec = cli.NewExecutionContext()
|
|
ctx.ec.Viper = viper.New()
|
|
ctx.ec.ExecutionDirectory = projectDirectory
|
|
//ctx.ec.LogLevel = "DEBUG"
|
|
Expect(ctx.ec.Prepare()).Should(BeNil())
|
|
ctx.ec.Stderr = io.Discard
|
|
Expect(ctx.ec.Validate()).Should(BeNil())
|
|
ctx.logger = ctx.ec.Logger
|
|
|
|
// bad sql migration
|
|
configV3DeployFSM := newConfigV3DeployFSM()
|
|
migrationFilePath := filepath.Join(projectDirectory, "migrations", sourceName, "1622047079431_chinook/up.sql")
|
|
upSQL, err := ioutil.ReadFile(migrationFilePath)
|
|
Expect(err).To(BeNil())
|
|
badUpSQL := []byte("SOME GARBAGE;")
|
|
Expect(ioutil.WriteFile(migrationFilePath, badUpSQL, 0755)).To(BeNil())
|
|
|
|
Expect(configV3DeployFSM.SendEvent(applyInitialMetadata, ctx)).To(BeNil())
|
|
Expect(configV3DeployFSM.Current).Should(Equal(failedOperation))
|
|
Expect(configV3DeployFSM.Previous).Should(Equal(applyingMigrationsFailed))
|
|
ctx.ec.Logger.Debugf("error: %v", ctx.err)
|
|
Expect(ctx.err).Should(Not(BeNil()))
|
|
// reset file contents
|
|
Expect(ioutil.WriteFile(migrationFilePath, upSQL, 0755)).To(BeNil())
|
|
|
|
// bad metadata yaml file
|
|
tablesYamlFilepath := filepath.Join(projectDirectory, "metadata", "databases", sourceName, "tables", "tables.yaml")
|
|
tablesYaml, err := ioutil.ReadFile(tablesYamlFilepath)
|
|
Expect(err).To(BeNil())
|
|
|
|
// user error in tables.yaml
|
|
configV3DeployFSM = newConfigV3DeployFSM()
|
|
badTablesYaml := []byte(`some: key`)
|
|
Expect(ioutil.WriteFile(tablesYamlFilepath, badTablesYaml, 0755)).To(BeNil())
|
|
Expect(configV3DeployFSM.SendEvent(applyInitialMetadata, ctx)).To(BeNil())
|
|
Expect(configV3DeployFSM.Current).Should(Equal(failedOperation))
|
|
Expect(configV3DeployFSM.Previous).Should(Equal(applyingInitialMetadataFailed))
|
|
ctx.ec.Logger.Debugf("error: %v", ctx.err)
|
|
Expect(ctx.err).Should(Not(BeNil()))
|
|
|
|
// validation error from server
|
|
configV3DeployFSM = newConfigV3DeployFSM()
|
|
badTablesYaml = []byte(`
|
|
- table:
|
|
schema: public
|
|
# this should be a string not a number
|
|
name: 1
|
|
`)
|
|
Expect(ioutil.WriteFile(tablesYamlFilepath, badTablesYaml, 0755)).To(BeNil())
|
|
Expect(configV3DeployFSM.SendEvent(applyInitialMetadata, ctx)).To(BeNil())
|
|
ctx.ec.Logger.Debugf("error: %v", ctx.err)
|
|
Expect(configV3DeployFSM.Current).Should(Equal(failedOperation))
|
|
Expect(configV3DeployFSM.Previous).Should(Equal(applyingInitialMetadataFailed))
|
|
Expect(ctx.err).Should(Not(BeNil()))
|
|
// reset file contents
|
|
Expect(ioutil.WriteFile(tablesYamlFilepath, tablesYaml, 0755)).To(BeNil())
|
|
|
|
// happy path
|
|
configV3DeployFSM = newConfigV3DeployFSM()
|
|
Expect(configV3DeployFSM.SendEvent(applyInitialMetadata, ctx)).To(BeNil())
|
|
Expect(configV3DeployFSM.Current).Should(Equal(reloadingMetadata))
|
|
|
|
// unreachable HGE
|
|
teardownHGE()
|
|
configV3DeployFSM = newConfigV3DeployFSM()
|
|
Expect(configV3DeployFSM.SendEvent(applyInitialMetadata, ctx)).To(BeNil())
|
|
Expect(configV3DeployFSM.Current).Should(Equal(failedOperation))
|
|
})
|
|
})
|