diff --git a/.github/workflows/product_builder.yaml b/.github/workflows/product_builder.yaml index 0046302227..faa64d0422 100644 --- a/.github/workflows/product_builder.yaml +++ b/.github/workflows/product_builder.yaml @@ -601,15 +601,25 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ github.token }} - - name: Setup using cli + - name: Setup dyrectorio stack using dyo-cli run: | export GITHUB_NETWORK=$(docker network ls -f name=github_network --format {{.Name}}) docker run -v /var/run/docker.sock:/var/run/docker.sock --network $GITHUB_NETWORK ${GITHUB_REGISTRY}/${CLI_IMAGE_NAME}:${{ needs.gather_changes.outputs.tag }} --image-tag ${{ needs.gather_changes.outputs.tag }} --network $GITHUB_NETWORK --prefer-local-images --expect-container-env --debug -p dyo-e2e up + - name: Check if containers are running and reachable + run: | + curl -vfL -m 30 http://dyo-e2e_traefik:8000 > /dev/null - name: Setup NPM caches uses: actions/cache/restore@v3 with: path: ${{ env.CRUX_UI_WORKING_DIRECTORY }}/.npm/** key: ${{ runner.os }}-e2e_test-${{ hashFiles('web/crux-ui/package-lock.json') }} + - name: Setup playwright + working-directory: ${{ env.CRUX_UI_WORKING_DIRECTORY }} + env: + CI: true + run: | + npm ci --include=dev --arch=x64 --cache .npm --prefer-offline --no-fund + npx playwright install chromium - name: Run tests working-directory: ${{ env.CRUX_UI_WORKING_DIRECTORY }} env: @@ -621,10 +631,7 @@ jobs: CRUX_UI_URL: "http://dyo-e2e_traefik:8000" KRATOS_URL: "http://dyo-e2e_kratos:4433" KRATOS_ADMIN_URL: "http://dyo-e2e_kratos:4434" - CI: true run: | - npm ci --include=dev --arch=x64 --cache .npm --prefer-offline --no-fund - npx playwright install chromium npm run test:e2e - name: Gather logs working-directory: ${{ env.CRUX_UI_WORKING_DIRECTORY }} @@ -632,11 +639,12 @@ jobs: run: | docker ps mkdir logs - docker logs dyo-e2e_crux-ui > logs/e2e-crux-ui.log 2>&1 - docker logs dyo-e2e_crux > logs/e2e-crux.log 2>&1 - docker logs dyo-e2e_kratos > logs/e2e-kratos.log 2>&1 - docker logs dyo-e2e_traefik > logs/e2e-traefik.log 2>&1 - docker logs dagent > logs/e2e-dagent.log 2>&1 + CONTAINERS="dyo-e2e_crux-ui dyo-e2e_crux dyo-e2e_kratos dyo-e2e_traefik dagent" + for cont in $CONTAINERS + do + docker logs $cont > logs/$cont.log 2>&1 + docker inspect $cont > logs/$cont.inspect 2>&1 + done - uses: actions/upload-artifact@v3 if: failure() with: diff --git a/go.mod b/go.mod index 4228c236c9..0dc28b49e8 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/dyrector-io/dyrectorio -go 1.21 +go 1.22.2 + +toolchain go1.23.3 require ( github.com/ProtonMail/gopenpgp/v2 v2.7.1 @@ -99,6 +101,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/na4ma4/go-permbits v0.5.1 github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc3 github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 58bb895697..6e02d26479 100644 --- a/go.sum +++ b/go.sum @@ -199,6 +199,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/na4ma4/go-permbits v0.5.1 h1:bC8ZV5Oysbcia7tMo7pgX19RGjuD4ZRF+p8dLxXk1y4= +github.com/na4ma4/go-permbits v0.5.1/go.mod h1:iOOrz6HQbNi5liXxRp8PfiF7geywq1CYYJCKmcbRgTI= github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= diff --git a/golang/Makefile b/golang/Makefile index 9ffb1593f2..8af462a58d 100644 --- a/golang/Makefile +++ b/golang/Makefile @@ -53,10 +53,11 @@ down: # target `upd` is for development purposes it defaults to the latest images # and expects crux and crux-ui to run locally +# for host name overrides you can define: --host localhost,yourdomain.com .PHONY: upd upd: cd cmd/dyo && \ - go run . --disable-crux --disable-crux-ui --image-tag latest --prefix dyo-latest up + go run . --disable-crux --disable-crux-ui --image-tag latest --prefix dyo-latest --host localhost up .PHONY: downd downd: @@ -65,7 +66,7 @@ downd: .PHONY: go-crane go-crane: - air --build.cmd "" --build.bin "cd cmd/crane && go run ." + air --build.cmd "" --build.bin "cd cmd/crane && ${GRPC_DEBUG_FLAGS} go run ." .PHONY: go-crane-init go-crane-init: @@ -74,7 +75,7 @@ go-crane-init: .PHONY: go-dagent go-dagent: - air --build.cmd "" --build.bin "cd cmd/dagent && go run ." + air --build.cmd "" --build.bin "cd cmd/dagent && ${GRPC_DEBUG_FLAGS} go run ." .PHONY: cli cli: diff --git a/golang/internal/health/server.go b/golang/internal/health/server.go index 5467c7c518..7af89255b8 100644 --- a/golang/internal/health/server.go +++ b/golang/internal/health/server.go @@ -7,6 +7,7 @@ import ( "net" "os" + "github.com/na4ma4/go-permbits" "github.com/rs/zerolog/log" ) @@ -61,7 +62,7 @@ func Serve(ctx context.Context) error { log.Error().Str("file", socketPath).Err(err).Msg("Failed to check socket file") } - err = os.MkdirAll(getSocketDir(), dirPerm) + err = os.MkdirAll(getSocketDir(), permbits.UserAll+permbits.GroupReadWrite+permbits.OtherReadWrite) if err != nil { return err } diff --git a/golang/internal/health/types.go b/golang/internal/health/types.go index 1aa0d2053c..a191744cc2 100644 --- a/golang/internal/health/types.go +++ b/golang/internal/health/types.go @@ -7,7 +7,6 @@ import ( const ( socketType = "unix" - dirPerm = 0o755 ) type Status struct { diff --git a/golang/pkg/cli/cli.go b/golang/pkg/cli/cli.go index 4f5c79cde0..643259a4dd 100644 --- a/golang/pkg/cli/cli.go +++ b/golang/pkg/cli/cli.go @@ -19,6 +19,7 @@ const ( FlagDebug = "debug" FlagPreferLocalImages = "prefer-local-images" FlagConfigPath = "config" + FlagHosts = "host" FlagPrefix = "prefix" FlagImageTag = "image-tag" FlagSilent = "silent" @@ -112,6 +113,14 @@ func InitCLI() *ucli.App { Required: false, EnvVars: []string{"DYO_CONFIG"}, }, + &ucli.StringSliceFlag{ + Name: FlagHosts, + Aliases: []string{}, + Value: ucli.NewStringSlice("localhost"), + DefaultText: "localhost", + Usage: "Use this hosts instead of default one. Eg. 'localhost,extradomain1.example.com,extradomain2.example.com'", + Required: false, + }, &ucli.StringFlag{ Name: FlagImageTag, Value: "", @@ -179,6 +188,7 @@ func run(cCtx *ucli.Context) error { LocalAgent: cCtx.Bool(FlagLocalAgent), Command: cCtx.Command.Name, EnvFile: cCtx.String(FlagEnvFile), + Hosts: cCtx.StringSlice(FlagHosts), } initialState := State{ diff --git a/golang/pkg/cli/config_file.go b/golang/pkg/cli/config_file.go index 129b89109d..a5f5f7de7e 100644 --- a/golang/pkg/cli/config_file.go +++ b/golang/pkg/cli/config_file.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/client" "github.com/ilyakaznacheev/cleanenv" + "github.com/na4ma4/go-permbits" "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" ) @@ -40,6 +41,7 @@ type ArgsFlags struct { Command string ImageTag string Prefix string + Hosts []string CruxDisabled bool CruxUIDisabled bool LocalAgent bool @@ -118,8 +120,6 @@ const ( ) const ( - filePerms = 0o600 - dirPerms = 0o750 secretLength = 32 cruxEncryptionKeyLength = 32 bufferMultiplier = 2 @@ -252,7 +252,7 @@ func SaveSettings(state *State, args *ArgsFlags) { // If settingsPath is default, we create the directory for it if args.SettingsFilePath == settingsPath { if _, err := os.Stat(path.Dir(settingsPath)); errors.Is(err, os.ErrNotExist) { - err = os.MkdirAll(path.Dir(settingsPath), dirPerms) + err = os.MkdirAll(path.Dir(settingsPath), permbits.UserAll+permbits.GroupRead+permbits.GroupExecute) if err != nil { log.Fatal().Err(err).Stack().Send() } @@ -271,7 +271,7 @@ func SaveSettings(state *State, args *ArgsFlags) { log.Fatal().Err(err).Stack().Send() } - err = os.WriteFile(args.SettingsFilePath, filedata, filePerms) + err = os.WriteFile(args.SettingsFilePath, filedata, permbits.UserReadWrite) if err != nil { log.Fatal().Err(err).Stack().Send() } diff --git a/golang/pkg/cli/container_defaults.go b/golang/pkg/cli/container_defaults.go index 5dac3f72b4..631eda9f48 100644 --- a/golang/pkg/cli/container_defaults.go +++ b/golang/pkg/cli/container_defaults.go @@ -22,6 +22,7 @@ import ( "github.com/dyrector-io/dyrectorio/golang/internal/helper/image" "github.com/dyrector-io/dyrectorio/golang/internal/label" "github.com/dyrector-io/dyrectorio/golang/internal/logdefer" + "github.com/dyrector-io/dyrectorio/golang/internal/util" containerbuilder "github.com/dyrector-io/dyrectorio/golang/pkg/builder/container" dagentutils "github.com/dyrector-io/dyrectorio/golang/pkg/dagent/utils" ) @@ -70,9 +71,9 @@ func GetCrux(state *State, args *ArgsFlags) containerbuilder.Builder { WithCmd([]string{"serve"}). WithLabels(map[string]string{ "traefik.enable": "true", - "traefik.http.routers.crux.rule": fmt.Sprintf("(Host(`localhost`) || Host(`%s`) || Host(`%s`)) && "+ + "traefik.http.routers.crux.rule": fmt.Sprintf("(%s) && "+ "PathPrefix(`/api`) && !PathPrefix(`/api/auth`) && !PathPrefix(`/api/status`) ", - state.Containers.Traefik.Name, state.InternalHostDomain), + RenderTraefikHostRules(append(args.Hosts, state.Containers.Traefik.Name, state.InternalHostDomain)...)), "traefik.http.routers.crux.entrypoints": "web", "traefik.http.services.crux.loadbalancer.server.port": fmt.Sprintf("%d", defaultCruxHTTPPort), "com.docker.compose.project": args.Prefix, @@ -220,8 +221,8 @@ func GetCruxUI(state *State, args *ArgsFlags) containerbuilder.Builder { WithNetworkAliases(state.Containers.CruxUI.Name). WithLabels(map[string]string{ "traefik.enable": "true", - "traefik.http.routers.crux-ui.rule": fmt.Sprintf("Host(`%s`) || Host(`%s`) || Host(`%s`)", traefikHost, state.InternalHostDomain, - state.Containers.Traefik.Name), + "traefik.http.routers.crux-ui.rule": RenderTraefikHostRules( + append(args.Hosts, traefikHost, state.InternalHostDomain, state.Containers.Traefik.Name)...), "traefik.http.routers.crux-ui.entrypoints": "web", "traefik.http.services.crux-ui.loadbalancer.server.port": fmt.Sprintf("%d", defaultCruxUIPort), "com.docker.compose.project": args.Prefix, @@ -270,7 +271,7 @@ func GetTraefik(state *State, args *ArgsFlags) containerbuilder.Builder { fmt.Sprintf("--entrypoints.web.address=:%d", defaultTraefikInternalPort), } - if args.CruxUIDisabled { + if args.CruxUIDisabled || args.CruxDisabled { commands = append(commands, "--providers.file.directory=/etc/traefik", "--providers.file.watch=true") } @@ -303,9 +304,14 @@ func GetTraefik(state *State, args *ArgsFlags) containerbuilder.Builder { return CopyTraefikConfiguration( ctx, cont.Name, - state.InternalHostDomain, - state.SettingsFile.CruxHTTPPort, - state.SettingsFile.CruxUIPort, + traefikFileProviderData{ + InternalHost: state.InternalHostDomain, + HostRules: RenderTraefikHostRules(append(args.Hosts, state.InternalHostDomain, cont.Name)...), + CruxUIPort: state.SettingsFile.CruxUIPort, + CruxPort: state.SettingsFile.CruxHTTPPort, + CruxUIDisabled: args.CruxUIDisabled, + CruxDisabled: args.CruxDisabled, + }, ) }) @@ -345,8 +351,9 @@ func GetKratos(state *State, args *ArgsFlags) containerbuilder.Builder { WithNetworkAliases(state.Containers.Kratos.Name). WithLabels(map[string]string{ "traefik.enable": "true", - "traefik.http.routers.kratos.rule": fmt.Sprintf("(Host(`localhost`) || Host(`%s`) || Host(`%s`)) && "+ - "PathPrefix(`/kratos`)", state.Containers.Traefik.Name, state.InternalHostDomain), + "traefik.http.routers.kratos.rule": fmt.Sprintf("(%s) && "+ + "PathPrefix(`/kratos`)", + RenderTraefikHostRules(append(args.Hosts, state.Containers.Traefik.Name, state.InternalHostDomain)...)), "traefik.http.routers.kratos.entrypoints": "web", "traefik.http.services.kratos.loadbalancer.server.port": fmt.Sprintf("%d", defaultKratosPublicPort), "traefik.http.middlewares.kratos-strip.stripprefix.prefixes": "/kratos", @@ -569,7 +576,7 @@ func getBasePostgres(state *State, args *ArgsFlags) containerbuilder.Builder { } // CopyTraefikConfiguration copies a config file to Traefik Container -func CopyTraefikConfiguration(ctx context.Context, name, internalHostDomain string, cruxPort, cruxUIPort uint) error { +func CopyTraefikConfiguration(ctx context.Context, containerName string, traefikTmplConfig traefikFileProviderData) error { cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { return err @@ -586,13 +593,7 @@ func CopyTraefikConfiguration(ctx context.Context, name, internalHostDomain stri var result bytes.Buffer - traefikData := traefikFileProviderData{ - InternalHost: internalHostDomain, - CruxUIPort: cruxUIPort, - CruxPort: cruxPort, - } - - err = traefikConfig.Execute(&result, traefikData) + err = traefikConfig.Execute(&result, traefikTmplConfig) if err != nil { return err } @@ -606,7 +607,7 @@ func CopyTraefikConfiguration(ctx context.Context, name, internalHostDomain stri err = dagentutils.WriteContainerFile( ctx, cli, - name, + containerName, "traefik/dynamic_conf.yml", data, int64(len([]rune(result.String()))), @@ -656,3 +657,12 @@ func healthProbe(ctx context.Context, address string) error { } } } + +func RenderTraefikHostRules(hosts ...string) string { + hostRules := []string{} + for _, v := range hosts { + hostRules = append(hostRules, fmt.Sprintf("Host(`%s`)", v)) + } + + return util.JoinV(" || ", hostRules...) +} diff --git a/golang/pkg/cli/container_defaults_test.go b/golang/pkg/cli/container_defaults_test.go new file mode 100644 index 0000000000..e6426e57d4 --- /dev/null +++ b/golang/pkg/cli/container_defaults_test.go @@ -0,0 +1,51 @@ +//go:build unit +// +build unit + +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRenderTraefikHostRules(t *testing.T) { + type args struct { + hosts []string + } + tests := []struct { + name string + want string + desc string + args args + }{ + { + name: "one-host", + args: args{ + hosts: []string{"localhost:8000"}, + }, + want: "Host(`localhost:8000`)", + }, + { + name: "two-hosts", + args: args{ + hosts: []string{"localhost:8000", "test.example.com"}, + }, + want: "Host(`localhost:8000`) || Host(`test.example.com`)", + }, + { + name: "no-host", + args: args{ + hosts: []string{}, + }, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, RenderTraefikHostRules(tt.args.hosts...), tt.desc) + }) + } + + assert.True(t, true, true) +} diff --git a/golang/pkg/cli/display.go b/golang/pkg/cli/display.go index 49b2ef90d0..94960d46e9 100644 --- a/golang/pkg/cli/display.go +++ b/golang/pkg/cli/display.go @@ -12,6 +12,7 @@ import ( "github.com/rs/zerolog/log" tm "github.com/buger/goterm" + "github.com/na4ma4/go-permbits" ) // PrintWelcomeMessage prints a welcome mesage before the command runs @@ -53,7 +54,7 @@ func NotifyOnce(name string, notifyFunc func()) { notificationPath := path.Join(targetDir, CLIDirName, "."+name) if _, err := os.Stat(notificationPath); err != nil { - err = os.WriteFile(notificationPath, []byte{}, os.ModePerm) + err = os.WriteFile(notificationPath, []byte{}, permbits.UserAll) if err != nil { log.Trace().Err(err).Msgf("cache folder is not available to store temporary info") } diff --git a/golang/pkg/cli/runner.go b/golang/pkg/cli/runner.go index 78263258eb..f8af05b6b5 100644 --- a/golang/pkg/cli/runner.go +++ b/golang/pkg/cli/runner.go @@ -52,9 +52,12 @@ const ( ) type traefikFileProviderData struct { - InternalHost string - CruxUIPort uint - CruxPort uint + InternalHost string + HostRules string + CruxUIPort uint + CruxPort uint + CruxUIDisabled bool + CruxDisabled bool } //go:embed traefik.yaml.tmpl diff --git a/golang/pkg/cli/traefik.yaml.tmpl b/golang/pkg/cli/traefik.yaml.tmpl index 4dd06cce9a..d7bea628b8 100644 --- a/golang/pkg/cli/traefik.yaml.tmpl +++ b/golang/pkg/cli/traefik.yaml.tmpl @@ -1,24 +1,44 @@ http: routers: + {{ if .CruxUIDisabled }} crux-ui: - rule: Host(`localhost`) || Host(`{{.InternalHost}}`) + rule: {{.HostRules}} service: crux-ui entryPoints: - web + {{ end }} - crux: - rule: (Host(`localhost`) || Host(`{{.InternalHost}}`)) && (PathPrefix(`/api`) && !PathPrefix(`/api/auth`) && !PathPrefix(`/api/status`)) - service: crux + + {{ if .CruxDisabled }} + crux-http: + rule: ({{.HostRules}}) && (PathPrefix(`/api`) && !PathPrefix(`/api/auth`) && !PathPrefix(`/api/status`)) + service: crux-http + entryPoints: + - web + + crux-grpc: + rule: ({{.HostRules}}) && Headers(`content-type`, `application/grpc`) + service: crux-grpc entryPoints: - web + {{ end }} services: + {{ if .CruxUIDisabled }} crux-ui: loadBalancer: servers: - url: http://{{.InternalHost}}:{{.CruxUIPort}} + {{ end }} - crux: + {{ if .CruxDisabled }} + crux-http: loadBalancer: servers: - url: http://{{.InternalHost}}:{{.CruxPort}} + + crux-grpc: + loadBalancer: + servers: + - url: h2c://{{.InternalHost}}:5000 + {{ end }} diff --git a/golang/pkg/dagent/config/config.go b/golang/pkg/dagent/config/config.go index 364aea7860..d66463d958 100644 --- a/golang/pkg/dagent/config/config.go +++ b/golang/pkg/dagent/config/config.go @@ -21,8 +21,6 @@ type Configuration struct { TraefikTLS bool `yaml:"traefikTLS" env:"TRAEFIK_TLS" env-default:"false"` } -const filePermReadWriteOnlyByOwner = 0o600 - func (c *Configuration) CheckPermissions() error { path := c.appendInternalMountPath(config.ConnectionTokenFileName) return checkFilePermissions(path) diff --git a/golang/pkg/dagent/config/secret.go b/golang/pkg/dagent/config/secret.go index 21046b8608..d0adaf76fa 100644 --- a/golang/pkg/dagent/config/secret.go +++ b/golang/pkg/dagent/config/secret.go @@ -9,6 +9,7 @@ import ( "syscall" "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/na4ma4/go-permbits" "github.com/rs/zerolog/log" config "github.com/dyrector-io/dyrectorio/golang/internal/config" @@ -60,7 +61,7 @@ func generateKey(path string) (string, error) { return "", keyErr } - fileErr := os.WriteFile(path, []byte(keyStr), os.ModePerm) + fileErr := os.WriteFile(path, []byte(keyStr), fs.FileMode(os.O_CREATE|os.O_WRONLY|os.O_TRUNC)) if fileErr != nil { return "", fileErr } @@ -97,7 +98,7 @@ func writeStringToFile(path, value string) error { return nil } - err := os.WriteFile(path, []byte(value), os.ModePerm) + err := os.WriteFile(path, []byte(value), permbits.UserReadWrite) if err != nil { return err } @@ -111,7 +112,7 @@ func (c *Configuration) appendInternalMountPath(path string) string { } func checkFilePermissions(path string) error { - file, err := os.OpenFile(filepath.Clean(path), os.O_RDWR|os.O_CREATE, filePermReadWriteOnlyByOwner) + file, err := os.OpenFile(filepath.Clean(path), os.O_RDWR|os.O_CREATE, permbits.UserReadWrite) if err != nil { return err } diff --git a/golang/pkg/dagent/utils/docker.go b/golang/pkg/dagent/utils/docker.go index 23eb552cd5..26c725e9a1 100644 --- a/golang/pkg/dagent/utils/docker.go +++ b/golang/pkg/dagent/utils/docker.go @@ -18,6 +18,7 @@ import ( "strings" "time" + "github.com/na4ma4/go-permbits" "github.com/rs/zerolog/log" "golang.org/x/exp/maps" @@ -48,8 +49,6 @@ import ( const DockerLogHeaderLength = 8 -const RWOwnerROther = 0o644 - type DockerVersion struct { ServerVersion string ClientVersion string @@ -115,7 +114,7 @@ func WriteContainerFile(ctx context.Context, cli *client.Client, tarHeader := &tar.Header{ Name: filename, - Mode: RWOwnerROther, + Mode: int64(permbits.UserReadWrite + permbits.GroupRead + permbits.OtherRead), Size: fileSize, Uid: meta.UID, Gid: meta.GID, @@ -604,6 +603,7 @@ func createRuntimeConfigFileOnHost(mounts []mount.Mount, containerName, containe panic(err) } } + //#nosec 304 -- this should be read-used by anyone, mostly the app container if err := os.WriteFile(path.Join(configDir, "appsettings.json"), []byte(runtimeConfig), os.ModePerm); err != nil { return mounts, err } diff --git a/golang/pkg/dagent/utils/environment.go b/golang/pkg/dagent/utils/environment.go index 02d97a4f35..458a9177a9 100644 --- a/golang/pkg/dagent/utils/environment.go +++ b/golang/pkg/dagent/utils/environment.go @@ -2,15 +2,13 @@ package utils import ( "fmt" - "io/fs" "os" "path/filepath" "github.com/joho/godotenv" + "github.com/na4ma4/go-permbits" ) -const dirPerm = 0o700 - type SharedVariableParamError struct { variable string } @@ -37,12 +35,12 @@ func WriteSharedEnvironmentVariables(dataRoot, prefix string, in map[string]stri sharedEnvDirPath := getSharedEnvDir(dataRoot, prefix) sharedEnvFilePath := getSharedEnvPath(dataRoot, prefix) - err = os.MkdirAll(sharedEnvDirPath, dirPerm) + err = os.MkdirAll(sharedEnvDirPath, permbits.UserAll) if err != nil { return err } - err = os.WriteFile(sharedEnvFilePath, []byte(out), fs.ModePerm) + err = os.WriteFile(sharedEnvFilePath, []byte(out), permbits.UserReadWrite) if err != nil { return err } diff --git a/golang/pkg/dagent/utils/environment_test.go b/golang/pkg/dagent/utils/environment_test.go index a4d12bbbcb..71108a3a1e 100644 --- a/golang/pkg/dagent/utils/environment_test.go +++ b/golang/pkg/dagent/utils/environment_test.go @@ -4,12 +4,12 @@ package utils_test import ( - "io/fs" "os" "path/filepath" "testing" "github.com/dyrector-io/dyrectorio/golang/pkg/dagent/utils" + "github.com/na4ma4/go-permbits" "github.com/stretchr/testify/assert" ) @@ -82,7 +82,7 @@ func TestReadSharedEnvironmentVariables(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { sharedEnvPath := filepath.Join(tt.dataRoot, tt.prefix, ".shared-env") - err := os.WriteFile(sharedEnvPath, []byte(tt.fileContent), fs.ModePerm) + err := os.WriteFile(sharedEnvPath, []byte(tt.fileContent), permbits.UserReadWrite) assert.NoError(t, err) defer func() { diff --git a/golang/pkg/dagent/utils/release.go b/golang/pkg/dagent/utils/release.go index 52c148dd8d..0a65644f7b 100644 --- a/golang/pkg/dagent/utils/release.go +++ b/golang/pkg/dagent/utils/release.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/na4ma4/go-permbits" "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" @@ -75,7 +76,7 @@ func DraftRelease(instance string, versionData v1.VersionData, deployResponse v1 log.Panic().Stack().Err(err).Send() } - err = os.WriteFile(filePath, content, os.ModePerm) + err = os.WriteFile(filePath, content, permbits.UserReadWrite) if err != nil { log.Error().Stack().Err(err).Msg("Writing release file error") } diff --git a/images/playwright/Dockerfile b/images/playwright/Dockerfile index 8c0d0ca3a6..9ad2bfd9ba 100644 --- a/images/playwright/Dockerfile +++ b/images/playwright/Dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:lunar +FROM ubuntu:noble -RUN apt-get update && apt-get install -y docker-compose nodejs npm jq curl zstd +RUN apt-get update && apt-get install -y docker-compose nodejs npm jq curl zstd libasound2t64 RUN mkdir playwright diff --git a/images/playwright/package.json b/images/playwright/package.json index d82839ea09..484141911e 100644 --- a/images/playwright/package.json +++ b/images/playwright/package.json @@ -17,7 +17,7 @@ }, "homepage": "https://github.com/dyrector-io/playwright#readme", "dependencies": { - "@playwright/test": "^1.42.0", - "playwright": "^1.42.0" + "@playwright/test": "^1.43.0", + "playwright": "^1.43.0" } } diff --git a/web/crux-ui/.env.example b/web/crux-ui/.env.example index 8f1b4e5d06..d1133ed077 100644 --- a/web/crux-ui/.env.example +++ b/web/crux-ui/.env.example @@ -9,15 +9,14 @@ KRATOS_ADMIN_URL=http://localhost:4434 # Example: error contains fatal LOG_LEVEL=trace -## Google ReCAPTCHA config - +# # Google ReCAPTCHA config DISABLE_RECAPTCHA=true + # Required only when ReCAPTCHA is enabled RECAPTCHA_SITE_KEY= RECAPTCHA_SECRET_KEY= -## Playwright test config (for e2e tests) - +# # Playwright test config (for e2e tests) E2E_BASE_URL=http://localhost:8000 # Docker HUB Proxy (optional) diff --git a/web/crux-ui/locales/en/404.json b/web/crux-ui/locales/en/404.json index f415a46b54..2922f9d99a 100644 --- a/web/crux-ui/locales/en/404.json +++ b/web/crux-ui/locales/en/404.json @@ -1,5 +1,5 @@ { - "oops": "Opps, it's empty in here.", + "oops": "Oops, it's empty in here.", "nothingYet": "Seems like there's nothing in this page yet.", "notFound": "Not found" diff --git a/web/crux-ui/locales/en/errors.json b/web/crux-ui/locales/en/errors.json index 3f925e4e1a..ac8c1b5c05 100644 --- a/web/crux-ui/locales/en/errors.json +++ b/web/crux-ui/locales/en/errors.json @@ -1,5 +1,5 @@ { - "oops": "Opps, something went wrong.", + "oops": "Oops, something went wrong.", "connectionLost": "Connection lost.", "invalid": "There are some errors. Please fix them.", "fetchFailed": "Failed to fetch {{type}}", diff --git a/web/crux-ui/next-env.d.ts b/web/crux-ui/next-env.d.ts index 4f11a03dc6..a4a7b3f5cf 100644 --- a/web/crux-ui/next-env.d.ts +++ b/web/crux-ui/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/web/crux-ui/package.json b/web/crux-ui/package.json index 2ae23b4549..9f5e59d17e 100644 --- a/web/crux-ui/package.json +++ b/web/crux-ui/package.json @@ -22,7 +22,7 @@ "format:win32": "prettier --write \"./**/*.tsx\" \"./**/*.ts\"", "build": "next build", "start": "npm run dev", - "start:prod": "next start", + "start:prod": "node .next/standalone/server.js", "test:e2e": "playwright test", "test:e2e-debug": "DEBUG=1 playwright test --debug", "test": "jest", diff --git a/web/crux-ui/playwright.config.ts b/web/crux-ui/playwright.config.ts index 3a26f30d37..05b575e6e1 100644 --- a/web/crux-ui/playwright.config.ts +++ b/web/crux-ui/playwright.config.ts @@ -31,7 +31,7 @@ const config: PlaywrightTestConfig = { outputDir: path.join(__dirname, 'e2e_results/'), testDir: path.join(__dirname, 'e2e'), webServer: { - command: 'npm run start:prod', + command: '>&2 echo "this should never happen, running UI is expected"', url: BASE_URL, timeout: 60 * 1000, // 1 min reuseExistingServer: true,