*: use new errors handling library
Implement a new error handling library based on pkg/errors. It provides stack saving on wrapping and exports some function to add stack saving also to external errors. It also implements custom zerolog error formatting without adding too much verbosity by just printing the chain error file:line without a full stack trace of every error. * Add a --detailed-errors options to print error with they full chain * Wrap all error returns. Use errors.WithStack to wrap without adding a new messsage and error.Wrap[f] to add a message. * Add golangci-lint wrapcheck to check that external packages errors are wrapped. This won't check that internal packages error are wrapped. But we want also to ensure this case so we'll have to find something else to check also these.
This commit is contained in:
parent
5df9ee19c4
commit
d2b09d854f
|
@ -1,2 +1,25 @@
|
||||||
linters:
|
linters:
|
||||||
enable: errorlint
|
enable:
|
||||||
|
- errorlint
|
||||||
|
- wrapcheck
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
wrapcheck:
|
||||||
|
# An array of strings that specify substrings of signatures to ignore.
|
||||||
|
# If this set, it will override the default set of ignored signatures.
|
||||||
|
# See https://github.com/tomarrell/wrapcheck#configuration for more information.
|
||||||
|
ignoreSigs:
|
||||||
|
- .Errorf(
|
||||||
|
- errors.New(
|
||||||
|
- errors.Unwrap(
|
||||||
|
- .Wrap(
|
||||||
|
- .Wrapf(
|
||||||
|
- .WithMessage(
|
||||||
|
- .WithMessagef(
|
||||||
|
- .WithStack(
|
||||||
|
- .NewDetailedError(
|
||||||
|
ignoreSigRegexps:
|
||||||
|
- \.New.*Error\(
|
||||||
|
ignorePackageGlobs:
|
||||||
|
- encoding/*
|
||||||
|
- github.com/pkg/*
|
||||||
|
|
|
@ -20,19 +20,20 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"agola.io/agola/cmd"
|
"agola.io/agola/cmd"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var token string
|
var token string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cw := zerolog.ConsoleWriter{
|
cw := zerolog.ConsoleWriter{
|
||||||
Out: os.Stderr,
|
Out: os.Stderr,
|
||||||
TimeFormat: time.RFC3339Nano,
|
TimeFormat: time.RFC3339Nano,
|
||||||
|
FormatErrFieldValue: errors.FormatErrFieldValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
zerolog.TimeFieldFormat = time.RFC3339Nano
|
zerolog.TimeFieldFormat = time.RFC3339Nano
|
||||||
|
@ -53,6 +54,9 @@ var cmdAgola = &cobra.Command{
|
||||||
if agolaOpts.debug {
|
if agolaOpts.debug {
|
||||||
log.Logger = log.Level(zerolog.DebugLevel)
|
log.Logger = log.Level(zerolog.DebugLevel)
|
||||||
}
|
}
|
||||||
|
if agolaOpts.detailedErrors {
|
||||||
|
zerolog.ErrorMarshalFunc = errors.ErrorMarshalFunc
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Run: func(c *cobra.Command, args []string) {
|
Run: func(c *cobra.Command, args []string) {
|
||||||
if err := c.Help(); err != nil {
|
if err := c.Help(); err != nil {
|
||||||
|
@ -62,8 +66,9 @@ var cmdAgola = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
type agolaOptions struct {
|
type agolaOptions struct {
|
||||||
gatewayURL string
|
gatewayURL string
|
||||||
debug bool
|
debug bool
|
||||||
|
detailedErrors bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var agolaOpts agolaOptions
|
var agolaOpts agolaOptions
|
||||||
|
@ -84,6 +89,7 @@ func init() {
|
||||||
flags.StringVarP(&agolaOpts.gatewayURL, "gateway-url", "u", gatewayURL, "agola gateway exposed url")
|
flags.StringVarP(&agolaOpts.gatewayURL, "gateway-url", "u", gatewayURL, "agola gateway exposed url")
|
||||||
flags.StringVar(&token, "token", token, "api token")
|
flags.StringVar(&token, "token", token, "api token")
|
||||||
flags.BoolVarP(&agolaOpts.debug, "debug", "d", false, "debug")
|
flags.BoolVarP(&agolaOpts.debug, "debug", "d", false, "debug")
|
||||||
|
flags.BoolVar(&agolaOpts.detailedErrors, "detailed-errors", false, "enabled detailed errors logging")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
|
|
|
@ -17,6 +17,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,11 +34,11 @@ func completionShell(cmd *cobra.Command, args []string, shell string) error {
|
||||||
switch shell {
|
switch shell {
|
||||||
case "bash":
|
case "bash":
|
||||||
if err := cmdAgola.GenBashCompletion(os.Stdout); err != nil {
|
if err := cmdAgola.GenBashCompletion(os.Stdout); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
case "zsh":
|
case "zsh":
|
||||||
if err := cmdAgola.GenZshCompletion(os.Stdout); err != nil {
|
if err := cmdAgola.GenZshCompletion(os.Stdout); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gitsave "agola.io/agola/internal/git-save"
|
gitsave "agola.io/agola/internal/git-save"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
|
@ -32,7 +33,6 @@ import (
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdDirectRunStart = &cobra.Command{
|
var cmdDirectRunStart = &cobra.Command{
|
||||||
|
@ -80,15 +80,15 @@ func parseVariable(variable string) (string, string, error) {
|
||||||
variable = strings.TrimLeftFunc(variable, unicode.IsSpace)
|
variable = strings.TrimLeftFunc(variable, unicode.IsSpace)
|
||||||
arr := strings.SplitN(variable, "=", 2)
|
arr := strings.SplitN(variable, "=", 2)
|
||||||
if len(arr) != 2 {
|
if len(arr) != 2 {
|
||||||
return "", "", fmt.Errorf("invalid variable definition: %s", variable)
|
return "", "", errors.Errorf("invalid variable definition: %s", variable)
|
||||||
}
|
}
|
||||||
varname := arr[0]
|
varname := arr[0]
|
||||||
varvalue := arr[1]
|
varvalue := arr[1]
|
||||||
if varname == "" {
|
if varname == "" {
|
||||||
return "", "", fmt.Errorf("invalid variable definition: %s", variable)
|
return "", "", errors.Errorf("invalid variable definition: %s", variable)
|
||||||
}
|
}
|
||||||
if varvalue == "" {
|
if varvalue == "" {
|
||||||
return "", "", fmt.Errorf("invalid variable definition: %s", variable)
|
return "", "", errors.Errorf("invalid variable definition: %s", variable)
|
||||||
}
|
}
|
||||||
return varname, varvalue, nil
|
return varname, varvalue, nil
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
for _, res := range directRunStartOpts.prRefRegexes {
|
for _, res := range directRunStartOpts.prRefRegexes {
|
||||||
if _, err := regexp.Compile(res); err != nil {
|
if _, err := regexp.Compile(res); err != nil {
|
||||||
return fmt.Errorf("wrong regular expression %q: %w", res, err)
|
return errors.Wrapf(err, "wrong regular expression %q", res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,12 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
branch = ""
|
branch = ""
|
||||||
}
|
}
|
||||||
if set > 1 {
|
if set > 1 {
|
||||||
return fmt.Errorf(`only one of "--branch", "--tag" or "--ref" can be provided`)
|
return errors.Errorf(`only one of "--branch", "--tag" or "--ref" can be provided`)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, _, err := gwclient.GetCurrentUser(context.TODO())
|
user, _, err := gwclient.GetCurrentUser(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
variables := map[string]string{}
|
variables := map[string]string{}
|
||||||
|
@ -142,11 +142,11 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
var err error
|
var err error
|
||||||
data, err = ioutil.ReadFile(varFile)
|
data, err = ioutil.ReadFile(varFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := yaml.Unmarshal(data, &variables); err != nil {
|
if err := yaml.Unmarshal(data, &variables); err != nil {
|
||||||
return errors.Errorf("failed to unmarshal values: %w", err)
|
return errors.Wrapf(err, "failed to unmarshal values")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sgotti) validate variable name
|
// TODO(sgotti) validate variable name
|
||||||
|
@ -155,7 +155,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
for _, variable := range directRunStartOpts.vars {
|
for _, variable := range directRunStartOpts.vars {
|
||||||
varname, varvalue, err := parseVariable(variable)
|
varname, varvalue, err := parseVariable(variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
variables[varname] = varvalue
|
variables[varname] = varvalue
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
if repoUUID == "" {
|
if repoUUID == "" {
|
||||||
repoUUID = uuid.Must(uuid.NewV4()).String()
|
repoUUID = uuid.Must(uuid.NewV4()).String()
|
||||||
if _, err := git.ConfigSet(context.Background(), "agola.repouuid", repoUUID); err != nil {
|
if _, err := git.ConfigSet(context.Background(), "agola.repouuid", repoUUID); err != nil {
|
||||||
return fmt.Errorf("failed to set agola repo uid in git config: %w", err)
|
return errors.Wrapf(err, "failed to set agola repo uid in git config")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
commitSHA, err := gs.Save(message, localBranch)
|
commitSHA, err := gs.Save(message, localBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msgf("pushing branch")
|
log.Info().Msgf("pushing branch")
|
||||||
|
@ -190,15 +190,15 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
// push to a branch with default branch refs "refs/heads/branch"
|
// push to a branch with default branch refs "refs/heads/branch"
|
||||||
if branch != "" {
|
if branch != "" {
|
||||||
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/heads/%s", path.Join(gs.RefsPrefix(), localBranch), branch)); err != nil {
|
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/heads/%s", path.Join(gs.RefsPrefix(), localBranch), branch)); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else if tag != "" {
|
} else if tag != "" {
|
||||||
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/tags/%s", path.Join(gs.RefsPrefix(), localBranch), tag)); err != nil {
|
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/tags/%s", path.Join(gs.RefsPrefix(), localBranch), tag)); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else if ref != "" {
|
} else if ref != "" {
|
||||||
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:%s", path.Join(gs.RefsPrefix(), localBranch), ref)); err != nil {
|
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:%s", path.Join(gs.RefsPrefix(), localBranch), ref)); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
|
||||||
Variables: variables,
|
Variables: variables,
|
||||||
}
|
}
|
||||||
if _, err := gwclient.UserCreateRun(context.TODO(), req); err != nil {
|
if _, err := gwclient.UserCreateRun(context.TODO(), req); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdLogDelete = &cobra.Command{
|
var cmdLogDelete = &cobra.Command{
|
||||||
|
@ -93,7 +93,7 @@ func logDelete(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
run, _, err := gwclient.GetRun(context.TODO(), logDeleteOpts.runid)
|
run, _, err := gwclient.GetRun(context.TODO(), logDeleteOpts.runid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for _, t := range run.Tasks {
|
for _, t := range run.Tasks {
|
||||||
if t.Name == logDeleteOpts.taskname {
|
if t.Name == logDeleteOpts.taskname {
|
||||||
|
|
|
@ -19,12 +19,12 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdLogGet = &cobra.Command{
|
var cmdLogGet = &cobra.Command{
|
||||||
|
@ -102,7 +102,7 @@ func logGet(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
run, _, err := gwclient.GetRun(context.TODO(), logGetOpts.runid)
|
run, _, err := gwclient.GetRun(context.TODO(), logGetOpts.runid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for _, t := range run.Tasks {
|
for _, t := range run.Tasks {
|
||||||
if t.Name == logGetOpts.taskname {
|
if t.Name == logGetOpts.taskname {
|
||||||
|
@ -127,7 +127,7 @@ func logGet(cmd *cobra.Command, args []string) error {
|
||||||
if flags.Changed("output") {
|
if flags.Changed("output") {
|
||||||
f, err := os.Create(logGetOpts.output)
|
f, err := os.Create(logGetOpts.output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
if _, err := io.Copy(f, resp.Body); err != nil {
|
if _, err := io.Copy(f, resp.Body); err != nil {
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdOrgCreate = &cobra.Command{
|
var cmdOrgCreate = &cobra.Command{
|
||||||
|
@ -71,7 +71,7 @@ func orgCreate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("creating org")
|
log.Info().Msgf("creating org")
|
||||||
org, _, err := gwclient.CreateOrg(context.TODO(), req)
|
org, _, err := gwclient.CreateOrg(context.TODO(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create org: %w", err)
|
return errors.Wrapf(err, "failed to create org")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("org %q created, ID: %q", org.Name, org.ID)
|
log.Info().Msgf("org %q created, ID: %q", org.Name, org.ID)
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdOrgDelete = &cobra.Command{
|
var cmdOrgDelete = &cobra.Command{
|
||||||
|
@ -57,7 +57,7 @@ func orgDelete(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
log.Info().Msgf("deleting organization %q", orgDeleteOpts.name)
|
log.Info().Msgf("deleting organization %q", orgDeleteOpts.name)
|
||||||
if _, err := gwclient.DeleteOrg(context.TODO(), orgDeleteOpts.name); err != nil {
|
if _, err := gwclient.DeleteOrg(context.TODO(), orgDeleteOpts.name); err != nil {
|
||||||
return errors.Errorf("failed to delete organization: %w", err)
|
return errors.Wrapf(err, "failed to delete organization")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdOrgMemberAdd = &cobra.Command{
|
var cmdOrgMemberAdd = &cobra.Command{
|
||||||
|
@ -66,7 +66,7 @@ func orgMemberAdd(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("adding/updating member %q to organization %q with role %q", orgMemberAddOpts.username, orgMemberAddOpts.orgname, orgMemberAddOpts.role)
|
log.Info().Msgf("adding/updating member %q to organization %q with role %q", orgMemberAddOpts.username, orgMemberAddOpts.orgname, orgMemberAddOpts.role)
|
||||||
_, _, err := gwclient.AddOrgMember(context.TODO(), orgMemberAddOpts.orgname, orgMemberAddOpts.username, gwapitypes.MemberRole(orgMemberAddOpts.role))
|
_, _, err := gwclient.AddOrgMember(context.TODO(), orgMemberAddOpts.orgname, orgMemberAddOpts.username, gwapitypes.MemberRole(orgMemberAddOpts.role))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to add/update organization member: %w", err)
|
return errors.Wrapf(err, "failed to add/update organization member")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -19,11 +19,11 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdOrgMemberList = &cobra.Command{
|
var cmdOrgMemberList = &cobra.Command{
|
||||||
|
@ -59,12 +59,12 @@ func orgMemberList(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
orgMembers, _, err := gwclient.GetOrgMembers(context.TODO(), orgMemberListOpts.orgname)
|
orgMembers, _, err := gwclient.GetOrgMembers(context.TODO(), orgMemberListOpts.orgname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to get organization member: %w", err)
|
return errors.Wrapf(err, "failed to get organization member")
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := json.MarshalIndent(orgMembers, "", "\t")
|
out, err := json.MarshalIndent(orgMembers, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
os.Stdout.Write(out)
|
os.Stdout.Write(out)
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdOrgMemberRemove = &cobra.Command{
|
var cmdOrgMemberRemove = &cobra.Command{
|
||||||
|
@ -63,7 +63,7 @@ func orgMemberRemove(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("removing member %q from organization %q", orgMemberRemoveOpts.username, orgMemberRemoveOpts.orgname)
|
log.Info().Msgf("removing member %q from organization %q", orgMemberRemoveOpts.username, orgMemberRemoveOpts.orgname)
|
||||||
_, err := gwclient.RemoveOrgMember(context.TODO(), orgMemberRemoveOpts.orgname, orgMemberRemoveOpts.username)
|
_, err := gwclient.RemoveOrgMember(context.TODO(), orgMemberRemoveOpts.orgname, orgMemberRemoveOpts.username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to remove organization member: %w", err)
|
return errors.Wrapf(err, "failed to remove organization member")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectCreate = &cobra.Command{
|
var cmdProjectCreate = &cobra.Command{
|
||||||
|
@ -106,7 +106,7 @@ func projectCreate(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
project, _, err := gwclient.CreateProject(context.TODO(), req)
|
project, _, err := gwclient.CreateProject(context.TODO(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create project: %w", err)
|
return errors.Wrapf(err, "failed to create project")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project %s created, ID: %s", project.Name, project.ID)
|
log.Info().Msgf("project %s created, ID: %s", project.Name, project.ID)
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectDelete = &cobra.Command{
|
var cmdProjectDelete = &cobra.Command{
|
||||||
|
@ -58,7 +58,7 @@ func projectDelete(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("deleting project")
|
log.Info().Msgf("deleting project")
|
||||||
|
|
||||||
if _, err := gwclient.DeleteProject(context.TODO(), projectDeleteOpts.ref); err != nil {
|
if _, err := gwclient.DeleteProject(context.TODO(), projectDeleteOpts.ref); err != nil {
|
||||||
return errors.Errorf("failed to delete project: %w", err)
|
return errors.Wrapf(err, "failed to delete project")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectGroupCreate = &cobra.Command{
|
var cmdProjectGroupCreate = &cobra.Command{
|
||||||
|
@ -78,7 +78,7 @@ func projectGroupCreate(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
projectGroup, _, err := gwclient.CreateProjectGroup(context.TODO(), req)
|
projectGroup, _, err := gwclient.CreateProjectGroup(context.TODO(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create project group: %w", err)
|
return errors.Wrapf(err, "failed to create project group")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group %s created, ID: %s", projectGroup.Name, projectGroup.ID)
|
log.Info().Msgf("project group %s created, ID: %s", projectGroup.Name, projectGroup.ID)
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectGroupDelete = &cobra.Command{
|
var cmdProjectGroupDelete = &cobra.Command{
|
||||||
|
@ -58,7 +58,7 @@ func projectGroupDelete(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("deleting project group")
|
log.Info().Msgf("deleting project group")
|
||||||
|
|
||||||
if _, err := gwclient.DeleteProjectGroup(context.TODO(), projectGroupDeleteOpts.ref); err != nil {
|
if _, err := gwclient.DeleteProjectGroup(context.TODO(), projectGroupDeleteOpts.ref); err != nil {
|
||||||
return errors.Errorf("failed to delete project group: %w", err)
|
return errors.Wrapf(err, "failed to delete project group")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectGroupUpdate = &cobra.Command{
|
var cmdProjectGroupUpdate = &cobra.Command{
|
||||||
|
@ -82,7 +82,7 @@ func projectGroupUpdate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("updating project group")
|
log.Info().Msgf("updating project group")
|
||||||
projectGroup, _, err := gwclient.UpdateProjectGroup(context.TODO(), projectGroupUpdateOpts.ref, req)
|
projectGroup, _, err := gwclient.UpdateProjectGroup(context.TODO(), projectGroupUpdateOpts.ref, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update project group: %w", err)
|
return errors.Wrapf(err, "failed to update project group")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group %s update, ID: %s", projectGroup.Name, projectGroup.ID)
|
log.Info().Msgf("project group %s update, ID: %s", projectGroup.Name, projectGroup.ID)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ func projectList(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
projects, _, err := gwclient.GetProjectGroupProjects(context.TODO(), projectListOpts.parentPath)
|
projects, _, err := gwclient.GetProjectGroupProjects(context.TODO(), projectListOpts.parentPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
printProjects(projects)
|
printProjects(projects)
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectReconfig = &cobra.Command{
|
var cmdProjectReconfig = &cobra.Command{
|
||||||
|
@ -57,7 +57,7 @@ func projectReconfig(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
log.Info().Msgf("reconfiguring remote project")
|
log.Info().Msgf("reconfiguring remote project")
|
||||||
if _, err := gwclient.ReconfigProject(context.TODO(), projectReconfigOpts.name); err != nil {
|
if _, err := gwclient.ReconfigProject(context.TODO(), projectReconfigOpts.name); err != nil {
|
||||||
return errors.Errorf("failed to reconfigure remote project: %w", err)
|
return errors.Wrapf(err, "failed to reconfigure remote project")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project reconfigured")
|
log.Info().Msgf("project reconfigured")
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,13 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectSecretCreate = &cobra.Command{
|
var cmdProjectSecretCreate = &cobra.Command{
|
||||||
|
@ -82,12 +82,12 @@ func secretCreate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
if secretCreateOpts.file == "-" {
|
if secretCreateOpts.file == "-" {
|
||||||
data, err = ioutil.ReadAll(os.Stdin)
|
data, err = ioutil.ReadAll(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data, err = ioutil.ReadFile(secretCreateOpts.file)
|
data, err = ioutil.ReadFile(secretCreateOpts.file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,14 +106,14 @@ func secretCreate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
log.Info().Msgf("creating project secret")
|
log.Info().Msgf("creating project secret")
|
||||||
secret, _, err := gwclient.CreateProjectSecret(context.TODO(), secretCreateOpts.parentRef, req)
|
secret, _, err := gwclient.CreateProjectSecret(context.TODO(), secretCreateOpts.parentRef, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create project secret: %w", err)
|
return errors.Wrapf(err, "failed to create project secret")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project secret %q created, ID: %q", secret.Name, secret.ID)
|
log.Info().Msgf("project secret %q created, ID: %q", secret.Name, secret.ID)
|
||||||
case "projectgroup":
|
case "projectgroup":
|
||||||
log.Info().Msgf("creating project group secret")
|
log.Info().Msgf("creating project group secret")
|
||||||
secret, _, err := gwclient.CreateProjectGroupSecret(context.TODO(), secretCreateOpts.parentRef, req)
|
secret, _, err := gwclient.CreateProjectGroupSecret(context.TODO(), secretCreateOpts.parentRef, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create project group secret: %w", err)
|
return errors.Wrapf(err, "failed to create project group secret")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group secret %q created, ID: %q", secret.Name, secret.ID)
|
log.Info().Msgf("project group secret %q created, ID: %q", secret.Name, secret.ID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectSecretDelete = &cobra.Command{
|
var cmdProjectSecretDelete = &cobra.Command{
|
||||||
|
@ -65,14 +65,14 @@ func secretDelete(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
log.Info().Msgf("deleting project secret")
|
log.Info().Msgf("deleting project secret")
|
||||||
_, err := gwclient.DeleteProjectSecret(context.TODO(), secretDeleteOpts.parentRef, secretDeleteOpts.name)
|
_, err := gwclient.DeleteProjectSecret(context.TODO(), secretDeleteOpts.parentRef, secretDeleteOpts.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to delete project secret: %w", err)
|
return errors.Wrapf(err, "failed to delete project secret")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project secret deleted")
|
log.Info().Msgf("project secret deleted")
|
||||||
case "projectgroup":
|
case "projectgroup":
|
||||||
log.Info().Msgf("deleting project group secret")
|
log.Info().Msgf("deleting project group secret")
|
||||||
_, err := gwclient.DeleteProjectGroupSecret(context.TODO(), secretDeleteOpts.parentRef, secretDeleteOpts.name)
|
_, err := gwclient.DeleteProjectGroupSecret(context.TODO(), secretDeleteOpts.parentRef, secretDeleteOpts.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to delete project group secret: %w", err)
|
return errors.Wrapf(err, "failed to delete project group secret")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group secret deleted")
|
log.Info().Msgf("project group secret deleted")
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectSecretList = &cobra.Command{
|
var cmdProjectSecretList = &cobra.Command{
|
||||||
|
@ -57,10 +57,10 @@ func init() {
|
||||||
|
|
||||||
func secretList(cmd *cobra.Command, ownertype string, args []string) error {
|
func secretList(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
if err := printSecrets(ownertype, fmt.Sprintf("%s secrets", ownertype), false, false); err != nil {
|
if err := printSecrets(ownertype, fmt.Sprintf("%s secrets", ownertype), false, false); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := printSecrets(ownertype, "All secrets (local and inherited)", true, true); err != nil {
|
if err := printSecrets(ownertype, "All secrets (local and inherited)", true, true); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -79,11 +79,11 @@ func printSecrets(ownertype, description string, tree, removeoverridden bool) er
|
||||||
secrets, _, err = gwclient.GetProjectGroupSecrets(context.TODO(), secretListOpts.parentRef, tree, removeoverridden)
|
secrets, _, err = gwclient.GetProjectGroupSecrets(context.TODO(), secretListOpts.parentRef, tree, removeoverridden)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to list %s secrets: %w", ownertype, err)
|
return errors.Wrapf(err, "failed to list %s secrets", ownertype)
|
||||||
}
|
}
|
||||||
prettyJSON, err := json.MarshalIndent(secrets, "", "\t")
|
prettyJSON, err := json.MarshalIndent(secrets, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to convert %s secrets to json: %w", ownertype, err)
|
return errors.Wrapf(err, "failed to convert %s secrets to json", ownertype)
|
||||||
}
|
}
|
||||||
fmt.Printf("%s:\n%s\n", description, string(prettyJSON))
|
fmt.Printf("%s:\n%s\n", description, string(prettyJSON))
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -19,13 +19,13 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectSecretUpdate = &cobra.Command{
|
var cmdProjectSecretUpdate = &cobra.Command{
|
||||||
|
@ -84,12 +84,12 @@ func secretUpdate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
if secretUpdateOpts.file == "-" {
|
if secretUpdateOpts.file == "-" {
|
||||||
data, err = ioutil.ReadAll(os.Stdin)
|
data, err = ioutil.ReadAll(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data, err = ioutil.ReadFile(secretUpdateOpts.file)
|
data, err = ioutil.ReadFile(secretUpdateOpts.file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +113,14 @@ func secretUpdate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
log.Info().Msgf("creating project secret")
|
log.Info().Msgf("creating project secret")
|
||||||
secret, _, err := gwclient.UpdateProjectSecret(context.TODO(), secretUpdateOpts.parentRef, secretUpdateOpts.name, req)
|
secret, _, err := gwclient.UpdateProjectSecret(context.TODO(), secretUpdateOpts.parentRef, secretUpdateOpts.name, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update project secret: %w", err)
|
return errors.Wrapf(err, "failed to update project secret")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project secret %q updated, ID: %q", secret.Name, secret.ID)
|
log.Info().Msgf("project secret %q updated, ID: %q", secret.Name, secret.ID)
|
||||||
case "projectgroup":
|
case "projectgroup":
|
||||||
log.Info().Msgf("creating project group secret")
|
log.Info().Msgf("creating project group secret")
|
||||||
secret, _, err := gwclient.UpdateProjectGroupSecret(context.TODO(), secretUpdateOpts.parentRef, secretUpdateOpts.name, req)
|
secret, _, err := gwclient.UpdateProjectGroupSecret(context.TODO(), secretUpdateOpts.parentRef, secretUpdateOpts.name, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update project group secret: %w", err)
|
return errors.Wrapf(err, "failed to update project group secret")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group secret %q updated, ID: %q", secret.Name, secret.ID)
|
log.Info().Msgf("project group secret %q updated, ID: %q", secret.Name, secret.ID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectUpdate = &cobra.Command{
|
var cmdProjectUpdate = &cobra.Command{
|
||||||
|
@ -88,7 +88,7 @@ func projectUpdate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("updating project")
|
log.Info().Msgf("updating project")
|
||||||
project, _, err := gwclient.UpdateProject(context.TODO(), projectUpdateOpts.ref, req)
|
project, _, err := gwclient.UpdateProject(context.TODO(), projectUpdateOpts.ref, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update project: %w", err)
|
return errors.Wrapf(err, "failed to update project")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project %s update, ID: %s", project.Name, project.ID)
|
log.Info().Msgf("project %s update, ID: %s", project.Name, project.ID)
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
config "agola.io/agola/internal/config"
|
config "agola.io/agola/internal/config"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectVariableCreate = &cobra.Command{
|
var cmdProjectVariableCreate = &cobra.Command{
|
||||||
|
@ -105,12 +105,12 @@ func variableCreate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
if variableCreateOpts.file == "-" {
|
if variableCreateOpts.file == "-" {
|
||||||
data, err = ioutil.ReadAll(os.Stdin)
|
data, err = ioutil.ReadAll(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data, err = ioutil.ReadFile(variableCreateOpts.file)
|
data, err = ioutil.ReadFile(variableCreateOpts.file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,14 +136,14 @@ func variableCreate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
log.Info().Msgf("creating project variable")
|
log.Info().Msgf("creating project variable")
|
||||||
variable, _, err := gwclient.CreateProjectVariable(context.TODO(), variableCreateOpts.parentRef, req)
|
variable, _, err := gwclient.CreateProjectVariable(context.TODO(), variableCreateOpts.parentRef, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create project variable: %w", err)
|
return errors.Wrapf(err, "failed to create project variable")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project variable %q created, ID: %q", variable.Name, variable.ID)
|
log.Info().Msgf("project variable %q created, ID: %q", variable.Name, variable.ID)
|
||||||
case "projectgroup":
|
case "projectgroup":
|
||||||
log.Info().Msgf("creating project group variable")
|
log.Info().Msgf("creating project group variable")
|
||||||
variable, _, err := gwclient.CreateProjectGroupVariable(context.TODO(), variableCreateOpts.parentRef, req)
|
variable, _, err := gwclient.CreateProjectGroupVariable(context.TODO(), variableCreateOpts.parentRef, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create project group variable: %w", err)
|
return errors.Wrapf(err, "failed to create project group variable")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group variable %q created, ID: %q", variable.Name, variable.ID)
|
log.Info().Msgf("project group variable %q created, ID: %q", variable.Name, variable.ID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectVariableDelete = &cobra.Command{
|
var cmdProjectVariableDelete = &cobra.Command{
|
||||||
|
@ -65,14 +65,14 @@ func variableDelete(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
log.Info().Msgf("deleting project variable")
|
log.Info().Msgf("deleting project variable")
|
||||||
_, err := gwclient.DeleteProjectVariable(context.TODO(), variableDeleteOpts.parentRef, variableDeleteOpts.name)
|
_, err := gwclient.DeleteProjectVariable(context.TODO(), variableDeleteOpts.parentRef, variableDeleteOpts.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to delete project variable: %w", err)
|
return errors.Wrapf(err, "failed to delete project variable")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project variable deleted")
|
log.Info().Msgf("project variable deleted")
|
||||||
case "projectgroup":
|
case "projectgroup":
|
||||||
log.Info().Msgf("deleting project group variable")
|
log.Info().Msgf("deleting project group variable")
|
||||||
_, err := gwclient.DeleteProjectGroupVariable(context.TODO(), variableDeleteOpts.parentRef, variableDeleteOpts.name)
|
_, err := gwclient.DeleteProjectGroupVariable(context.TODO(), variableDeleteOpts.parentRef, variableDeleteOpts.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to delete project group variable: %w", err)
|
return errors.Wrapf(err, "failed to delete project group variable")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group variable deleted")
|
log.Info().Msgf("project group variable deleted")
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectVariableList = &cobra.Command{
|
var cmdProjectVariableList = &cobra.Command{
|
||||||
|
@ -57,10 +57,10 @@ func init() {
|
||||||
|
|
||||||
func variableList(cmd *cobra.Command, ownertype string, args []string) error {
|
func variableList(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
if err := printVariables(ownertype, fmt.Sprintf("%s variables", ownertype), false, false); err != nil {
|
if err := printVariables(ownertype, fmt.Sprintf("%s variables", ownertype), false, false); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := printVariables(ownertype, "All variables (local and inherited)", true, true); err != nil {
|
if err := printVariables(ownertype, "All variables (local and inherited)", true, true); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -79,11 +79,11 @@ func printVariables(ownertype, description string, tree, removeoverridden bool)
|
||||||
variables, _, err = gwclient.GetProjectGroupVariables(context.TODO(), variableListOpts.parentRef, tree, removeoverridden)
|
variables, _, err = gwclient.GetProjectGroupVariables(context.TODO(), variableListOpts.parentRef, tree, removeoverridden)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to list %s variables: %w", ownertype, err)
|
return errors.Wrapf(err, "failed to list %s variables", ownertype)
|
||||||
}
|
}
|
||||||
prettyJSON, err := json.MarshalIndent(variables, "", "\t")
|
prettyJSON, err := json.MarshalIndent(variables, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to convert %s variables to json: %w", ownertype, err)
|
return errors.Wrapf(err, "failed to convert %s variables to json", ownertype)
|
||||||
}
|
}
|
||||||
fmt.Printf("%s:\n%s\n", description, string(prettyJSON))
|
fmt.Printf("%s:\n%s\n", description, string(prettyJSON))
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -19,13 +19,13 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdProjectVariableUpdate = &cobra.Command{
|
var cmdProjectVariableUpdate = &cobra.Command{
|
||||||
|
@ -77,12 +77,12 @@ func variableUpdate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
if variableUpdateOpts.file == "-" {
|
if variableUpdateOpts.file == "-" {
|
||||||
data, err = ioutil.ReadAll(os.Stdin)
|
data, err = ioutil.ReadAll(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data, err = ioutil.ReadFile(variableUpdateOpts.file)
|
data, err = ioutil.ReadFile(variableUpdateOpts.file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +113,14 @@ func variableUpdate(cmd *cobra.Command, ownertype string, args []string) error {
|
||||||
log.Info().Msgf("updating project variable")
|
log.Info().Msgf("updating project variable")
|
||||||
variable, _, err := gwclient.UpdateProjectVariable(context.TODO(), variableUpdateOpts.parentRef, variableUpdateOpts.name, req)
|
variable, _, err := gwclient.UpdateProjectVariable(context.TODO(), variableUpdateOpts.parentRef, variableUpdateOpts.name, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update project variable: %w", err)
|
return errors.Wrapf(err, "failed to update project variable")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project variable %q updated, ID: %q", variable.Name, variable.ID)
|
log.Info().Msgf("project variable %q updated, ID: %q", variable.Name, variable.ID)
|
||||||
case "projectgroup":
|
case "projectgroup":
|
||||||
log.Info().Msgf("updating project group variable")
|
log.Info().Msgf("updating project group variable")
|
||||||
variable, _, err := gwclient.UpdateProjectGroupVariable(context.TODO(), variableUpdateOpts.parentRef, variableUpdateOpts.name, req)
|
variable, _, err := gwclient.UpdateProjectGroupVariable(context.TODO(), variableUpdateOpts.parentRef, variableUpdateOpts.name, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update project group variable: %w", err)
|
return errors.Wrapf(err, "failed to update project group variable")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("project group variable %q updated, ID: %q", variable.Name, variable.ID)
|
log.Info().Msgf("project group variable %q updated, ID: %q", variable.Name, variable.ID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/gitsources/github"
|
"agola.io/agola/internal/gitsources/github"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
@ -24,7 +25,6 @@ import (
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRemoteSourceCreate = &cobra.Command{
|
var cmdRemoteSourceCreate = &cobra.Command{
|
||||||
|
@ -117,7 +117,7 @@ func remoteSourceCreate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("creating remotesource")
|
log.Info().Msgf("creating remotesource")
|
||||||
remoteSource, _, err := gwclient.CreateRemoteSource(context.TODO(), req)
|
remoteSource, _, err := gwclient.CreateRemoteSource(context.TODO(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create remotesource: %w", err)
|
return errors.Wrapf(err, "failed to create remotesource")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("remotesource %s created, ID: %s", remoteSource.Name, remoteSource.ID)
|
log.Info().Msgf("remotesource %s created, ID: %s", remoteSource.Name, remoteSource.ID)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ func remoteSourceList(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
remouteSources, _, err := gwclient.GetRemoteSources(context.TODO(), remoteSourceListOpts.start, remoteSourceListOpts.limit, false)
|
remouteSources, _, err := gwclient.GetRemoteSources(context.TODO(), remoteSourceListOpts.start, remoteSourceListOpts.limit, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
printRemoteSources(remouteSources)
|
printRemoteSources(remouteSources)
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRemoteSourceUpdate = &cobra.Command{
|
var cmdRemoteSourceUpdate = &cobra.Command{
|
||||||
|
@ -109,7 +109,7 @@ func remoteSourceUpdate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("updating remotesource")
|
log.Info().Msgf("updating remotesource")
|
||||||
remoteSource, _, err := gwclient.UpdateRemoteSource(context.TODO(), remoteSourceUpdateOpts.ref, req)
|
remoteSource, _, err := gwclient.UpdateRemoteSource(context.TODO(), remoteSourceUpdateOpts.ref, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to update remotesource: %w", err)
|
return errors.Wrapf(err, "failed to update remotesource")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("remotesource %s updated, ID: %s", remoteSource.Name, remoteSource.ID)
|
log.Info().Msgf("remotesource %s updated, ID: %s", remoteSource.Name, remoteSource.ID)
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func runCreate(cmd *cobra.Command, args []string) error {
|
||||||
set++
|
set++
|
||||||
}
|
}
|
||||||
if set != 1 {
|
if set != 1 {
|
||||||
return fmt.Errorf(`one of "--branch", "--tag" or "--ref" must be provided`)
|
return errors.Errorf(`one of "--branch", "--tag" or "--ref" must be provided`)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &gwapitypes.ProjectCreateRunRequest{
|
req := &gwapitypes.ProjectCreateRunRequest{
|
||||||
|
@ -88,5 +88,5 @@ func runCreate(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
_, err := gwclient.ProjectCreateRun(context.TODO(), runCreateOpts.projectRef, req)
|
_, err := gwclient.ProjectCreateRun(context.TODO(), runCreateOpts.projectRef, req)
|
||||||
|
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -104,14 +104,14 @@ func runList(cmd *cobra.Command, args []string) error {
|
||||||
groups := []string{path.Join("/project", project.ID)}
|
groups := []string{path.Join("/project", project.ID)}
|
||||||
runsResp, _, err := gwclient.GetRuns(context.TODO(), runListOpts.phaseFilter, nil, groups, nil, runListOpts.start, runListOpts.limit, false)
|
runsResp, _, err := gwclient.GetRuns(context.TODO(), runListOpts.phaseFilter, nil, groups, nil, runListOpts.start, runListOpts.limit, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
runs := make([]*runDetails, len(runsResp))
|
runs := make([]*runDetails, len(runsResp))
|
||||||
for i, runResponse := range runsResp {
|
for i, runResponse := range runsResp {
|
||||||
run, _, err := gwclient.GetRun(context.TODO(), runResponse.ID)
|
run, _, err := gwclient.GetRun(context.TODO(), runResponse.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks := []*taskDetails{}
|
tasks := []*taskDetails{}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"agola.io/agola/cmd"
|
"agola.io/agola/cmd"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/services/config"
|
"agola.io/agola/internal/services/config"
|
||||||
"agola.io/agola/internal/services/configstore"
|
"agola.io/agola/internal/services/configstore"
|
||||||
"agola.io/agola/internal/services/executor"
|
"agola.io/agola/internal/services/executor"
|
||||||
|
@ -33,7 +34,6 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.etcd.io/etcd/embed"
|
"go.etcd.io/etcd/embed"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -96,7 +96,7 @@ func embeddedEtcd(ctx context.Context) error {
|
||||||
log.Info().Msgf("starting embedded etcd server")
|
log.Info().Msgf("starting embedded etcd server")
|
||||||
e, err := embed.StartEtcd(cfg)
|
e, err := embed.StartEtcd(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -132,12 +132,12 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
c, err := config.Parse(serveOpts.config, serveOpts.components)
|
c, err := config.Parse(serveOpts.config, serveOpts.components)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("config error: %w", err)
|
return errors.Wrapf(err, "config error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if serveOpts.embeddedEtcd {
|
if serveOpts.embeddedEtcd {
|
||||||
if err := embeddedEtcd(ctx); err != nil {
|
if err := embeddedEtcd(ctx); err != nil {
|
||||||
return errors.Errorf("failed to start run service scheduler: %w", err)
|
return errors.Wrapf(err, "failed to start run service scheduler")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("runservice") {
|
if isComponentEnabled("runservice") {
|
||||||
rs, err = rsscheduler.NewRunservice(ctx, log.Logger, &c.Runservice)
|
rs, err = rsscheduler.NewRunservice(ctx, log.Logger, &c.Runservice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start run service scheduler: %w", err)
|
return errors.Wrapf(err, "failed to start run service scheduler")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("executor") {
|
if isComponentEnabled("executor") {
|
||||||
ex, err = executor.NewExecutor(ctx, log.Logger, &c.Executor)
|
ex, err = executor.NewExecutor(ctx, log.Logger, &c.Executor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start run service executor: %w", err)
|
return errors.Wrapf(err, "failed to start run service executor")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("configstore") {
|
if isComponentEnabled("configstore") {
|
||||||
cs, err = configstore.NewConfigstore(ctx, log.Logger, &c.Configstore)
|
cs, err = configstore.NewConfigstore(ctx, log.Logger, &c.Configstore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start config store: %w", err)
|
return errors.Wrapf(err, "failed to start config store")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("scheduler") {
|
if isComponentEnabled("scheduler") {
|
||||||
sched, err = scheduler.NewScheduler(ctx, log.Logger, &c.Scheduler)
|
sched, err = scheduler.NewScheduler(ctx, log.Logger, &c.Scheduler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start scheduler: %w", err)
|
return errors.Wrapf(err, "failed to start scheduler")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("notification") {
|
if isComponentEnabled("notification") {
|
||||||
ns, err = notification.NewNotificationService(ctx, log.Logger, c)
|
ns, err = notification.NewNotificationService(ctx, log.Logger, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start notification service: %w", err)
|
return errors.Wrapf(err, "failed to start notification service")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("gateway") {
|
if isComponentEnabled("gateway") {
|
||||||
gw, err = gateway.NewGateway(ctx, log.Logger, c)
|
gw, err = gateway.NewGateway(ctx, log.Logger, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start gateway: %w", err)
|
return errors.Wrapf(err, "failed to start gateway")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||||
if isComponentEnabled("gitserver") {
|
if isComponentEnabled("gitserver") {
|
||||||
gs, err = gitserver.NewGitserver(ctx, log.Logger, &c.Gitserver)
|
gs, err = gitserver.NewGitserver(ctx, log.Logger, &c.Gitserver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to start git server: %w", err)
|
return errors.Wrapf(err, "failed to start git server")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUserCreate = &cobra.Command{
|
var cmdUserCreate = &cobra.Command{
|
||||||
|
@ -63,7 +63,7 @@ func userCreate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("creating user")
|
log.Info().Msgf("creating user")
|
||||||
user, _, err := gwclient.CreateUser(context.TODO(), req)
|
user, _, err := gwclient.CreateUser(context.TODO(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create user: %w", err)
|
return errors.Wrapf(err, "failed to create user")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("user %q created, ID: %q", user.UserName, user.ID)
|
log.Info().Msgf("user %q created, ID: %q", user.UserName, user.ID)
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUserDelete = &cobra.Command{
|
var cmdUserDelete = &cobra.Command{
|
||||||
|
@ -57,7 +57,7 @@ func userDelete(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
log.Info().Msgf("deleting user %q", userDeleteOpts.username)
|
log.Info().Msgf("deleting user %q", userDeleteOpts.username)
|
||||||
if _, err := gwclient.DeleteUser(context.TODO(), userDeleteOpts.username); err != nil {
|
if _, err := gwclient.DeleteUser(context.TODO(), userDeleteOpts.username); err != nil {
|
||||||
return errors.Errorf("failed to delete user: %w", err)
|
return errors.Wrapf(err, "failed to delete user")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,12 +17,12 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUserLACreate = &cobra.Command{
|
var cmdUserLACreate = &cobra.Command{
|
||||||
|
@ -74,7 +74,7 @@ func userLACreate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("creating linked account for user %q", userLACreateOpts.username)
|
log.Info().Msgf("creating linked account for user %q", userLACreateOpts.username)
|
||||||
resp, _, err := gwclient.CreateUserLA(context.TODO(), userLACreateOpts.username, req)
|
resp, _, err := gwclient.CreateUserLA(context.TODO(), userLACreateOpts.username, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create linked account: %w", err)
|
return errors.Wrapf(err, "failed to create linked account")
|
||||||
}
|
}
|
||||||
if resp.Oauth2Redirect != "" {
|
if resp.Oauth2Redirect != "" {
|
||||||
log.Info().Msgf("visit %s to continue", resp.Oauth2Redirect)
|
log.Info().Msgf("visit %s to continue", resp.Oauth2Redirect)
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUserLADelete = &cobra.Command{
|
var cmdUserLADelete = &cobra.Command{
|
||||||
|
@ -66,7 +66,7 @@ func userLADelete(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("deleting linked account %q for user %q", laID, userName)
|
log.Info().Msgf("deleting linked account %q for user %q", laID, userName)
|
||||||
_, err := gwclient.DeleteUserLA(context.TODO(), userName, laID)
|
_, err := gwclient.DeleteUserLA(context.TODO(), userName, laID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to delete linked account: %w", err)
|
return errors.Wrapf(err, "failed to delete linked account")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msgf("linked account %q for user %q deleted", laID, userName)
|
log.Info().Msgf("linked account %q for user %q deleted", laID, userName)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ func userList(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
users, _, err := gwclient.GetUsers(context.TODO(), userListOpts.start, userListOpts.limit, false)
|
users, _, err := gwclient.GetUsers(context.TODO(), userListOpts.start, userListOpts.limit, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
printUsers(users)
|
printUsers(users)
|
||||||
|
|
|
@ -18,12 +18,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUserTokenCreate = &cobra.Command{
|
var cmdUserTokenCreate = &cobra.Command{
|
||||||
|
@ -69,7 +69,7 @@ func userTokenCreate(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("creating token for user %q", userTokenCreateOpts.username)
|
log.Info().Msgf("creating token for user %q", userTokenCreateOpts.username)
|
||||||
resp, _, err := gwclient.CreateUserToken(context.TODO(), userTokenCreateOpts.username, req)
|
resp, _, err := gwclient.CreateUserToken(context.TODO(), userTokenCreateOpts.username, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to create token: %w", err)
|
return errors.Wrapf(err, "failed to create token")
|
||||||
}
|
}
|
||||||
log.Info().Msgf("token for user %q created: %s", userTokenCreateOpts.username, resp.Token)
|
log.Info().Msgf("token for user %q created: %s", userTokenCreateOpts.username, resp.Token)
|
||||||
fmt.Println(resp.Token)
|
fmt.Println(resp.Token)
|
||||||
|
|
|
@ -17,11 +17,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUserTokenDelete = &cobra.Command{
|
var cmdUserTokenDelete = &cobra.Command{
|
||||||
|
@ -66,7 +66,7 @@ func userTokenDelete(cmd *cobra.Command, args []string) error {
|
||||||
log.Info().Msgf("deleting token %q for user %q", tokenName, userName)
|
log.Info().Msgf("deleting token %q for user %q", tokenName, userName)
|
||||||
_, err := gwclient.DeleteUserToken(context.TODO(), userName, tokenName)
|
_, err := gwclient.DeleteUserToken(context.TODO(), userName, tokenName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to delete user token: %w", err)
|
return errors.Wrapf(err, "failed to delete user token")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msgf("token %q for user %q deleted", tokenName, userName)
|
log.Info().Msgf("token %q for user %q deleted", tokenName, userName)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gwclient "agola.io/agola/services/gateway/client"
|
gwclient "agola.io/agola/services/gateway/client"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
@ -43,7 +44,7 @@ func printVersions(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
gwversion, _, err := gwclient.GetVersion(context.TODO())
|
gwversion, _, err := gwclient.GetVersion(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Gateway version:\t%s\n", gwversion.Version)
|
fmt.Printf("Gateway version:\t%s\n", gwversion.Version)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,18 +49,18 @@ func createFile(r io.Reader) (string, error) {
|
||||||
// create a temp dir if the image doesn't have one
|
// create a temp dir if the image doesn't have one
|
||||||
tmpDir := os.TempDir()
|
tmpDir := os.TempDir()
|
||||||
if err := os.MkdirAll(tmpDir, 0777); err != nil {
|
if err := os.MkdirAll(tmpDir, 0777); err != nil {
|
||||||
return "", fmt.Errorf("failed to create tmp dir %q", tmpDir)
|
return "", errors.Errorf("failed to create tmp dir %q", tmpDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := ioutil.TempFile("", "")
|
file, err := ioutil.TempFile("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := file.Name()
|
filename := file.Name()
|
||||||
if _, err := io.Copy(file, r); err != nil {
|
if _, err := io.Copy(file, r); err != nil {
|
||||||
file.Close()
|
file.Close()
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -28,6 +27,8 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,20 +49,20 @@ func md5sum(filename string) (string, error) {
|
||||||
|
|
||||||
if info, err := os.Stat(filename); err == nil {
|
if info, err := os.Stat(filename); err == nil {
|
||||||
if info.Size() > 1024*1024 {
|
if info.Size() > 1024*1024 {
|
||||||
return "", fmt.Errorf("file %q is too big", filename)
|
return "", errors.Errorf("file %q is too big", filename)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(filename)
|
f, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
if _, err := io.Copy(h, f); err != nil {
|
if _, err := io.Copy(h, f); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
||||||
|
@ -74,20 +75,20 @@ func sha256sum(filename string) (string, error) {
|
||||||
|
|
||||||
if info, err := os.Stat(filename); err == nil {
|
if info, err := os.Stat(filename); err == nil {
|
||||||
if info.Size() > 1024*1024 {
|
if info.Size() > 1024*1024 {
|
||||||
return "", fmt.Errorf("file %q is too big", filename)
|
return "", errors.Errorf("file %q is too big", filename)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(filename)
|
f, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
if _, err := io.Copy(h, f); err != nil {
|
if _, err := io.Copy(h, f); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
||||||
|
|
10
doc/devel.md
10
doc/devel.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#### Start the web interface
|
#### Start the web interface
|
||||||
|
|
||||||
* Clone the [agola-web repository](https://github.com/agola-io/agola-web)
|
- Clone the [agola-web repository](https://github.com/agola-io/agola-web)
|
||||||
|
|
||||||
For the first time you'll need the `vue cli` and its services installed as global modules:
|
For the first time you'll need the `vue cli` and its services installed as global modules:
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ make
|
||||||
|
|
||||||
### Start the agola server
|
### Start the agola server
|
||||||
|
|
||||||
* Copy the `example/config.yml` where you prefer
|
- Copy the `example/config.yml` where you prefer
|
||||||
|
|
||||||
```
|
```
|
||||||
./bin/agola serve --embedded-etcd --config /path/to/your/config.yml --components all-base,executor
|
./bin/agola serve --embedded-etcd --config /path/to/your/config.yml --components all-base,executor
|
||||||
|
@ -38,3 +38,9 @@ or use an external etcd (set it in the config.yml):
|
||||||
```
|
```
|
||||||
./bin/agola serve --config /path/to/your/config.yml --components all-base,executor
|
./bin/agola serve --config /path/to/your/config.yml --components all-base,executor
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error handling
|
||||||
|
|
||||||
|
Use the `--detailed-errors` option to easily follow the errors chain.
|
||||||
|
|
||||||
|
When developing you should wrap every error using `errors.Wrap[f]` or `errors.WithStack`. The ci uses `golangci-lint` with the `wrapcheck` linter enabled to check if some errors aren't wrapped.
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -35,7 +35,6 @@ require (
|
||||||
go.starlark.net v0.0.0-20200203144150-6677ee5c7211
|
go.starlark.net v0.0.0-20200203144150-6677ee5c7211
|
||||||
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e
|
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
|
||||||
gopkg.in/src-d/go-billy.v4 v4.3.2
|
gopkg.in/src-d/go-billy.v4 v4.3.2
|
||||||
gopkg.in/src-d/go-git.v4 v4.13.1
|
gopkg.in/src-d/go-git.v4 v4.13.1
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
|
|
|
@ -21,12 +21,12 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
"agola.io/agola/internal/objectstorage"
|
"agola.io/agola/internal/objectstorage"
|
||||||
"agola.io/agola/internal/services/config"
|
"agola.io/agola/internal/services/config"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -43,7 +43,7 @@ func WriteFileAtomicFunc(filename string, perm os.FileMode, writeFunc func(f io.
|
||||||
dir, name := path.Split(filename)
|
dir, name := path.Split(filename)
|
||||||
f, err := ioutil.TempFile(dir, name)
|
f, err := ioutil.TempFile(dir, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
err = writeFunc(f)
|
err = writeFunc(f)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -62,7 +62,7 @@ func WriteFileAtomicFunc(filename string, perm os.FileMode, writeFunc func(f io.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(f.Name())
|
os.Remove(f.Name())
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteFileAtomic atomically writes a file
|
// WriteFileAtomic atomically writes a file
|
||||||
|
@ -70,7 +70,7 @@ func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
|
||||||
return WriteFileAtomicFunc(filename, perm,
|
return WriteFileAtomicFunc(filename, perm,
|
||||||
func(f io.Writer) error {
|
func(f io.Writer) error {
|
||||||
_, err := f.Write(data)
|
_, err := f.Write(data)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ func NewObjectStorage(c *config.ObjectStorage) (*objectstorage.ObjStorage, error
|
||||||
case config.ObjectStorageTypePosix:
|
case config.ObjectStorageTypePosix:
|
||||||
ost, err = objectstorage.NewPosix(c.Path)
|
ost, err = objectstorage.NewPosix(c.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to create posix object storage: %w", err)
|
return nil, errors.Wrapf(err, "failed to create posix object storage")
|
||||||
}
|
}
|
||||||
case config.ObjectStorageTypeS3:
|
case config.ObjectStorageTypeS3:
|
||||||
// minio golang client doesn't accept an url as an endpoint
|
// minio golang client doesn't accept an url as an endpoint
|
||||||
|
@ -103,7 +103,7 @@ func NewObjectStorage(c *config.ObjectStorage) (*objectstorage.ObjStorage, error
|
||||||
}
|
}
|
||||||
ost, err = objectstorage.NewS3(c.Bucket, c.Location, endpoint, c.AccessKey, c.SecretAccessKey, secure)
|
ost, err = objectstorage.NewS3(c.Bucket, c.Location, endpoint, c.AccessKey, c.SecretAccessKey, secure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to create s3 object storage: %w", err)
|
return nil, errors.Wrapf(err, "failed to create s3 object storage")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ func NewEtcd(c *config.Etcd, log zerolog.Logger, prefix string) (*etcd.Store, er
|
||||||
SkipTLSVerify: c.TLSSkipVerify,
|
SkipTLSVerify: c.TLSSkipVerify,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to create etcd store: %w", err)
|
return nil, errors.Wrapf(err, "failed to create etcd store")
|
||||||
}
|
}
|
||||||
|
|
||||||
return e, nil
|
return e, nil
|
||||||
|
|
|
@ -20,12 +20,12 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
itypes "agola.io/agola/internal/services/types"
|
itypes "agola.io/agola/internal/services/types"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/types"
|
"agola.io/agola/services/types"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ type SaveContent struct {
|
||||||
func (s *Steps) UnmarshalJSON(b []byte) error {
|
func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
var stepsRaw []json.RawMessage
|
var stepsRaw []json.RawMessage
|
||||||
if err := json.Unmarshal(b, &stepsRaw); err != nil {
|
if err := json.Unmarshal(b, &stepsRaw); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
steps := make(Steps, len(stepsRaw))
|
steps := make(Steps, len(stepsRaw))
|
||||||
|
@ -210,13 +210,13 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
|
|
||||||
var stepMap map[string]json.RawMessage
|
var stepMap map[string]json.RawMessage
|
||||||
if err := json.Unmarshal(stepRaw, &stepMap); err != nil {
|
if err := json.Unmarshal(stepRaw, &stepMap); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// handle default step definition using format { type: "steptype", other steps fields }
|
// handle default step definition using format { type: "steptype", other steps fields }
|
||||||
if _, ok := stepMap["type"]; ok {
|
if _, ok := stepMap["type"]; ok {
|
||||||
var stepTypeI interface{}
|
var stepTypeI interface{}
|
||||||
if err := json.Unmarshal(stepMap["type"], &stepTypeI); err != nil {
|
if err := json.Unmarshal(stepMap["type"], &stepTypeI); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
stepType, ok := stepTypeI.(string)
|
stepType, ok := stepTypeI.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -227,7 +227,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "clone":
|
case "clone":
|
||||||
var s CloneStep
|
var s CloneStep
|
||||||
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -235,7 +235,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "run":
|
case "run":
|
||||||
var s RunStep
|
var s RunStep
|
||||||
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if s.Tty == nil {
|
if s.Tty == nil {
|
||||||
s.Tty = util.BoolP(true)
|
s.Tty = util.BoolP(true)
|
||||||
|
@ -246,7 +246,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "save_to_workspace":
|
case "save_to_workspace":
|
||||||
var s SaveToWorkspaceStep
|
var s SaveToWorkspaceStep
|
||||||
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -254,7 +254,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "restore_workspace":
|
case "restore_workspace":
|
||||||
var s RestoreWorkspaceStep
|
var s RestoreWorkspaceStep
|
||||||
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -262,7 +262,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "save_cache":
|
case "save_cache":
|
||||||
var s SaveCacheStep
|
var s SaveCacheStep
|
||||||
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -270,7 +270,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "restore_cache":
|
case "restore_cache":
|
||||||
var s RestoreCacheStep
|
var s RestoreCacheStep
|
||||||
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
if err := json.Unmarshal(stepRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -285,14 +285,14 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
for stepType, stepSpecRaw := range stepMap {
|
for stepType, stepSpecRaw := range stepMap {
|
||||||
var stepSpec interface{}
|
var stepSpec interface{}
|
||||||
if err := json.Unmarshal(stepSpecRaw, &stepSpec); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &stepSpec); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch stepType {
|
switch stepType {
|
||||||
case "clone":
|
case "clone":
|
||||||
var s CloneStep
|
var s CloneStep
|
||||||
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -304,7 +304,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
s.Command = stepSpec
|
s.Command = stepSpec
|
||||||
default:
|
default:
|
||||||
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
|
@ -313,7 +313,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "save_to_workspace":
|
case "save_to_workspace":
|
||||||
var s SaveToWorkspaceStep
|
var s SaveToWorkspaceStep
|
||||||
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -321,7 +321,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "restore_workspace":
|
case "restore_workspace":
|
||||||
var s RestoreWorkspaceStep
|
var s RestoreWorkspaceStep
|
||||||
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -329,7 +329,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "save_cache":
|
case "save_cache":
|
||||||
var s SaveCacheStep
|
var s SaveCacheStep
|
||||||
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -337,7 +337,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
|
||||||
case "restore_cache":
|
case "restore_cache":
|
||||||
var s RestoreCacheStep
|
var s RestoreCacheStep
|
||||||
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.Type = stepType
|
s.Type = stepType
|
||||||
step = &s
|
step = &s
|
||||||
|
@ -359,14 +359,14 @@ func (d *Depends) UnmarshalJSON(b []byte) error {
|
||||||
var dependsRaw []json.RawMessage
|
var dependsRaw []json.RawMessage
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &dependsRaw); err != nil {
|
if err := json.Unmarshal(b, &dependsRaw); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
depends := make([]*Depend, len(dependsRaw))
|
depends := make([]*Depend, len(dependsRaw))
|
||||||
for i, dependRaw := range dependsRaw {
|
for i, dependRaw := range dependsRaw {
|
||||||
var dependi interface{}
|
var dependi interface{}
|
||||||
if err := json.Unmarshal(dependRaw, &dependi); err != nil {
|
if err := json.Unmarshal(dependRaw, &dependi); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
var depend *Depend
|
var depend *Depend
|
||||||
isSimpler := false
|
isSimpler := false
|
||||||
|
@ -391,7 +391,7 @@ func (d *Depends) UnmarshalJSON(b []byte) error {
|
||||||
if !isSimpler {
|
if !isSimpler {
|
||||||
// handle default depends definition using format "task": "taskname", conditions: [ list of conditions ]
|
// handle default depends definition using format "task": "taskname", conditions: [ list of conditions ]
|
||||||
if err := json.Unmarshal(dependRaw, &depend); err != nil {
|
if err := json.Unmarshal(dependRaw, &depend); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle simpler (for yaml) depends definition using format "taskname": [ list of conditions ]
|
// handle simpler (for yaml) depends definition using format "taskname": [ list of conditions ]
|
||||||
|
@ -401,7 +401,7 @@ func (d *Depends) UnmarshalJSON(b []byte) error {
|
||||||
type deplist map[string][]DependCondition
|
type deplist map[string][]DependCondition
|
||||||
var dl deplist
|
var dl deplist
|
||||||
if err := json.Unmarshal(dependRaw, &dl); err != nil {
|
if err := json.Unmarshal(dependRaw, &dl); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(dl) != 1 {
|
if len(dl) != 1 {
|
||||||
return errors.Errorf("unsupported depend entry format")
|
return errors.Errorf("unsupported depend entry format")
|
||||||
|
@ -440,7 +440,7 @@ type Value struct {
|
||||||
func (val *Value) UnmarshalJSON(b []byte) error {
|
func (val *Value) UnmarshalJSON(b []byte) error {
|
||||||
var ival interface{}
|
var ival interface{}
|
||||||
if err := json.Unmarshal(b, &ival); err != nil {
|
if err := json.Unmarshal(b, &ival); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
switch valValue := ival.(type) {
|
switch valValue := ival.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -479,7 +479,7 @@ func (w *When) ToWhen() *types.When {
|
||||||
func (w *When) UnmarshalJSON(b []byte) error {
|
func (w *When) UnmarshalJSON(b []byte) error {
|
||||||
var wi *when
|
var wi *when
|
||||||
if err := json.Unmarshal(b, &wi); err != nil {
|
if err := json.Unmarshal(b, &wi); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -487,21 +487,21 @@ func (w *When) UnmarshalJSON(b []byte) error {
|
||||||
if wi.Branch != nil {
|
if wi.Branch != nil {
|
||||||
w.Branch, err = parseWhenConditions(wi.Branch)
|
w.Branch, err = parseWhenConditions(wi.Branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if wi.Tag != nil {
|
if wi.Tag != nil {
|
||||||
w.Tag, err = parseWhenConditions(wi.Tag)
|
w.Tag, err = parseWhenConditions(wi.Tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if wi.Ref != nil {
|
if wi.Ref != nil {
|
||||||
w.Ref, err = parseWhenConditions(wi.Ref)
|
w.Ref, err = parseWhenConditions(wi.Ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,7 +521,7 @@ func parseWhenConditions(wi interface{}) (*types.WhenConditions, error) {
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
ss, err := parseSliceString(c)
|
ss, err := parseSliceString(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
include = ss
|
include = ss
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
|
@ -530,12 +530,12 @@ func parseWhenConditions(wi interface{}) (*types.WhenConditions, error) {
|
||||||
case "include":
|
case "include":
|
||||||
include, err = parseStringOrSlice(v)
|
include, err = parseStringOrSlice(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
case "exclude":
|
case "exclude":
|
||||||
exclude, err = parseStringOrSlice(v)
|
exclude, err = parseStringOrSlice(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf(`expected one of "include" or "exclude", got %s`, k)
|
return nil, errors.Errorf(`expected one of "include" or "exclude", got %s`, k)
|
||||||
|
@ -547,11 +547,11 @@ func parseWhenConditions(wi interface{}) (*types.WhenConditions, error) {
|
||||||
|
|
||||||
w.Include, err = parseWhenConditionSlice(include)
|
w.Include, err = parseWhenConditionSlice(include)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
w.Exclude, err = parseWhenConditionSlice(exclude)
|
w.Exclude, err = parseWhenConditionSlice(exclude)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return w, nil
|
return w, nil
|
||||||
|
@ -566,7 +566,7 @@ func parseWhenConditionSlice(conds []string) ([]types.WhenCondition, error) {
|
||||||
for _, cond := range conds {
|
for _, cond := range conds {
|
||||||
wc, err := parseWhenCondition(cond)
|
wc, err := parseWhenCondition(cond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
wcs = append(wcs, *wc)
|
wcs = append(wcs, *wc)
|
||||||
}
|
}
|
||||||
|
@ -590,7 +590,7 @@ func parseWhenCondition(s string) (*types.WhenCondition, error) {
|
||||||
|
|
||||||
if isRegExp {
|
if isRegExp {
|
||||||
if _, err := regexp.Compile(s); err != nil {
|
if _, err := regexp.Compile(s); err != nil {
|
||||||
return nil, errors.Errorf("wrong regular expression: %w", err)
|
return nil, errors.Wrapf(err, "wrong regular expression")
|
||||||
}
|
}
|
||||||
wc.Type = types.WhenConditionTypeRegExp
|
wc.Type = types.WhenConditionTypeRegExp
|
||||||
} else {
|
} else {
|
||||||
|
@ -608,7 +608,7 @@ func parseStringOrSlice(si interface{}) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
ss, err = parseSliceString(c)
|
ss, err = parseSliceString(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ss, nil
|
return ss, nil
|
||||||
|
@ -669,14 +669,14 @@ func ParseConfig(configData []byte, format ConfigFormat, configContext *ConfigCo
|
||||||
var err error
|
var err error
|
||||||
configData, err = execJsonnet(configData, configContext)
|
configData, err = execJsonnet(configData, configContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to execute jsonnet: %w", err)
|
return nil, errors.Wrapf(err, "failed to execute jsonnet")
|
||||||
}
|
}
|
||||||
case ConfigFormatStarlark:
|
case ConfigFormatStarlark:
|
||||||
// Generate json from starlark
|
// Generate json from starlark
|
||||||
var err error
|
var err error
|
||||||
configData, err = execStarlark(configData, configContext)
|
configData, err = execStarlark(configData, configContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to execute starlark: %w", err)
|
return nil, errors.Wrapf(err, "failed to execute starlark")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +686,7 @@ func ParseConfig(configData []byte, format ConfigFormat, configContext *ConfigCo
|
||||||
|
|
||||||
config := DefaultConfig
|
config := DefaultConfig
|
||||||
if err := yaml.Unmarshal(configData, &config); err != nil {
|
if err := yaml.Unmarshal(configData, &config); err != nil {
|
||||||
return nil, errors.Errorf("failed to unmarshal config: %w", err)
|
return nil, errors.Wrapf(err, "failed to unmarshal config")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &config, checkConfig(&config)
|
return &config, checkConfig(&config)
|
||||||
|
|
|
@ -15,14 +15,13 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/types"
|
"agola.io/agola/services/types"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,14 +34,14 @@ func TestParseConfig(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "test no runs 1",
|
name: "test no runs 1",
|
||||||
in: ``,
|
in: ``,
|
||||||
err: fmt.Errorf(`no runs defined`),
|
err: errors.Errorf(`no runs defined`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test no runs 2",
|
name: "test no runs 2",
|
||||||
in: `
|
in: `
|
||||||
runs:
|
runs:
|
||||||
`,
|
`,
|
||||||
err: fmt.Errorf(`no runs defined`),
|
err: errors.Errorf(`no runs defined`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test empty run",
|
name: "test empty run",
|
||||||
|
@ -50,7 +49,7 @@ func TestParseConfig(t *testing.T) {
|
||||||
runs:
|
runs:
|
||||||
-
|
-
|
||||||
`,
|
`,
|
||||||
err: fmt.Errorf(`run at index 0 is empty`),
|
err: errors.Errorf(`run at index 0 is empty`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test empty task",
|
name: "test empty task",
|
||||||
|
@ -60,7 +59,7 @@ func TestParseConfig(t *testing.T) {
|
||||||
tasks:
|
tasks:
|
||||||
-
|
-
|
||||||
`,
|
`,
|
||||||
err: fmt.Errorf(`run "run01": task at index 0 is empty`),
|
err: errors.Errorf(`run "run01": task at index 0 is empty`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test empty runtime arch",
|
name: "test empty runtime arch",
|
||||||
|
@ -88,7 +87,7 @@ func TestParseConfig(t *testing.T) {
|
||||||
containers:
|
containers:
|
||||||
- image: busybox
|
- image: busybox
|
||||||
`,
|
`,
|
||||||
err: fmt.Errorf(`task "task01" runtime: invalid arch "invalidarch"`),
|
err: errors.Errorf(`task "task01" runtime: invalid arch "invalidarch"`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test missing task dependency",
|
name: "test missing task dependency",
|
||||||
|
@ -104,7 +103,7 @@ func TestParseConfig(t *testing.T) {
|
||||||
depends:
|
depends:
|
||||||
- task02
|
- task02
|
||||||
`,
|
`,
|
||||||
err: fmt.Errorf(`run task "task02" needed by task "task01" doesn't exist`),
|
err: errors.Errorf(`run task "task02" needed by task "task01" doesn't exist`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test circular dependency between 2 tasks a -> b -> a",
|
name: "test circular dependency between 2 tasks a -> b -> a",
|
||||||
|
|
|
@ -17,21 +17,21 @@ package config
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"github.com/google/go-jsonnet"
|
"github.com/google/go-jsonnet"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func execJsonnet(configData []byte, configContext *ConfigContext) ([]byte, error) {
|
func execJsonnet(configData []byte, configContext *ConfigContext) ([]byte, error) {
|
||||||
vm := jsonnet.MakeVM()
|
vm := jsonnet.MakeVM()
|
||||||
cj, err := json.Marshal(configContext)
|
cj, err := json.Marshal(configContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal config context: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal config context")
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.TLACode("ctx", string(cj))
|
vm.TLACode("ctx", string(cj))
|
||||||
out, err := vm.EvaluateSnippet("", string(configData))
|
out, err := vm.EvaluateSnippet("", string(configData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to evaluate jsonnet config: %w", err)
|
return nil, errors.Wrapf(err, "failed to evaluate jsonnet config")
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(out), nil
|
return []byte(out), nil
|
||||||
|
|
|
@ -19,29 +19,29 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"go.starlark.net/starlark"
|
"go.starlark.net/starlark"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func starlarkArgs(cc *ConfigContext) (starlark.Tuple, error) {
|
func starlarkArgs(cc *ConfigContext) (starlark.Tuple, error) {
|
||||||
d := &starlark.Dict{}
|
d := &starlark.Dict{}
|
||||||
if err := d.SetKey(starlark.String("ref_type"), starlark.String(cc.RefType)); err != nil {
|
if err := d.SetKey(starlark.String("ref_type"), starlark.String(cc.RefType)); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.SetKey(starlark.String("ref"), starlark.String(cc.Ref)); err != nil {
|
if err := d.SetKey(starlark.String("ref"), starlark.String(cc.Ref)); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.SetKey(starlark.String("branch"), starlark.String(cc.Branch)); err != nil {
|
if err := d.SetKey(starlark.String("branch"), starlark.String(cc.Branch)); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.SetKey(starlark.String("tag"), starlark.String(cc.Tag)); err != nil {
|
if err := d.SetKey(starlark.String("tag"), starlark.String(cc.Tag)); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.SetKey(starlark.String("pull_request_id"), starlark.String(cc.PullRequestID)); err != nil {
|
if err := d.SetKey(starlark.String("pull_request_id"), starlark.String(cc.PullRequestID)); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.SetKey(starlark.String("commit_sha"), starlark.String(cc.CommitSHA)); err != nil {
|
if err := d.SetKey(starlark.String("commit_sha"), starlark.String(cc.CommitSHA)); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return []starlark.Value{d}, nil
|
return []starlark.Value{d}, nil
|
||||||
|
@ -59,13 +59,13 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
|
||||||
case starlark.Int:
|
case starlark.Int:
|
||||||
data, err := json.Marshal(v.BigInt())
|
data, err := json.Marshal(v.BigInt())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
out.Write(data)
|
out.Write(data)
|
||||||
case starlark.Float:
|
case starlark.Float:
|
||||||
data, err := json.Marshal(float64(v))
|
data, err := json.Marshal(float64(v))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
out.Write(data)
|
out.Write(data)
|
||||||
case starlark.String:
|
case starlark.String:
|
||||||
|
@ -76,7 +76,7 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
|
||||||
e := json.NewEncoder(data)
|
e := json.NewEncoder(data)
|
||||||
e.SetEscapeHTML(false)
|
e.SetEscapeHTML(false)
|
||||||
if err := e.Encode(string(v)); err != nil {
|
if err := e.Encode(string(v)); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// remove final \n introduced by the encoder
|
// remove final \n introduced by the encoder
|
||||||
out.Write(bytes.TrimSuffix(data.Bytes(), []byte("\n")))
|
out.Write(bytes.TrimSuffix(data.Bytes(), []byte("\n")))
|
||||||
|
@ -87,7 +87,7 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
|
||||||
out.WriteString(", ")
|
out.WriteString(", ")
|
||||||
}
|
}
|
||||||
if err := starlarkJSON(out, v.Index(i)); err != nil {
|
if err := starlarkJSON(out, v.Index(i)); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.WriteByte(']')
|
out.WriteByte(']')
|
||||||
|
@ -98,20 +98,20 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
|
||||||
out.WriteString(", ")
|
out.WriteString(", ")
|
||||||
}
|
}
|
||||||
if _, ok := item[0].(starlark.String); !ok {
|
if _, ok := item[0].(starlark.String); !ok {
|
||||||
return fmt.Errorf("cannot convert non-string dict key to JSON")
|
return errors.Errorf("cannot convert non-string dict key to JSON")
|
||||||
}
|
}
|
||||||
if err := starlarkJSON(out, item[0]); err != nil {
|
if err := starlarkJSON(out, item[0]); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
out.WriteString(": ")
|
out.WriteString(": ")
|
||||||
if err := starlarkJSON(out, item[1]); err != nil {
|
if err := starlarkJSON(out, item[1]); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.WriteByte('}')
|
out.WriteByte('}')
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("cannot convert starlark type %q to JSON", v.Type())
|
return errors.Errorf("cannot convert starlark type %q to JSON", v.Type())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func execStarlark(configData []byte, configContext *ConfigContext) ([]byte, erro
|
||||||
}
|
}
|
||||||
globals, err := starlark.ExecFile(thread, "config.star", configData, nil)
|
globals, err := starlark.ExecFile(thread, "config.star", configData, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we require a main function that will be called wiht one
|
// we require a main function that will be called wiht one
|
||||||
|
@ -139,18 +139,18 @@ func execStarlark(configData []byte, configContext *ConfigContext) ([]byte, erro
|
||||||
}
|
}
|
||||||
args, err := starlarkArgs(configContext)
|
args, err := starlarkArgs(configContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot create startlark arguments: %w", err)
|
return nil, errors.Wrapf(err, "cannot create startlark arguments")
|
||||||
}
|
}
|
||||||
mainVal, err = starlark.Call(thread, main, args, nil)
|
mainVal, err = starlark.Call(thread, main, args, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
switch v := mainVal.(type) {
|
switch v := mainVal.(type) {
|
||||||
case *starlark.Dict:
|
case *starlark.Dict:
|
||||||
if err := starlarkJSON(buf, v); err != nil {
|
if err := starlarkJSON(buf, v); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("wrong starlark output, must be a dict")
|
return nil, errors.Errorf("wrong starlark output, must be a dict")
|
||||||
|
|
|
@ -16,10 +16,10 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"go.starlark.net/starlark"
|
"go.starlark.net/starlark"
|
||||||
)
|
)
|
||||||
|
@ -48,7 +48,7 @@ func TestStarlarkJSON(t *testing.T) {
|
||||||
_ = s.SetKey(starlark.MakeInt(10), starlark.String("string01"))
|
_ = s.SetKey(starlark.MakeInt(10), starlark.String("string01"))
|
||||||
return starlark.Value(s)
|
return starlark.Value(s)
|
||||||
}(),
|
}(),
|
||||||
err: fmt.Errorf("cannot convert non-string dict key to JSON"),
|
err: errors.Errorf("cannot convert non-string dict key to JSON"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test list",
|
name: "test list",
|
||||||
|
|
|
@ -24,11 +24,11 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
|
|
||||||
etcdclientv3rpc "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
|
etcdclientv3rpc "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
|
||||||
"go.etcd.io/etcd/mvcc/mvccpb"
|
"go.etcd.io/etcd/mvcc/mvccpb"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(sgotti) rewrite this to use a sqlite local cache
|
// TODO(sgotti) rewrite this to use a sqlite local cache
|
||||||
|
@ -132,7 +132,7 @@ func (d *DataManager) applyWalChanges(ctx context.Context, walData *WalData, rev
|
||||||
|
|
||||||
walDataFile, err := d.ost.ReadObject(walDataFilePath)
|
walDataFile, err := d.ost.ReadObject(walDataFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to read waldata %q: %w", walDataFilePath, err)
|
return errors.Wrapf(err, "failed to read waldata %q", walDataFilePath)
|
||||||
}
|
}
|
||||||
defer walDataFile.Close()
|
defer walDataFile.Close()
|
||||||
dec := json.NewDecoder(walDataFile)
|
dec := json.NewDecoder(walDataFile)
|
||||||
|
@ -148,7 +148,7 @@ func (d *DataManager) applyWalChanges(ctx context.Context, walData *WalData, rev
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to decode wal file: %w", err)
|
return errors.Wrapf(err, "failed to decode wal file")
|
||||||
}
|
}
|
||||||
|
|
||||||
d.applyWalChangesAction(ctx, action, walData.WalSequence, revision)
|
d.applyWalChangesAction(ctx, action, walData.WalSequence, revision)
|
||||||
|
@ -200,7 +200,7 @@ func (d *DataManager) initializeChanges(ctx context.Context) error {
|
||||||
for {
|
for {
|
||||||
listResp, err := d.e.ListPaged(ctx, etcdWalsDir+"/", 0, 10, continuation)
|
listResp, err := d.e.ListPaged(ctx, etcdWalsDir+"/", 0, 10, continuation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
resp := listResp.Resp
|
resp := listResp.Resp
|
||||||
continuation = listResp.Continuation
|
continuation = listResp.Continuation
|
||||||
|
@ -210,10 +210,10 @@ func (d *DataManager) initializeChanges(ctx context.Context) error {
|
||||||
for _, kv := range resp.Kvs {
|
for _, kv := range resp.Kvs {
|
||||||
var walData *WalData
|
var walData *WalData
|
||||||
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.applyWalChanges(ctx, walData, revision); err != nil {
|
if err := d.applyWalChanges(ctx, walData, revision); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !listResp.HasMore {
|
if !listResp.HasMore {
|
||||||
|
@ -226,7 +226,7 @@ func (d *DataManager) initializeChanges(ctx context.Context) error {
|
||||||
for {
|
for {
|
||||||
listResp, err := d.e.ListPaged(ctx, etcdChangeGroupsDir+"/", 0, 10, continuation)
|
listResp, err := d.e.ListPaged(ctx, etcdChangeGroupsDir+"/", 0, 10, continuation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
resp := listResp.Resp
|
resp := listResp.Resp
|
||||||
continuation = listResp.Continuation
|
continuation = listResp.Continuation
|
||||||
|
@ -267,7 +267,7 @@ func (d *DataManager) watcher(ctx context.Context) error {
|
||||||
d.changes.initialized = false
|
d.changes.initialized = false
|
||||||
d.changes.Unlock()
|
d.changes.Unlock()
|
||||||
}
|
}
|
||||||
return errors.Errorf("watch error: %w", err)
|
return errors.Wrapf(err, "watch error")
|
||||||
}
|
}
|
||||||
revision := wresp.Header.Revision
|
revision := wresp.Header.Revision
|
||||||
|
|
||||||
|
@ -280,13 +280,13 @@ func (d *DataManager) watcher(ctx context.Context) error {
|
||||||
case mvccpb.PUT:
|
case mvccpb.PUT:
|
||||||
var walData *WalData
|
var walData *WalData
|
||||||
if err := json.Unmarshal(ev.Kv.Value, &walData); err != nil {
|
if err := json.Unmarshal(ev.Kv.Value, &walData); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if walData.WalStatus != WalStatusCommitted {
|
if walData.WalStatus != WalStatusCommitted {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := d.applyWalChanges(ctx, walData, revision); err != nil {
|
if err := d.applyWalChanges(ctx, walData, revision); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
case mvccpb.DELETE:
|
case mvccpb.DELETE:
|
||||||
walseq := path.Base(string(key))
|
walseq := path.Base(string(key))
|
||||||
|
|
|
@ -26,11 +26,11 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/objectstorage"
|
"agola.io/agola/internal/objectstorage"
|
||||||
"agola.io/agola/internal/sequence"
|
"agola.io/agola/internal/sequence"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNoDataStatus represent when there's no data status files in the ost
|
// ErrNoDataStatus represent when there's no data status files in the ost
|
||||||
|
@ -96,12 +96,12 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex,
|
||||||
for _, walData := range wals {
|
for _, walData := range wals {
|
||||||
header, err := d.ReadWal(walData.WalSequence)
|
header, err := d.ReadWal(walData.WalSequence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
walFile, err := d.ReadWalData(header.WalDataFileID)
|
walFile, err := d.ReadWalData(header.WalDataFileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot read wal data file %q: %w", header.WalDataFileID, err)
|
return nil, errors.Wrapf(err, "cannot read wal data file %q", header.WalDataFileID)
|
||||||
}
|
}
|
||||||
defer walFile.Close()
|
defer walFile.Close()
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex,
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to decode wal file: %w", err)
|
return nil, errors.Wrapf(err, "failed to decode wal file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := wimap[action.DataType]; !ok {
|
if _, ok := wimap[action.DataType]; !ok {
|
||||||
|
@ -148,7 +148,7 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex,
|
||||||
func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) error {
|
func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) error {
|
||||||
dataSequence, err := sequence.IncSequence(ctx, d.e, etcdCheckpointSeqKey)
|
dataSequence, err := sequence.IncSequence(ctx, d.e, etcdCheckpointSeqKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastWalSequence string
|
var lastWalSequence string
|
||||||
|
@ -164,7 +164,7 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
|
||||||
|
|
||||||
curDataStatus, err := d.GetLastDataStatus()
|
curDataStatus, err := d.GetLastDataStatus()
|
||||||
if err != nil && !errors.Is(err, ErrNoDataStatus) {
|
if err != nil && !errors.Is(err, ErrNoDataStatus) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
startWalIndex := 0
|
startWalIndex := 0
|
||||||
|
@ -184,7 +184,7 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
|
||||||
|
|
||||||
wi, err := d.walIndex(ctx, wals)
|
wi, err := d.walIndex(ctx, wals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dataType := range d.dataTypes {
|
for _, dataType := range d.dataTypes {
|
||||||
|
@ -194,14 +194,14 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
|
||||||
}
|
}
|
||||||
dataStatusFiles, err := d.writeDataType(ctx, wi, dataType, dataSequence, curDataStatusFiles)
|
dataStatusFiles, err := d.writeDataType(ctx, wi, dataType, dataSequence, curDataStatusFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataStatus.Files[dataType] = dataStatusFiles
|
dataStatus.Files[dataType] = dataStatusFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
dataStatusj, err := json.Marshal(dataStatus)
|
dataStatusj, err := json.Marshal(dataStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.ost.WriteObject(d.dataStatusPath(dataSequence), bytes.NewReader(dataStatusj), int64(len(dataStatusj)), true); err != nil {
|
if err := d.ost.WriteObject(d.dataStatusPath(dataSequence), bytes.NewReader(dataStatusj), int64(len(dataStatusj)), true); err != nil {
|
||||||
return fromOSTError(err)
|
return fromOSTError(err)
|
||||||
|
@ -212,7 +212,7 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
|
||||||
|
|
||||||
func (d *DataManager) writeDataFile(ctx context.Context, buf *bytes.Buffer, size int64, dataFileIndex *DataFileIndex, dataFileID, dataType string) error {
|
func (d *DataManager) writeDataFile(ctx context.Context, buf *bytes.Buffer, size int64, dataFileIndex *DataFileIndex, dataFileID, dataType string) error {
|
||||||
if buf.Len() == 0 {
|
if buf.Len() == 0 {
|
||||||
return fmt.Errorf("empty data entries")
|
return errors.Errorf("empty data entries")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.ost.WriteObject(d.DataFilePath(dataType, dataFileID), buf, size, true); err != nil {
|
if err := d.ost.WriteObject(d.DataFilePath(dataType, dataFileID), buf, size, true); err != nil {
|
||||||
|
@ -221,7 +221,7 @@ func (d *DataManager) writeDataFile(ctx context.Context, buf *bytes.Buffer, size
|
||||||
|
|
||||||
dataFileIndexj, err := json.Marshal(dataFileIndex)
|
dataFileIndexj, err := json.Marshal(dataFileIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.ost.WriteObject(d.DataFileIndexPath(dataType, dataFileID), bytes.NewReader(dataFileIndexj), int64(len(dataFileIndexj)), true); err != nil {
|
if err := d.ost.WriteObject(d.DataFileIndexPath(dataType, dataFileID), bytes.NewReader(dataFileIndexj), int64(len(dataFileIndexj)), true); err != nil {
|
||||||
return fromOSTError(err)
|
return fromOSTError(err)
|
||||||
|
@ -354,7 +354,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
oldDataf.Close()
|
oldDataf.Close()
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataEntries = append(dataEntries, de)
|
dataEntries = append(dataEntries, de)
|
||||||
|
@ -434,10 +434,10 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
|
||||||
lastEntryID = de.ID
|
lastEntryID = de.ID
|
||||||
dataEntryj, err := json.Marshal(de)
|
dataEntryj, err := json.Marshal(de)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, err := buf.Write(dataEntryj); err != nil {
|
if _, err := buf.Write(dataEntryj); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataFileIndex.Index[de.ID] = pos - lastSplitPos
|
dataFileIndex.Index[de.ID] = pos - lastSplitPos
|
||||||
prevPos := pos
|
prevPos := pos
|
||||||
|
@ -470,7 +470,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
|
||||||
for i, sp := range splitPoints {
|
for i, sp := range splitPoints {
|
||||||
curDataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
|
curDataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
|
||||||
if err := d.writeDataFile(ctx, &buf, sp.pos-curPos, dataFileIndexes[i], curDataFileID, dataType); err != nil {
|
if err := d.writeDataFile(ctx, &buf, sp.pos-curPos, dataFileIndexes[i], curDataFileID, dataType); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// insert new dataStatusFile
|
// insert new dataStatusFile
|
||||||
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
|
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
|
||||||
|
@ -492,7 +492,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
|
||||||
func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
|
func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
|
||||||
curDataStatus, err := d.GetLastDataStatus()
|
curDataStatus, err := d.GetLastDataStatus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
curFiles := curDataStatus.Files
|
curFiles := curDataStatus.Files
|
||||||
|
|
||||||
|
@ -519,7 +519,7 @@ func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
|
||||||
err = dec.Decode(&dataFileIndex)
|
err = dec.Decode(&dataFileIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dataFileIndexf.Close()
|
dataFileIndexf.Close()
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataFileIndexf.Close()
|
dataFileIndexf.Close()
|
||||||
|
|
||||||
|
@ -534,13 +534,13 @@ func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
|
||||||
}
|
}
|
||||||
if _, err := dataf.Seek(int64(pos), io.SeekStart); err != nil {
|
if _, err := dataf.Seek(int64(pos), io.SeekStart); err != nil {
|
||||||
dataf.Close()
|
dataf.Close()
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
var de *DataEntry
|
var de *DataEntry
|
||||||
dec = json.NewDecoder(dataf)
|
dec = json.NewDecoder(dataf)
|
||||||
if err := dec.Decode(&de); err != nil {
|
if err := dec.Decode(&de); err != nil {
|
||||||
dataf.Close()
|
dataf.Close()
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataf.Close()
|
dataf.Close()
|
||||||
|
|
||||||
|
@ -640,7 +640,7 @@ func (d *DataManager) GetDataStatus(dataSequence *sequence.Sequence) (*DataStatu
|
||||||
func (d *DataManager) GetFirstDataStatusSequence() (*sequence.Sequence, error) {
|
func (d *DataManager) GetFirstDataStatusSequence() (*sequence.Sequence, error) {
|
||||||
dataStatusSequences, err := d.GetFirstDataStatusSequences(1)
|
dataStatusSequences, err := d.GetFirstDataStatusSequences(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataStatusSequences[0], nil
|
return dataStatusSequences[0], nil
|
||||||
|
@ -649,7 +649,7 @@ func (d *DataManager) GetFirstDataStatusSequence() (*sequence.Sequence, error) {
|
||||||
func (d *DataManager) GetLastDataStatusSequence() (*sequence.Sequence, error) {
|
func (d *DataManager) GetLastDataStatusSequence() (*sequence.Sequence, error) {
|
||||||
dataStatusSequences, err := d.GetLastDataStatusSequences(1)
|
dataStatusSequences, err := d.GetLastDataStatusSequences(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataStatusSequences[0], nil
|
return dataStatusSequences[0], nil
|
||||||
|
@ -658,7 +658,7 @@ func (d *DataManager) GetLastDataStatusSequence() (*sequence.Sequence, error) {
|
||||||
func (d *DataManager) GetFirstDataStatus() (*DataStatus, error) {
|
func (d *DataManager) GetFirstDataStatus() (*DataStatus, error) {
|
||||||
dataStatusSequence, err := d.GetFirstDataStatusSequence()
|
dataStatusSequence, err := d.GetFirstDataStatusSequence()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.GetDataStatus(dataStatusSequence)
|
return d.GetDataStatus(dataStatusSequence)
|
||||||
|
@ -667,7 +667,7 @@ func (d *DataManager) GetFirstDataStatus() (*DataStatus, error) {
|
||||||
func (d *DataManager) GetLastDataStatus() (*DataStatus, error) {
|
func (d *DataManager) GetLastDataStatus() (*DataStatus, error) {
|
||||||
dataStatusSequence, err := d.GetLastDataStatusSequence()
|
dataStatusSequence, err := d.GetLastDataStatusSequence()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.GetDataStatus(dataStatusSequence)
|
return d.GetDataStatus(dataStatusSequence)
|
||||||
|
@ -675,12 +675,12 @@ func (d *DataManager) GetLastDataStatus() (*DataStatus, error) {
|
||||||
|
|
||||||
func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
|
func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
|
||||||
if err := d.checkpoint(ctx, true); err != nil {
|
if err := d.checkpoint(ctx, true); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
curDataStatus, err := d.GetLastDataStatus()
|
curDataStatus, err := d.GetLastDataStatus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dataType := range d.dataTypes {
|
for _, dataType := range d.dataTypes {
|
||||||
|
@ -695,7 +695,7 @@ func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(w, dataf); err != nil {
|
if _, err := io.Copy(w, dataf); err != nil {
|
||||||
dataf.Close()
|
dataf.Close()
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataf.Close()
|
dataf.Close()
|
||||||
|
@ -708,7 +708,7 @@ func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
|
||||||
func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
// delete contents in etcd
|
// delete contents in etcd
|
||||||
if err := d.deleteEtcd(ctx); err != nil {
|
if err := d.deleteEtcd(ctx); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we require all entries of the same datatypes grouped together
|
// we require all entries of the same datatypes grouped together
|
||||||
|
@ -717,7 +717,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
// create a new sequence, we assume that it'll be greater than previous data sequences
|
// create a new sequence, we assume that it'll be greater than previous data sequences
|
||||||
dataSequence, err := sequence.IncSequence(ctx, d.e, etcdCheckpointSeqKey)
|
dataSequence, err := sequence.IncSequence(ctx, d.e, etcdCheckpointSeqKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataStatus := &DataStatus{
|
dataStatus := &DataStatus{
|
||||||
|
@ -745,7 +745,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
if errors.Is(err, io.EOF) {
|
if errors.Is(err, io.EOF) {
|
||||||
dataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
|
dataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
|
||||||
if err := d.writeDataFile(ctx, &buf, int64(buf.Len()), dataFileIndex, dataFileID, curDataType); err != nil {
|
if err := d.writeDataFile(ctx, &buf, int64(buf.Len()), dataFileIndex, dataFileID, curDataType); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
|
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
|
||||||
|
@ -779,7 +779,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
if mustWrite {
|
if mustWrite {
|
||||||
dataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
|
dataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
|
||||||
if err := d.writeDataFile(ctx, &buf, int64(buf.Len()), dataFileIndex, dataFileID, curDataType); err != nil {
|
if err := d.writeDataFile(ctx, &buf, int64(buf.Len()), dataFileIndex, dataFileID, curDataType); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
|
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
|
||||||
|
@ -810,10 +810,10 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
|
|
||||||
dataEntryj, err := json.Marshal(de)
|
dataEntryj, err := json.Marshal(de)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, err := buf.Write(dataEntryj); err != nil {
|
if _, err := buf.Write(dataEntryj); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataFileIndex.Index[de.ID] = pos
|
dataFileIndex.Index[de.ID] = pos
|
||||||
pos += int64(len(dataEntryj))
|
pos += int64(len(dataEntryj))
|
||||||
|
@ -821,7 +821,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
|
|
||||||
dataStatusj, err := json.Marshal(dataStatus)
|
dataStatusj, err := json.Marshal(dataStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := d.ost.WriteObject(d.dataStatusPath(dataSequence), bytes.NewReader(dataStatusj), int64(len(dataStatusj)), true); err != nil {
|
if err := d.ost.WriteObject(d.dataStatusPath(dataSequence), bytes.NewReader(dataStatusj), int64(len(dataStatusj)), true); err != nil {
|
||||||
return fromOSTError(err)
|
return fromOSTError(err)
|
||||||
|
@ -829,7 +829,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
|
|
||||||
// initialize etcd providing the specific datastatus
|
// initialize etcd providing the specific datastatus
|
||||||
if err := d.InitEtcd(ctx, dataStatus); err != nil {
|
if err := d.InitEtcd(ctx, dataStatus); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -838,7 +838,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
|
||||||
func (d *DataManager) CleanOldCheckpoints(ctx context.Context) error {
|
func (d *DataManager) CleanOldCheckpoints(ctx context.Context) error {
|
||||||
dataStatusSequences, err := d.GetLastDataStatusSequences(dataStatusToKeep)
|
dataStatusSequences, err := d.GetLastDataStatusSequences(dataStatusToKeep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.cleanOldCheckpoints(ctx, dataStatusSequences)
|
return d.cleanOldCheckpoints(ctx, dataStatusSequences)
|
||||||
|
@ -894,7 +894,7 @@ func (d *DataManager) cleanOldCheckpoints(ctx context.Context, dataStatusSequenc
|
||||||
for _, dataStatusSequence := range dataStatusSequences {
|
for _, dataStatusSequence := range dataStatusSequences {
|
||||||
dataStatus, err := d.GetDataStatus(dataStatusSequence)
|
dataStatus, err := d.GetDataStatus(dataStatusSequence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for dataType := range dataStatus.Files {
|
for dataType := range dataStatus.Files {
|
||||||
|
|
|
@ -21,12 +21,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
"agola.io/agola/internal/objectstorage"
|
"agola.io/agola/internal/objectstorage"
|
||||||
"agola.io/agola/internal/sequence"
|
"agola.io/agola/internal/sequence"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(sgotti) handle etcd unwanted changes:
|
// TODO(sgotti) handle etcd unwanted changes:
|
||||||
|
@ -252,7 +252,7 @@ func (d *DataManager) deleteEtcd(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
for _, prefix := range prefixes {
|
for _, prefix := range prefixes {
|
||||||
if err := d.e.DeletePrefix(ctx, prefix); err != nil {
|
if err := d.e.DeletePrefix(ctx, prefix); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,12 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/objectstorage"
|
"agola.io/agola/internal/objectstorage"
|
||||||
"agola.io/agola/internal/testutil"
|
"agola.io/agola/internal/testutil"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupEtcd(t *testing.T, log zerolog.Logger, dir string) *testutil.TestEmbeddedEtcd {
|
func setupEtcd(t *testing.T, log zerolog.Logger, dir string) *testutil.TestEmbeddedEtcd {
|
||||||
|
@ -612,7 +612,7 @@ func doAndCheckCheckpoint(t *testing.T, ctx context.Context, dm *DataManager, ac
|
||||||
// populate with a wal
|
// populate with a wal
|
||||||
_, err := dm.WriteWal(ctx, actionGroup, nil)
|
_, err := dm.WriteWal(ctx, actionGroup, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,11 +621,11 @@ func doAndCheckCheckpoint(t *testing.T, ctx context.Context, dm *DataManager, ac
|
||||||
|
|
||||||
// do a checkpoint
|
// do a checkpoint
|
||||||
if err := dm.checkpoint(ctx, true); err != nil {
|
if err := dm.checkpoint(ctx, true); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkDataFiles(ctx, t, dm, expectedEntries); err != nil {
|
if err := checkDataFiles(ctx, t, dm, expectedEntries); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return expectedEntries, nil
|
return expectedEntries, nil
|
||||||
|
@ -635,7 +635,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
// read the data file
|
// read the data file
|
||||||
curDataStatus, err := dm.GetLastDataStatus()
|
curDataStatus, err := dm.GetLastDataStatus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
allEntriesMap := map[string]*DataEntry{}
|
allEntriesMap := map[string]*DataEntry{}
|
||||||
|
@ -645,14 +645,14 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
for i, file := range curDataStatus.Files[dataType] {
|
for i, file := range curDataStatus.Files[dataType] {
|
||||||
dataFileIndexf, err := dm.ost.ReadObject(dm.DataFileIndexPath(dataType, file.ID))
|
dataFileIndexf, err := dm.ost.ReadObject(dm.DataFileIndexPath(dataType, file.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
var dataFileIndex *DataFileIndex
|
var dataFileIndex *DataFileIndex
|
||||||
dec := json.NewDecoder(dataFileIndexf)
|
dec := json.NewDecoder(dataFileIndexf)
|
||||||
err = dec.Decode(&dataFileIndex)
|
err = dec.Decode(&dataFileIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dataFileIndexf.Close()
|
dataFileIndexf.Close()
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataFileIndexf.Close()
|
dataFileIndexf.Close()
|
||||||
|
@ -660,7 +660,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
dataEntries := []*DataEntry{}
|
dataEntries := []*DataEntry{}
|
||||||
dataf, err := dm.ost.ReadObject(dm.DataFilePath(dataType, file.ID))
|
dataf, err := dm.ost.ReadObject(dm.DataFilePath(dataType, file.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dec = json.NewDecoder(dataf)
|
dec = json.NewDecoder(dataf)
|
||||||
var prevEntryID string
|
var prevEntryID string
|
||||||
|
@ -674,15 +674,15 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dataf.Close()
|
dataf.Close()
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// check that there are no duplicate entries
|
// check that there are no duplicate entries
|
||||||
if _, ok := allEntriesMap[de.ID]; ok {
|
if _, ok := allEntriesMap[de.ID]; ok {
|
||||||
return fmt.Errorf("duplicate entry id: %s", de.ID)
|
return errors.Errorf("duplicate entry id: %s", de.ID)
|
||||||
}
|
}
|
||||||
// check that the entries are in order
|
// check that the entries are in order
|
||||||
if de.ID < prevEntryID {
|
if de.ID < prevEntryID {
|
||||||
return fmt.Errorf("previous entry id: %s greater than entry id: %s", prevEntryID, de.ID)
|
return errors.Errorf("previous entry id: %s greater than entry id: %s", prevEntryID, de.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataEntriesMap[de.ID] = de
|
dataEntriesMap[de.ID] = de
|
||||||
|
@ -693,7 +693,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
|
|
||||||
// check that the index matches the entries
|
// check that the index matches the entries
|
||||||
if len(dataFileIndex.Index) != len(dataEntriesMap) {
|
if len(dataFileIndex.Index) != len(dataEntriesMap) {
|
||||||
return fmt.Errorf("index entries: %d different than data entries: %d", len(dataFileIndex.Index), len(dataEntriesMap))
|
return errors.Errorf("index entries: %d different than data entries: %d", len(dataFileIndex.Index), len(dataEntriesMap))
|
||||||
}
|
}
|
||||||
indexIDs := make([]string, len(dataFileIndex.Index))
|
indexIDs := make([]string, len(dataFileIndex.Index))
|
||||||
entriesIDs := make([]string, len(dataEntriesMap))
|
entriesIDs := make([]string, len(dataEntriesMap))
|
||||||
|
@ -706,19 +706,19 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
sort.Strings(indexIDs)
|
sort.Strings(indexIDs)
|
||||||
sort.Strings(entriesIDs)
|
sort.Strings(entriesIDs)
|
||||||
if !reflect.DeepEqual(indexIDs, entriesIDs) {
|
if !reflect.DeepEqual(indexIDs, entriesIDs) {
|
||||||
return fmt.Errorf("index entries ids don't match data entries ids: index: %v, data: %v", indexIDs, entriesIDs)
|
return errors.Errorf("index entries ids don't match data entries ids: index: %v, data: %v", indexIDs, entriesIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.LastEntryID != dataEntries[len(dataEntries)-1].ID {
|
if file.LastEntryID != dataEntries[len(dataEntries)-1].ID {
|
||||||
return fmt.Errorf("lastEntryID for datafile %d: %s is different than real last entry id: %s", i, file.LastEntryID, dataEntries[len(dataEntries)-1].ID)
|
return errors.Errorf("lastEntryID for datafile %d: %s is different than real last entry id: %s", i, file.LastEntryID, dataEntries[len(dataEntries)-1].ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that all the files are in order
|
// check that all the files are in order
|
||||||
if file.LastEntryID == prevLastEntryID {
|
if file.LastEntryID == prevLastEntryID {
|
||||||
return fmt.Errorf("lastEntryID for datafile %d is equal than previous file lastEntryID: %s == %s", i, file.LastEntryID, prevLastEntryID)
|
return errors.Errorf("lastEntryID for datafile %d is equal than previous file lastEntryID: %s == %s", i, file.LastEntryID, prevLastEntryID)
|
||||||
}
|
}
|
||||||
if file.LastEntryID < prevLastEntryID {
|
if file.LastEntryID < prevLastEntryID {
|
||||||
return fmt.Errorf("lastEntryID for datafile %d is less than previous file lastEntryID: %s < %s", i, file.LastEntryID, prevLastEntryID)
|
return errors.Errorf("lastEntryID for datafile %d is less than previous file lastEntryID: %s < %s", i, file.LastEntryID, prevLastEntryID)
|
||||||
}
|
}
|
||||||
prevLastEntryID = file.LastEntryID
|
prevLastEntryID = file.LastEntryID
|
||||||
}
|
}
|
||||||
|
@ -726,10 +726,10 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
|
||||||
|
|
||||||
// check that the number of entries is right
|
// check that the number of entries is right
|
||||||
if len(allEntriesMap) != len(expectedEntriesMap) {
|
if len(allEntriesMap) != len(expectedEntriesMap) {
|
||||||
return fmt.Errorf("expected %d total entries, got %d", len(expectedEntriesMap), len(allEntriesMap))
|
return errors.Errorf("expected %d total entries, got %d", len(expectedEntriesMap), len(allEntriesMap))
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(expectedEntriesMap, allEntriesMap) {
|
if !reflect.DeepEqual(expectedEntriesMap, allEntriesMap) {
|
||||||
return fmt.Errorf("expected entries don't match current entries")
|
return errors.Errorf("expected entries don't match current entries")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
"agola.io/agola/internal/objectstorage"
|
"agola.io/agola/internal/objectstorage"
|
||||||
"agola.io/agola/internal/sequence"
|
"agola.io/agola/internal/sequence"
|
||||||
|
@ -34,7 +35,6 @@ import (
|
||||||
"go.etcd.io/etcd/clientv3/concurrency"
|
"go.etcd.io/etcd/clientv3/concurrency"
|
||||||
etcdclientv3rpc "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
|
etcdclientv3rpc "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
|
||||||
"go.etcd.io/etcd/mvcc/mvccpb"
|
"go.etcd.io/etcd/mvcc/mvccpb"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionType string
|
type ActionType string
|
||||||
|
@ -127,7 +127,7 @@ func (d *DataManager) ReadObject(dataType, id string, cgNames []string) (io.Read
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := d.Read(dataType, id)
|
f, err := d.Read(dataType, id)
|
||||||
return ioutil.NopCloser(f), cgt, err
|
return ioutil.NopCloser(f), cgt, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataManager) HasOSTWal(walseq string) (bool, error) {
|
func (d *DataManager) HasOSTWal(walseq string) (bool, error) {
|
||||||
|
@ -150,7 +150,7 @@ func (d *DataManager) ReadWal(walseq string) (*WalHeader, error) {
|
||||||
dec := json.NewDecoder(walFilef)
|
dec := json.NewDecoder(walFilef)
|
||||||
var header *WalHeader
|
var header *WalHeader
|
||||||
if err = dec.Decode(&header); err != nil {
|
if err = dec.Decode(&header); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return header, nil
|
return header, nil
|
||||||
|
@ -260,7 +260,7 @@ func (d *DataManager) ListEtcdChangeGroups(ctx context.Context, revision int64)
|
||||||
changeGroupsRevisions := changeGroupsRevisions{}
|
changeGroupsRevisions := changeGroupsRevisions{}
|
||||||
resp, err := d.e.List(ctx, etcdChangeGroupsDir, "", revision)
|
resp, err := d.e.List(ctx, etcdChangeGroupsDir, "", revision)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for _, kv := range resp.Kvs {
|
for _, kv := range resp.Kvs {
|
||||||
changegroupID := path.Base(string(kv.Key))
|
changegroupID := path.Base(string(kv.Key))
|
||||||
|
@ -277,7 +277,7 @@ func (d *DataManager) FirstAvailableWalData(ctx context.Context) (*WalData, int6
|
||||||
// list waldata and just get the first if available
|
// list waldata and just get the first if available
|
||||||
listResp, err := d.e.ListPaged(ctx, etcdWalsDir, 0, 1, nil)
|
listResp, err := d.e.ListPaged(ctx, etcdWalsDir, 0, 1, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
resp := listResp.Resp
|
resp := listResp.Resp
|
||||||
revision := resp.Header.Revision
|
revision := resp.Header.Revision
|
||||||
|
@ -288,7 +288,7 @@ func (d *DataManager) FirstAvailableWalData(ctx context.Context) (*WalData, int6
|
||||||
|
|
||||||
var walData *WalData
|
var walData *WalData
|
||||||
if err := json.Unmarshal(resp.Kvs[0].Value, &walData); err != nil {
|
if err := json.Unmarshal(resp.Kvs[0].Value, &walData); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return walData, revision, nil
|
return walData, revision, nil
|
||||||
|
@ -297,7 +297,7 @@ func (d *DataManager) FirstAvailableWalData(ctx context.Context) (*WalData, int6
|
||||||
func (d *DataManager) LastCommittedStorageWal(ctx context.Context) (string, int64, error) {
|
func (d *DataManager) LastCommittedStorageWal(ctx context.Context) (string, int64, error) {
|
||||||
resp, err := d.e.Get(ctx, etcdLastCommittedStorageWalSeqKey, 0)
|
resp, err := d.e.Get(ctx, etcdLastCommittedStorageWalSeqKey, 0)
|
||||||
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return "", 0, err
|
return "", 0, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if errors.Is(err, etcd.ErrKeyNotFound) {
|
if errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return "", 0, errors.Errorf("no last committedstorage wal on etcd")
|
return "", 0, errors.Errorf("no last committedstorage wal on etcd")
|
||||||
|
@ -424,17 +424,17 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
|
||||||
|
|
||||||
walSequence, err := sequence.IncSequence(ctx, d.e, etcdWalSeqKey)
|
walSequence, err := sequence.IncSequence(ctx, d.e, etcdWalSeqKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := d.e.Get(ctx, etcdWalsDataKey, 0)
|
resp, err := d.e.Get(ctx, etcdWalsDataKey, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var walsData WalsData
|
var walsData WalsData
|
||||||
if err := json.Unmarshal(resp.Kvs[0].Value, &walsData); err != nil {
|
if err := json.Unmarshal(resp.Kvs[0].Value, &walsData); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walsData.Revision = resp.Kvs[0].ModRevision
|
walsData.Revision = resp.Kvs[0].ModRevision
|
||||||
|
|
||||||
|
@ -446,10 +446,10 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
|
||||||
for _, action := range actions {
|
for _, action := range actions {
|
||||||
actionj, err := json.Marshal(action)
|
actionj, err := json.Marshal(action)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, err := buf.Write(actionj); err != nil {
|
if _, err := buf.Write(actionj); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := d.ost.WriteObject(walDataFilePath, bytes.NewReader(buf.Bytes()), int64(buf.Len()), true); err != nil {
|
if err := d.ost.WriteObject(walDataFilePath, bytes.NewReader(buf.Bytes()), int64(buf.Len()), true); err != nil {
|
||||||
|
@ -468,11 +468,11 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
|
||||||
|
|
||||||
walsDataj, err := json.Marshal(walsData)
|
walsDataj, err := json.Marshal(walsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walDataj, err := json.Marshal(walData)
|
walDataj, err := json.Marshal(walData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmp == nil {
|
if cmp == nil {
|
||||||
|
@ -512,7 +512,7 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
|
||||||
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...).Else(getWalsData, getWal)
|
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...).Else(getWalsData, getWal)
|
||||||
tresp, err := txn.Commit()
|
tresp, err := txn.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, etcd.FromEtcdError(err)
|
return nil, errors.WithStack(etcd.FromEtcdError(err))
|
||||||
}
|
}
|
||||||
if !tresp.Succeeded {
|
if !tresp.Succeeded {
|
||||||
walsDataRev := tresp.Responses[0].GetResponseRange().Kvs[0].ModRevision
|
walsDataRev := tresp.Responses[0].GetResponseRange().Kvs[0].ModRevision
|
||||||
|
@ -559,7 +559,7 @@ func (d *DataManager) syncLoop(ctx context.Context) {
|
||||||
func (d *DataManager) sync(ctx context.Context) error {
|
func (d *DataManager) sync(ctx context.Context) error {
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -569,18 +569,18 @@ func (d *DataManager) sync(ctx context.Context) error {
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for _, kv := range resp.Kvs {
|
for _, kv := range resp.Kvs {
|
||||||
var walData WalData
|
var walData WalData
|
||||||
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// wals must be committed and checkpointed in order.
|
// wals must be committed and checkpointed in order.
|
||||||
// TODO(sgotti) this could be optimized by parallelizing writes of wals that don't have common change groups
|
// TODO(sgotti) this could be optimized by parallelizing writes of wals that don't have common change groups
|
||||||
|
@ -594,7 +594,7 @@ func (d *DataManager) sync(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
headerj, err := json.Marshal(header)
|
headerj, err := json.Marshal(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
walFileCommittedPath := walFilePath + ".committed"
|
walFileCommittedPath := walFilePath + ".committed"
|
||||||
|
@ -606,7 +606,7 @@ func (d *DataManager) sync(ctx context.Context) error {
|
||||||
walData.WalStatus = WalStatusCommittedStorage
|
walData.WalStatus = WalStatusCommittedStorage
|
||||||
walDataj, err := json.Marshal(walData)
|
walDataj, err := json.Marshal(walData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp := []etcdclientv3.Cmp{}
|
cmp := []etcdclientv3.Cmp{}
|
||||||
|
@ -619,7 +619,7 @@ func (d *DataManager) sync(ctx context.Context) error {
|
||||||
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
||||||
tresp, err := txn.Commit()
|
tresp, err := txn.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return etcd.FromEtcdError(err)
|
return errors.WithStack(etcd.FromEtcdError(err))
|
||||||
}
|
}
|
||||||
if !tresp.Succeeded {
|
if !tresp.Succeeded {
|
||||||
return errors.Errorf("failed to write committedstorage wal: concurrent update")
|
return errors.Errorf("failed to write committedstorage wal: concurrent update")
|
||||||
|
@ -648,7 +648,7 @@ func (d *DataManager) checkpointLoop(ctx context.Context) {
|
||||||
func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
|
func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -658,19 +658,19 @@ func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walsData := []*WalData{}
|
walsData := []*WalData{}
|
||||||
for _, kv := range resp.Kvs {
|
for _, kv := range resp.Kvs {
|
||||||
var walData *WalData
|
var walData *WalData
|
||||||
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walData.Revision = kv.ModRevision
|
walData.Revision = kv.ModRevision
|
||||||
|
|
||||||
|
@ -692,7 +692,7 @@ func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.writeDataSnapshot(ctx, walsData); err != nil {
|
if err := d.writeDataSnapshot(ctx, walsData); err != nil {
|
||||||
return errors.Errorf("checkpoint function error: %w", err)
|
return errors.Wrapf(err, "checkpoint function error")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, walData := range walsData {
|
for _, walData := range walsData {
|
||||||
|
@ -700,11 +700,11 @@ func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
|
||||||
walData.WalStatus = WalStatusCheckpointed
|
walData.WalStatus = WalStatusCheckpointed
|
||||||
walDataj, err := json.Marshal(walData)
|
walDataj, err := json.Marshal(walData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walKey := etcdWalKey(walData.WalSequence)
|
walKey := etcdWalKey(walData.WalSequence)
|
||||||
if _, err := d.e.AtomicPut(ctx, walKey, walDataj, walData.Revision, nil); err != nil {
|
if _, err := d.e.AtomicPut(ctx, walKey, walDataj, walData.Revision, nil); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,7 +730,7 @@ func (d *DataManager) checkpointCleanLoop(ctx context.Context) {
|
||||||
func (d *DataManager) checkpointClean(ctx context.Context) error {
|
func (d *DataManager) checkpointClean(ctx context.Context) error {
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -740,12 +740,12 @@ func (d *DataManager) checkpointClean(ctx context.Context) error {
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
if err := d.CleanOldCheckpoints(ctx); err != nil {
|
if err := d.CleanOldCheckpoints(ctx); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -773,7 +773,7 @@ func (d *DataManager) etcdWalCleanerLoop(ctx context.Context) {
|
||||||
func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
|
func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -783,13 +783,13 @@ func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(resp.Kvs) <= d.etcdWalsKeepNum {
|
if len(resp.Kvs) <= d.etcdWalsKeepNum {
|
||||||
return nil
|
return nil
|
||||||
|
@ -799,7 +799,7 @@ func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
|
||||||
for _, kv := range resp.Kvs {
|
for _, kv := range resp.Kvs {
|
||||||
var walData WalData
|
var walData WalData
|
||||||
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
if err := json.Unmarshal(kv.Value, &walData); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if walData.WalStatus != WalStatusCheckpointed {
|
if walData.WalStatus != WalStatusCheckpointed {
|
||||||
break
|
break
|
||||||
|
@ -814,7 +814,7 @@ func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
|
||||||
// arrive to a differnt S3 server that is not yet in sync?
|
// arrive to a differnt S3 server that is not yet in sync?
|
||||||
d.log.Info().Msgf("removing wal %q from etcd", walData.WalSequence)
|
d.log.Info().Msgf("removing wal %q from etcd", walData.WalSequence)
|
||||||
if _, err := d.e.AtomicDelete(ctx, string(kv.Key), kv.ModRevision); err != nil {
|
if _, err := d.e.AtomicDelete(ctx, string(kv.Key), kv.ModRevision); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeCount--
|
removeCount--
|
||||||
|
@ -846,7 +846,7 @@ func (d *DataManager) storageWalCleanerLoop(ctx context.Context) {
|
||||||
func (d *DataManager) storageWalCleaner(ctx context.Context) error {
|
func (d *DataManager) storageWalCleaner(ctx context.Context) error {
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -856,13 +856,13 @@ func (d *DataManager) storageWalCleaner(ctx context.Context) error {
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
firstDataStatus, err := d.GetFirstDataStatus()
|
firstDataStatus, err := d.GetFirstDataStatus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
firstWalSequence := firstDataStatus.WalSequence
|
firstWalSequence := firstDataStatus.WalSequence
|
||||||
|
|
||||||
|
@ -870,14 +870,14 @@ func (d *DataManager) storageWalCleaner(ctx context.Context) error {
|
||||||
// it's lesser than the first data status wal sequence
|
// it's lesser than the first data status wal sequence
|
||||||
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(resp.Kvs) == 0 {
|
if len(resp.Kvs) == 0 {
|
||||||
return errors.Errorf("no wals in etcd")
|
return errors.Errorf("no wals in etcd")
|
||||||
}
|
}
|
||||||
var walData WalData
|
var walData WalData
|
||||||
if err := json.Unmarshal(resp.Kvs[0].Value, &walData); err != nil {
|
if err := json.Unmarshal(resp.Kvs[0].Value, &walData); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if walData.WalSequence < firstWalSequence {
|
if walData.WalSequence < firstWalSequence {
|
||||||
firstWalSequence = walData.WalSequence
|
firstWalSequence = walData.WalSequence
|
||||||
|
@ -902,7 +902,7 @@ func (d *DataManager) storageWalCleaner(ctx context.Context) error {
|
||||||
|
|
||||||
header, err := d.ReadWal(walSequence)
|
header, err := d.ReadWal(walSequence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// first remove wal data file
|
// first remove wal data file
|
||||||
|
@ -956,7 +956,7 @@ func (d *DataManager) compactChangeGroupsLoop(ctx context.Context) {
|
||||||
func (d *DataManager) compactChangeGroups(ctx context.Context) error {
|
func (d *DataManager) compactChangeGroups(ctx context.Context) error {
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -966,13 +966,13 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
resp, err := d.e.Client().Get(ctx, etcdChangeGroupMinRevisionKey)
|
resp, err := d.e.Client().Get(ctx, etcdChangeGroupMinRevisionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(resp.Kvs) == 0 {
|
if len(resp.Kvs) == 0 {
|
||||||
|
@ -986,7 +986,8 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
|
||||||
txn := d.e.Client().Txn(ctx).If(cmp).Then(then)
|
txn := d.e.Client().Txn(ctx).If(cmp).Then(then)
|
||||||
tresp, err := txn.Commit()
|
tresp, err := txn.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return etcd.FromEtcdError(err)
|
return errors.WithStack(etcd.FromEtcdError(err))
|
||||||
|
|
||||||
}
|
}
|
||||||
if !tresp.Succeeded {
|
if !tresp.Succeeded {
|
||||||
return errors.Errorf("failed to update change group min revision key due to concurrent update")
|
return errors.Errorf("failed to update change group min revision key due to concurrent update")
|
||||||
|
@ -997,7 +998,7 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
|
||||||
// then remove all the groups keys with modrevision < minrevision
|
// then remove all the groups keys with modrevision < minrevision
|
||||||
resp, err = d.e.List(ctx, etcdChangeGroupsDir, "", 0)
|
resp, err = d.e.List(ctx, etcdChangeGroupsDir, "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for _, kv := range resp.Kvs {
|
for _, kv := range resp.Kvs {
|
||||||
if kv.ModRevision < revision-etcdChangeGroupMinRevisionRange {
|
if kv.ModRevision < revision-etcdChangeGroupMinRevisionRange {
|
||||||
|
@ -1006,7 +1007,7 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
|
||||||
txn := d.e.Client().Txn(ctx).If(cmp).Then(then)
|
txn := d.e.Client().Txn(ctx).If(cmp).Then(then)
|
||||||
tresp, err := txn.Commit()
|
tresp, err := txn.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return etcd.FromEtcdError(err)
|
return errors.WithStack(etcd.FromEtcdError(err))
|
||||||
}
|
}
|
||||||
if !tresp.Succeeded {
|
if !tresp.Succeeded {
|
||||||
d.log.Err(err).Msgf("failed to update change group min revision key due to concurrent update")
|
d.log.Err(err).Msgf("failed to update change group min revision key due to concurrent update")
|
||||||
|
@ -1040,7 +1041,7 @@ func (d *DataManager) etcdPingerLoop(ctx context.Context) {
|
||||||
|
|
||||||
func (d *DataManager) etcdPinger(ctx context.Context) error {
|
func (d *DataManager) etcdPinger(ctx context.Context) error {
|
||||||
if _, err := d.e.Put(ctx, etcdPingKey, []byte{}, nil); err != nil {
|
if _, err := d.e.Put(ctx, etcdPingKey, []byte{}, nil); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1055,7 +1056,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
var header *WalHeader
|
var header *WalHeader
|
||||||
if err = dec.Decode(&header); err != nil && !errors.Is(err, io.EOF) {
|
if err = dec.Decode(&header); err != nil && !errors.Is(err, io.EOF) {
|
||||||
walFile.Close()
|
walFile.Close()
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walFile.Close()
|
walFile.Close()
|
||||||
|
|
||||||
|
@ -1073,7 +1074,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
}
|
}
|
||||||
walDataj, err := json.Marshal(walData)
|
walDataj, err := json.Marshal(walData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp := []etcdclientv3.Cmp{}
|
cmp := []etcdclientv3.Cmp{}
|
||||||
|
@ -1084,7 +1085,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
||||||
tresp, err := txn.Commit()
|
tresp, err := txn.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return etcd.FromEtcdError(err)
|
return errors.WithStack(etcd.FromEtcdError(err))
|
||||||
}
|
}
|
||||||
if !tresp.Succeeded {
|
if !tresp.Succeeded {
|
||||||
return errors.Errorf("failed to sync etcd: wal %q already written", wal.WalSequence)
|
return errors.Errorf("failed to sync etcd: wal %q already written", wal.WalSequence)
|
||||||
|
@ -1094,7 +1095,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
|
|
||||||
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -1104,7 +1105,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
if errors.Is(err, etcd.ErrLocked) {
|
if errors.Is(err, etcd.ErrLocked) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() { _ = m.Unlock(ctx) }()
|
defer func() { _ = m.Unlock(ctx) }()
|
||||||
|
|
||||||
|
@ -1113,7 +1114,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
_, err = d.e.Get(ctx, etcdWalsDataKey, 0)
|
_, err = d.e.Get(ctx, etcdWalsDataKey, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, etcd.ErrKeyNotFound) {
|
if !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
mustInit = true
|
mustInit = true
|
||||||
}
|
}
|
||||||
|
@ -1123,7 +1124,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
|
|
||||||
// delete all wals from etcd
|
// delete all wals from etcd
|
||||||
if err := d.deleteEtcd(ctx); err != nil {
|
if err := d.deleteEtcd(ctx); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1135,7 +1136,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
then = append(then, etcdclientv3.OpPut(etcdChangeGroupMinRevisionKey, ""))
|
then = append(then, etcdclientv3.OpPut(etcdChangeGroupMinRevisionKey, ""))
|
||||||
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
||||||
if _, err := txn.Commit(); err != nil {
|
if _, err := txn.Commit(); err != nil {
|
||||||
return etcd.FromEtcdError(err)
|
return errors.WithStack(etcd.FromEtcdError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !mustInit {
|
if !mustInit {
|
||||||
|
@ -1150,7 +1151,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
} else {
|
} else {
|
||||||
dataStatus, err = d.GetLastDataStatus()
|
dataStatus, err = d.GetLastDataStatus()
|
||||||
if err != nil && !errors.Is(err, ErrNoDataStatus) {
|
if err != nil && !errors.Is(err, ErrNoDataStatus) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// set the first wal to import in etcd if there's a snapshot. In this way we'll
|
// set the first wal to import in etcd if there's a snapshot. In this way we'll
|
||||||
// ignore older wals (or wals left after an import)
|
// ignore older wals (or wals left after an import)
|
||||||
|
@ -1172,7 +1173,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
}
|
}
|
||||||
d.log.Debug().Msgf("wal: %s", wal)
|
d.log.Debug().Msgf("wal: %s", wal)
|
||||||
if wal.Err != nil {
|
if wal.Err != nil {
|
||||||
return wal.Err
|
return errors.WithStack(wal.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if wal.WalSequence < firstWal {
|
if wal.WalSequence < firstWal {
|
||||||
|
@ -1182,7 +1183,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
lastCommittedStorageWalSequence = wal.WalSequence
|
lastCommittedStorageWalSequence = wal.WalSequence
|
||||||
|
|
||||||
if err := writeWal(wal, previousWalSequence); err != nil {
|
if err := writeWal(wal, previousWalSequence); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
previousWalSequence = wal.WalSequence
|
previousWalSequence = wal.WalSequence
|
||||||
wroteWals++
|
wroteWals++
|
||||||
|
@ -1192,7 +1193,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
// insert an empty wal and make it already committedstorage
|
// insert an empty wal and make it already committedstorage
|
||||||
walSequence, err := sequence.IncSequence(ctx, d.e, etcdWalSeqKey)
|
walSequence, err := sequence.IncSequence(ctx, d.e, etcdWalSeqKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
walDataFileID := uuid.Must(uuid.NewV4()).String()
|
walDataFileID := uuid.Must(uuid.NewV4()).String()
|
||||||
|
@ -1212,7 +1213,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
}
|
}
|
||||||
headerj, err := json.Marshal(header)
|
headerj, err := json.Marshal(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
walFileCommittedPath := walFilePath + ".committed"
|
walFileCommittedPath := walFilePath + ".committed"
|
||||||
if err := d.ost.WriteObject(walFileCommittedPath, bytes.NewReader(headerj), int64(len(headerj)), true); err != nil {
|
if err := d.ost.WriteObject(walFileCommittedPath, bytes.NewReader(headerj), int64(len(headerj)), true); err != nil {
|
||||||
|
@ -1234,12 +1235,12 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
|
|
||||||
walDataj, err := json.Marshal(walData)
|
walDataj, err := json.Marshal(walData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
walsDataj, err := json.Marshal(walsData)
|
walsDataj, err := json.Marshal(walsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// save walsdata and lastcommittedstoragewalseq only after writing all the
|
// save walsdata and lastcommittedstoragewalseq only after writing all the
|
||||||
|
@ -1256,7 +1257,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
txn = d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
txn = d.e.Client().Txn(ctx).If(cmp...).Then(then...)
|
||||||
tresp, err := txn.Commit()
|
tresp, err := txn.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return etcd.FromEtcdError(err)
|
return errors.WithStack(etcd.FromEtcdError(err))
|
||||||
}
|
}
|
||||||
if !tresp.Succeeded {
|
if !tresp.Succeeded {
|
||||||
return errors.Errorf("failed to sync etcd: walsdata already written")
|
return errors.Errorf("failed to sync etcd: walsdata already written")
|
||||||
|
@ -1264,7 +1265,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
|
||||||
|
|
||||||
// force a checkpoint
|
// force a checkpoint
|
||||||
if err := d.checkpoint(ctx, true); err != nil {
|
if err := d.checkpoint(ctx, true); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -18,8 +18,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const dbVersionTableDDLTmpl = `
|
const dbVersionTableDDLTmpl = `
|
||||||
|
@ -33,22 +33,22 @@ func (db *DB) Create(ctx context.Context, stmts []string) error {
|
||||||
|
|
||||||
err := db.Do(ctx, func(tx *Tx) error {
|
err := db.Do(ctx, func(tx *Tx) error {
|
||||||
if _, err := tx.Exec(dbVersionTableDDLTmpl); err != nil {
|
if _, err := tx.Exec(dbVersionTableDDLTmpl); err != nil {
|
||||||
return errors.Errorf("failed to create dbversion table: %w", err)
|
return errors.Wrapf(err, "failed to create dbversion table")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.Do(ctx, func(tx *Tx) error {
|
err = db.Do(ctx, func(tx *Tx) error {
|
||||||
var version sql.NullInt64
|
var version sql.NullInt64
|
||||||
q, args, err := sb.Select("max(version)").From("dbversion").ToSql()
|
q, args, err := sb.Select("max(version)").From("dbversion").ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if err := tx.QueryRow(q, args...).Scan(&version); err != nil {
|
if err := tx.QueryRow(q, args...).Scan(&version); err != nil {
|
||||||
return errors.Errorf("cannot get current db version: %w", err)
|
return errors.Wrapf(err, "cannot get current db version")
|
||||||
}
|
}
|
||||||
if version.Valid {
|
if version.Valid {
|
||||||
return nil
|
return nil
|
||||||
|
@ -56,18 +56,18 @@ func (db *DB) Create(ctx context.Context, stmts []string) error {
|
||||||
|
|
||||||
for _, stmt := range stmts {
|
for _, stmt := range stmts {
|
||||||
if _, err := tx.Exec(stmt); err != nil {
|
if _, err := tx.Exec(stmt); err != nil {
|
||||||
return errors.Errorf("creation failed: %w", err)
|
return errors.Wrapf(err, "creation failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
q, args, err = sb.Insert("dbversion").Columns("version", "time").Values(dbVersion, "now()").ToSql()
|
q, args, err = sb.Insert("dbversion").Columns("version", "time").Values(dbVersion, "now()").ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, err := tx.Exec(q, args...); err != nil {
|
if _, err := tx.Exec(q, args...); err != nil {
|
||||||
return errors.Errorf("failed to update dbversion table: %w", err)
|
return errors.Wrapf(err, "failed to update dbversion table")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"github.com/mattn/go-sqlite3"
|
"github.com/mattn/go-sqlite3"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Type string
|
type Type string
|
||||||
|
@ -128,7 +128,7 @@ func NewDB(dbType Type, dbConnString string) (*DB, error) {
|
||||||
|
|
||||||
sqldb, err := sql.Open(driverName, dbConnString)
|
sqldb, err := sql.Open(driverName, dbConnString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := &DB{
|
db := &DB{
|
||||||
|
@ -151,11 +151,12 @@ type Tx struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Close() error {
|
func (db *DB) Close() error {
|
||||||
return db.db.Close()
|
return errors.WithStack(db.db.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Conn(ctx context.Context) (*sql.Conn, error) {
|
func (db *DB) Conn(ctx context.Context) (*sql.Conn, error) {
|
||||||
return db.db.Conn(ctx)
|
c, err := db.db.Conn(ctx)
|
||||||
|
return c, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) NewUnstartedTx() *Tx {
|
func (db *DB) NewUnstartedTx() *Tx {
|
||||||
|
@ -167,7 +168,7 @@ func (db *DB) NewUnstartedTx() *Tx {
|
||||||
func (db *DB) NewTx(ctx context.Context) (*Tx, error) {
|
func (db *DB) NewTx(ctx context.Context) (*Tx, error) {
|
||||||
tx := db.NewUnstartedTx()
|
tx := db.NewUnstartedTx()
|
||||||
if err := tx.Start(ctx); err != nil {
|
if err := tx.Start(ctx); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx, nil
|
return tx, nil
|
||||||
|
@ -188,14 +189,14 @@ func (db *DB) Do(ctx context.Context, f func(tx *Tx) error) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
|
func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
|
||||||
tx, err := db.NewTx(ctx)
|
tx, err := db.NewTx(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if p := recover(); p != nil {
|
if p := recover(); p != nil {
|
||||||
|
@ -205,7 +206,7 @@ func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
|
||||||
}()
|
}()
|
||||||
if err = f(tx); err != nil {
|
if err = f(tx); err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return tx.Commit()
|
return tx.Commit()
|
||||||
}
|
}
|
||||||
|
@ -213,12 +214,12 @@ func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
|
||||||
func (tx *Tx) Start(ctx context.Context) error {
|
func (tx *Tx) Start(ctx context.Context) error {
|
||||||
wtx, err := tx.db.db.Begin()
|
wtx, err := tx.db.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
switch tx.db.data.t {
|
switch tx.db.data.t {
|
||||||
case Postgres:
|
case Postgres:
|
||||||
if _, err := wtx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); err != nil {
|
if _, err := wtx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tx.tx = wtx
|
tx.tx = wtx
|
||||||
|
@ -230,26 +231,26 @@ func (tx *Tx) Commit() error {
|
||||||
if tx.tx == nil {
|
if tx.tx == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return tx.tx.Commit()
|
return errors.WithStack(tx.tx.Commit())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) Rollback() error {
|
func (tx *Tx) Rollback() error {
|
||||||
if tx.tx == nil {
|
if tx.tx == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return tx.tx.Rollback()
|
return errors.WithStack(tx.tx.Rollback())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) {
|
func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) {
|
||||||
query = tx.db.data.translate(query)
|
query = tx.db.data.translate(query)
|
||||||
r, err := tx.tx.ExecContext(tx.ctx, query, tx.db.data.translateArgs(args)...)
|
r, err := tx.tx.ExecContext(tx.ctx, query, tx.db.data.translateArgs(args)...)
|
||||||
return r, err
|
return r, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) Query(query string, args ...interface{}) (*sql.Rows, error) {
|
func (tx *Tx) Query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||||
query = tx.db.data.translate(query)
|
query = tx.db.data.translate(query)
|
||||||
r, err := tx.tx.QueryContext(tx.ctx, query, tx.db.data.translateArgs(args)...)
|
r, err := tx.tx.QueryContext(tx.ctx, query, tx.db.data.translateArgs(args)...)
|
||||||
return r, err
|
return r, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) QueryRow(query string, args ...interface{}) *sql.Row {
|
func (tx *Tx) QueryRow(query string, args ...interface{}) *sql.Row {
|
||||||
|
@ -262,13 +263,14 @@ func (tx *Tx) CurTime() (time.Time, error) {
|
||||||
case Sqlite3:
|
case Sqlite3:
|
||||||
var timestring string
|
var timestring string
|
||||||
if err := tx.QueryRow("select now()").Scan(×tring); err != nil {
|
if err := tx.QueryRow("select now()").Scan(×tring); err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return time.ParseInLocation("2006-01-02 15:04:05.999999999", timestring, time.UTC)
|
t, err := time.ParseInLocation("2006-01-02 15:04:05.999999999", timestring, time.UTC)
|
||||||
|
return t, errors.WithStack(err)
|
||||||
case Postgres:
|
case Postgres:
|
||||||
var now time.Time
|
var now time.Time
|
||||||
if err := tx.QueryRow("select now()").Scan(&now); err != nil {
|
if err := tx.QueryRow("select now()").Scan(&now); err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return now, nil
|
return now, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type werror struct {
|
||||||
|
cause error
|
||||||
|
msg string
|
||||||
|
*Stack
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *werror) Error() string {
|
||||||
|
if w.cause == nil {
|
||||||
|
return w.msg
|
||||||
|
}
|
||||||
|
if w.msg != "" {
|
||||||
|
return w.msg + ": " + w.cause.Error()
|
||||||
|
} else {
|
||||||
|
return w.cause.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *werror) Format(s fmt.State, verb rune) {
|
||||||
|
_, _ = io.WriteString(s, w.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *werror) Unwrap() error { return w.cause }
|
||||||
|
|
||||||
|
// New returns an error with the supplied message.
|
||||||
|
// New also records the stack trace at the point it was called.
|
||||||
|
func New(message string) error {
|
||||||
|
return &werror{
|
||||||
|
msg: message,
|
||||||
|
Stack: Callers(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf formats according to a format specifier and returns the string
|
||||||
|
// as a value that satisfies error.
|
||||||
|
// Errorf also records the stack trace at the point it was called.
|
||||||
|
func Errorf(format string, args ...interface{}) error {
|
||||||
|
return &werror{
|
||||||
|
msg: fmt.Sprintf(format, args...),
|
||||||
|
Stack: Callers(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithStack annotates err with a stack trace at the point WithStack was called.
|
||||||
|
// If err is nil, WithStack returns nil.
|
||||||
|
func WithStack(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &werror{
|
||||||
|
err,
|
||||||
|
"",
|
||||||
|
Callers(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap returns an error annotating err with a stack trace
|
||||||
|
// at the point Wrap is called, and the supplied message.
|
||||||
|
// If err is nil, Wrap returns nil.
|
||||||
|
func Wrap(err error, message string) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &werror{
|
||||||
|
err,
|
||||||
|
message,
|
||||||
|
Callers(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapf returns an error annotating err with a stack trace
|
||||||
|
// at the point Wrapf is called, and the format specifier.
|
||||||
|
// If err is nil, Wrapf returns nil.
|
||||||
|
func Wrapf(err error, format string, args ...interface{}) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &werror{
|
||||||
|
err,
|
||||||
|
fmt.Sprintf(format, args...),
|
||||||
|
Callers(0),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrintErrorDetails(err error) []string {
|
||||||
|
type stackTracer interface {
|
||||||
|
StackTrace() StackTrace
|
||||||
|
}
|
||||||
|
type errWithStack struct {
|
||||||
|
err error
|
||||||
|
msg string
|
||||||
|
stack StackTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
var stackErrs []errWithStack
|
||||||
|
errCause := err
|
||||||
|
for errCause != nil {
|
||||||
|
stackErr := errWithStack{
|
||||||
|
err: errCause,
|
||||||
|
msg: errCause.Error(),
|
||||||
|
}
|
||||||
|
//nolint:errorlint
|
||||||
|
if s, ok := errCause.(stackTracer); ok {
|
||||||
|
stackErr.stack = s.StackTrace()
|
||||||
|
}
|
||||||
|
stackErrs = append(stackErrs, stackErr)
|
||||||
|
errCause = errors.Unwrap(errCause)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines []string
|
||||||
|
for _, stackErr := range stackErrs {
|
||||||
|
if len(stackErr.stack) > 0 {
|
||||||
|
frame := stackErr.stack[0]
|
||||||
|
lines = append(lines, fmt.Sprintf("(%T) %+v: %s", stackErr.err, frame, stackErr.msg))
|
||||||
|
} else {
|
||||||
|
lines = append(lines, fmt.Sprintf("(%T) %s", stackErr.err, stackErr.msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
// +build go1.13
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
stderrors "errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Is reports whether any error in err's chain matches target.
|
||||||
|
//
|
||||||
|
// The chain consists of err itself followed by the sequence of errors obtained by
|
||||||
|
// repeatedly calling Unwrap.
|
||||||
|
//
|
||||||
|
// An error is considered to match a target if it is equal to that target or if
|
||||||
|
// it implements a method Is(error) bool such that Is(target) returns true.
|
||||||
|
func Is(err, target error) bool { return stderrors.Is(err, target) }
|
||||||
|
|
||||||
|
// As finds the first error in err's chain that matches target, and if so, sets
|
||||||
|
// target to that error value and returns true.
|
||||||
|
//
|
||||||
|
// The chain consists of err itself followed by the sequence of errors obtained by
|
||||||
|
// repeatedly calling Unwrap.
|
||||||
|
//
|
||||||
|
// An error matches target if the error's concrete value is assignable to the value
|
||||||
|
// pointed to by target, or if the error has a method As(interface{}) bool such that
|
||||||
|
// As(target) returns true. In the latter case, the As method is responsible for
|
||||||
|
// setting target.
|
||||||
|
//
|
||||||
|
// As will panic if target is not a non-nil pointer to either a type that implements
|
||||||
|
// error, or to any interface type. As returns false if err is nil.
|
||||||
|
func As(err error, target interface{}) bool { return stderrors.As(err, target) }
|
||||||
|
|
||||||
|
// Unwrap returns the result of calling the Unwrap method on err, if err's
|
||||||
|
// type contains an Unwrap method returning error.
|
||||||
|
// Otherwise, Unwrap returns nil.
|
||||||
|
func Unwrap(err error) error {
|
||||||
|
return stderrors.Unwrap(err)
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultSkip = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Frame represents a program counter inside a stack frame.
|
||||||
|
// For historical reasons if Frame is interpreted as a uintptr
|
||||||
|
// its value represents the program counter + 1.
|
||||||
|
type Frame uintptr
|
||||||
|
|
||||||
|
// pc returns the program counter for this frame;
|
||||||
|
// multiple frames may have the same PC value.
|
||||||
|
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
|
||||||
|
|
||||||
|
// file returns the full path to the file that contains the
|
||||||
|
// function for this Frame's pc.
|
||||||
|
func (f Frame) file() string {
|
||||||
|
fn := runtime.FuncForPC(f.pc())
|
||||||
|
if fn == nil {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
file, _ := fn.FileLine(f.pc())
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
// line returns the line number of source code of the
|
||||||
|
// function for this Frame's pc.
|
||||||
|
func (f Frame) line() int {
|
||||||
|
fn := runtime.FuncForPC(f.pc())
|
||||||
|
if fn == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
_, line := fn.FileLine(f.pc())
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
|
// name returns the name of this function, if known.
|
||||||
|
func (f Frame) name() string {
|
||||||
|
fn := runtime.FuncForPC(f.pc())
|
||||||
|
if fn == nil {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
return fn.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format formats the frame according to the fmt.Formatter interface.
|
||||||
|
//
|
||||||
|
// %s source file
|
||||||
|
// %d source line
|
||||||
|
// %n function name
|
||||||
|
// %v equivalent to %s:%d
|
||||||
|
//
|
||||||
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
|
//
|
||||||
|
// %+s function name and path of source file relative to the compile time
|
||||||
|
// GOPATH separated by \n\t (<funcname>\n\t<path>)
|
||||||
|
// %+v equivalent to %+s:%d
|
||||||
|
func (f Frame) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 's':
|
||||||
|
switch {
|
||||||
|
case s.Flag('+'):
|
||||||
|
_, _ = io.WriteString(s, f.name())
|
||||||
|
_, _ = io.WriteString(s, "\n\t")
|
||||||
|
_, _ = io.WriteString(s, f.file())
|
||||||
|
default:
|
||||||
|
_, _ = io.WriteString(s, path.Base(f.file()))
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
_, _ = io.WriteString(s, strconv.Itoa(f.line()))
|
||||||
|
case 'n':
|
||||||
|
_, _ = io.WriteString(s, funcname(f.name()))
|
||||||
|
case 'v':
|
||||||
|
f.Format(s, 's')
|
||||||
|
_, _ = io.WriteString(s, ":")
|
||||||
|
f.Format(s, 'd')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText formats a stacktrace Frame as a text string. The output is the
|
||||||
|
// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
|
||||||
|
func (f Frame) MarshalText() ([]byte, error) {
|
||||||
|
name := f.name()
|
||||||
|
if name == "unknown" {
|
||||||
|
return []byte(name), nil
|
||||||
|
}
|
||||||
|
return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
||||||
|
type StackTrace []Frame
|
||||||
|
|
||||||
|
// Format formats the stack of Frames according to the fmt.Formatter interface.
|
||||||
|
//
|
||||||
|
// %s lists source files for each Frame in the stack
|
||||||
|
// %v lists the source file and line number for each Frame in the stack
|
||||||
|
//
|
||||||
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
|
//
|
||||||
|
// %+v Prints filename, function, and line number for each Frame in the stack.
|
||||||
|
func (st StackTrace) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
switch {
|
||||||
|
case s.Flag('+'):
|
||||||
|
for _, f := range st {
|
||||||
|
_, _ = io.WriteString(s, "\n")
|
||||||
|
f.Format(s, verb)
|
||||||
|
}
|
||||||
|
case s.Flag('#'):
|
||||||
|
fmt.Fprintf(s, "%#v", []Frame(st))
|
||||||
|
default:
|
||||||
|
st.formatSlice(s, verb)
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
st.formatSlice(s, verb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatSlice will format this StackTrace into the given buffer as a slice of
|
||||||
|
// Frame, only valid when called with '%s' or '%v'.
|
||||||
|
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
|
||||||
|
_, _ = io.WriteString(s, "[")
|
||||||
|
for i, f := range st {
|
||||||
|
if i > 0 {
|
||||||
|
_, _ = io.WriteString(s, " ")
|
||||||
|
}
|
||||||
|
f.Format(s, verb)
|
||||||
|
}
|
||||||
|
_, _ = io.WriteString(s, "]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack represents a Stack of program counters.
|
||||||
|
type Stack []uintptr
|
||||||
|
|
||||||
|
func (s *Stack) Format(st fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
switch {
|
||||||
|
case st.Flag('+'):
|
||||||
|
for _, pc := range *s {
|
||||||
|
f := Frame(pc)
|
||||||
|
fmt.Fprintf(st, "\n%+v", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stack) StackTrace() StackTrace {
|
||||||
|
f := make([]Frame, len(*s))
|
||||||
|
for i := 0; i < len(f); i++ {
|
||||||
|
f[i] = Frame((*s)[i])
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func Callers(additionalSkip int) *Stack {
|
||||||
|
const depth = 32
|
||||||
|
var pcs [depth]uintptr
|
||||||
|
n := runtime.Callers(defaultSkip+additionalSkip, pcs[:])
|
||||||
|
var st Stack = pcs[0:n]
|
||||||
|
return &st
|
||||||
|
}
|
||||||
|
|
||||||
|
// funcname removes the path prefix component of a function's name reported by func.Name().
|
||||||
|
func funcname(name string) string {
|
||||||
|
i := strings.LastIndex(name, "/")
|
||||||
|
name = name[i+1:]
|
||||||
|
i = strings.Index(name, ".")
|
||||||
|
return name[i+1:]
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// copied from zerolog console writer since they aren't exported
|
||||||
|
//nolint
|
||||||
|
const (
|
||||||
|
colorBlack = iota + 30
|
||||||
|
colorRed
|
||||||
|
colorGreen
|
||||||
|
colorYellow
|
||||||
|
colorBlue
|
||||||
|
colorMagenta
|
||||||
|
colorCyan
|
||||||
|
colorWhite
|
||||||
|
)
|
||||||
|
|
||||||
|
// colorize returns the string s wrapped in ANSI code c, unless disabled is true.
|
||||||
|
func colorize(s interface{}, c int, disabled bool) string {
|
||||||
|
if disabled {
|
||||||
|
return fmt.Sprintf("%s", s)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("\x1b[%dm%v\x1b[0m", c, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorFormat = struct {
|
||||||
|
Error string
|
||||||
|
Details []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatErrFieldValue(i interface{}) string {
|
||||||
|
switch d := i.(type) {
|
||||||
|
case []byte:
|
||||||
|
var ed errorFormat
|
||||||
|
if err := json.Unmarshal(d, &ed); err != nil {
|
||||||
|
return fmt.Sprintf("error: %v", err)
|
||||||
|
}
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString(fmt.Sprintf("%s\n", ed.Error))
|
||||||
|
if len(ed.Details) > 0 {
|
||||||
|
sb.WriteString("error details:\n")
|
||||||
|
for _, l := range ed.Details {
|
||||||
|
sb.WriteString(fmt.Sprintf("%s\n", l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return colorize(sb.String(), colorRed, false)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return colorize(fmt.Sprintf("%s", d), colorRed, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrorMarshalFunc(err error) interface{} {
|
||||||
|
ef := errorFormat{
|
||||||
|
Error: err.Error(),
|
||||||
|
Details: PrintErrorDetails(err),
|
||||||
|
}
|
||||||
|
return ef
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -29,7 +30,6 @@ import (
|
||||||
etcdclientv3 "go.etcd.io/etcd/clientv3"
|
etcdclientv3 "go.etcd.io/etcd/clientv3"
|
||||||
"go.etcd.io/etcd/clientv3/namespace"
|
"go.etcd.io/etcd/clientv3/namespace"
|
||||||
"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
|
"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -65,7 +65,7 @@ func FromEtcdError(err error) error {
|
||||||
if errors.Is(err, rpctypes.ErrKeyNotFound) {
|
if errors.Is(err, rpctypes.ErrKeyNotFound) {
|
||||||
return ErrKeyNotFound
|
return ErrKeyNotFound
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Store struct {
|
type Store struct {
|
||||||
|
@ -90,7 +90,7 @@ func New(cfg Config) (*Store, error) {
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
u, err := url.Parse(e)
|
u, err := url.Parse(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot parse endpoint %q: %w", e, err)
|
return nil, errors.Wrapf(err, "cannot parse endpoint %q", e)
|
||||||
}
|
}
|
||||||
if scheme == "" {
|
if scheme == "" {
|
||||||
scheme = u.Scheme
|
scheme = u.Scheme
|
||||||
|
@ -108,7 +108,7 @@ func New(cfg Config) (*Store, error) {
|
||||||
var err error
|
var err error
|
||||||
tlsConfig, err = util.NewTLSConfig(cfg.CertFile, cfg.KeyFile, cfg.CAFile, cfg.SkipTLSVerify)
|
tlsConfig, err = util.NewTLSConfig(cfg.CertFile, cfg.KeyFile, cfg.CAFile, cfg.SkipTLSVerify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot create tls config: %w", err)
|
return nil, errors.Wrapf(err, "cannot create tls config")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ func New(cfg Config) (*Store, error) {
|
||||||
|
|
||||||
c, err := etcdclientv3.New(config)
|
c, err := etcdclientv3.New(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.KV = namespace.NewKV(c.KV, prefix)
|
c.KV = namespace.NewKV(c.KV, prefix)
|
||||||
|
@ -150,7 +150,7 @@ func (s *Store) Put(ctx context.Context, key string, value []byte, options *Writ
|
||||||
if options.TTL > 0 {
|
if options.TTL > 0 {
|
||||||
lease, err := s.c.Grant(ctx, int64(options.TTL.Seconds()))
|
lease, err := s.c.Grant(ctx, int64(options.TTL.Seconds()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID))
|
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID))
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ func (s *Store) AtomicPut(ctx context.Context, key string, value []byte, prevRev
|
||||||
if options.TTL > 0 {
|
if options.TTL > 0 {
|
||||||
lease, err := s.c.Grant(ctx, int64(options.TTL))
|
lease, err := s.c.Grant(ctx, int64(options.TTL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID))
|
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID))
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ func (s *Store) AtomicPut(ctx context.Context, key string, value []byte, prevRev
|
||||||
func (s *Store) Delete(ctx context.Context, key string) error {
|
func (s *Store) Delete(ctx context.Context, key string) error {
|
||||||
_, err := s.c.Delete(ctx, key)
|
_, err := s.c.Delete(ctx, key)
|
||||||
|
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeletePrefix(ctx context.Context, prefix string) error {
|
func (s *Store) DeletePrefix(ctx context.Context, prefix string) error {
|
||||||
|
@ -298,7 +298,7 @@ func (s *Store) DeletePrefix(ctx context.Context, prefix string) error {
|
||||||
|
|
||||||
_, err := s.c.Delete(ctx, key, etcdv3Options...)
|
_, err := s.c.Delete(ctx, key, etcdv3Options...)
|
||||||
|
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) AtomicDelete(ctx context.Context, key string, revision int64) (*etcdclientv3.TxnResponse, error) {
|
func (s *Store) AtomicDelete(ctx context.Context, key string, revision int64) (*etcdclientv3.TxnResponse, error) {
|
||||||
|
@ -333,7 +333,7 @@ func (s *Store) Watch(ctx context.Context, prefix string, revision int64) etcdcl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) Close() error {
|
func (s *Store) Close() error {
|
||||||
return s.c.Close()
|
return errors.WithStack(s.c.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) compactor(ctx context.Context, interval time.Duration) {
|
func (s *Store) compactor(ctx context.Context, interval time.Duration) {
|
||||||
|
@ -364,7 +364,7 @@ func (s *Store) compact(ctx context.Context, version, rev int64) (int64, int64,
|
||||||
).Commit()
|
).Commit()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return version, rev, err
|
return version, rev, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
curRev := resp.Header.Revision
|
curRev := resp.Header.Revision
|
||||||
|
@ -380,7 +380,7 @@ func (s *Store) compact(ctx context.Context, version, rev int64) (int64, int64,
|
||||||
}
|
}
|
||||||
if _, err = s.c.Compact(ctx, rev); err != nil {
|
if _, err = s.c.Compact(ctx, rev); err != nil {
|
||||||
s.log.Warn().Msgf("compact error: %v", err)
|
s.log.Warn().Msgf("compact error: %v", err)
|
||||||
return curVersion, curRev, err
|
return curVersion, curRev, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.log.Info().Msgf("compacted revision: %d", rev)
|
s.log.Info().Msgf("compacted revision: %d", rev)
|
||||||
return curVersion, curRev, nil
|
return curVersion, curRev, nil
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
// have the TryLock function not yet available on stable v3.4 client
|
// have the TryLock function not yet available on stable v3.4 client
|
||||||
// Remove this when updating the client to a version providing TryLock
|
// Remove this when updating the client to a version providing TryLock
|
||||||
|
|
||||||
|
//nolint:wrapcheck
|
||||||
package etcd
|
package etcd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -24,10 +24,10 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -109,21 +109,21 @@ func InfoRefsResponse(ctx context.Context, repoPath, serviceName string) ([]byte
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
out, err := git.Output(ctx, nil, serviceName, "--stateless-rpc", "--advertise-refs", repoPath)
|
out, err := git.Output(ctx, nil, serviceName, "--stateless-rpc", "--advertise-refs", repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
buf.Write(out)
|
buf.Write(out)
|
||||||
|
|
||||||
return buf.Bytes(), err
|
return buf.Bytes(), errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitService(ctx context.Context, w io.Writer, r io.Reader, repoPath, serviceName string) error {
|
func gitService(ctx context.Context, w io.Writer, r io.Reader, repoPath, serviceName string) error {
|
||||||
git := &util.Git{GitDir: repoPath}
|
git := &util.Git{GitDir: repoPath}
|
||||||
return git.Pipe(ctx, w, r, serviceName, "--stateless-rpc", repoPath)
|
return errors.WithStack(git.Pipe(ctx, w, r, serviceName, "--stateless-rpc", repoPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitFetchFile(ctx context.Context, w io.Writer, r io.Reader, repoPath, ref, path string) error {
|
func gitFetchFile(ctx context.Context, w io.Writer, r io.Reader, repoPath, ref, path string) error {
|
||||||
git := &util.Git{GitDir: repoPath}
|
git := &util.Git{GitDir: repoPath}
|
||||||
return git.Pipe(ctx, w, r, "show", fmt.Sprintf("%s:%s", ref, path))
|
return errors.WithStack(git.Pipe(ctx, w, r, "show", fmt.Sprintf("%s:%s", ref, path)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrWrongRepoPath = errors.New("wrong repository path")
|
var ErrWrongRepoPath = errors.New("wrong repository path")
|
||||||
|
|
|
@ -20,11 +20,11 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -35,24 +35,24 @@ const (
|
||||||
func copyFile(src, dest string) error {
|
func copyFile(src, dest string) error {
|
||||||
srcf, err := os.Open(src)
|
srcf, err := os.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer srcf.Close()
|
defer srcf.Close()
|
||||||
|
|
||||||
destf, err := os.Create(dest)
|
destf, err := os.Create(dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer destf.Close()
|
defer destf.Close()
|
||||||
|
|
||||||
_, err = io.Copy(destf, srcf)
|
_, err = io.Copy(destf, srcf)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileExists(path string) (bool, error) {
|
func fileExists(path string) (bool, error) {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return false, err
|
return false, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return !os.IsNotExist(err), nil
|
return !os.IsNotExist(err), nil
|
||||||
}
|
}
|
||||||
|
@ -62,24 +62,24 @@ func GitDir() (string, error) {
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
lines, err := git.OutputLines(context.Background(), nil, "rev-parse", "--git-dir")
|
lines, err := git.OutputLines(context.Background(), nil, "rev-parse", "--git-dir")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(lines) != 1 {
|
if len(lines) != 1 {
|
||||||
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
||||||
}
|
}
|
||||||
return lines[0], err
|
return lines[0], errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func currentGitBranch() (string, error) {
|
func currentGitBranch() (string, error) {
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
lines, err := git.OutputLines(context.Background(), nil, "symbolic-ref", "--short", "HEAD")
|
lines, err := git.OutputLines(context.Background(), nil, "symbolic-ref", "--short", "HEAD")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(lines) != 1 {
|
if len(lines) != 1 {
|
||||||
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
||||||
}
|
}
|
||||||
return lines[0], err
|
return lines[0], errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// gitDir returns the git dir relative to the working dir
|
// gitDir returns the git dir relative to the working dir
|
||||||
|
@ -87,60 +87,60 @@ func gitWriteTree(indexPath string) (string, error) {
|
||||||
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
||||||
lines, err := git.OutputLines(context.Background(), nil, "write-tree")
|
lines, err := git.OutputLines(context.Background(), nil, "write-tree")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(lines) != 1 {
|
if len(lines) != 1 {
|
||||||
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
||||||
}
|
}
|
||||||
return lines[0], err
|
return lines[0], errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitCommitTree(message, treeSHA string) (string, error) {
|
func gitCommitTree(message, treeSHA string) (string, error) {
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
lines, err := git.OutputLines(context.Background(), nil, "commit-tree", "-m", message, treeSHA)
|
lines, err := git.OutputLines(context.Background(), nil, "commit-tree", "-m", message, treeSHA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(lines) != 1 {
|
if len(lines) != 1 {
|
||||||
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
return "", errors.Errorf("received %d lines, expected one line", len(lines))
|
||||||
}
|
}
|
||||||
return lines[0], err
|
return lines[0], errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitUpdateRef(message, ref, commitSHA string) error {
|
func gitUpdateRef(message, ref, commitSHA string) error {
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
_, err := git.Output(context.Background(), nil, "update-ref", "-m", message, ref, commitSHA)
|
_, err := git.Output(context.Background(), nil, "update-ref", "-m", message, ref, commitSHA)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitUpdateFiles(indexPath string) error {
|
func gitUpdateFiles(indexPath string) error {
|
||||||
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
||||||
_, err := git.Output(context.Background(), nil, "add", "-u")
|
_, err := git.Output(context.Background(), nil, "add", "-u")
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitAddUntrackedFiles(indexPath string) error {
|
func gitAddUntrackedFiles(indexPath string) error {
|
||||||
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
||||||
_, err := git.Output(context.Background(), nil, "add", ".")
|
_, err := git.Output(context.Background(), nil, "add", ".")
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitAddIgnoredFiles(indexPath string) error {
|
func gitAddIgnoredFiles(indexPath string) error {
|
||||||
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
|
||||||
_, err := git.Output(context.Background(), nil, "add", "-f", "-A", ".")
|
_, err := git.Output(context.Background(), nil, "add", "-f", "-A", ".")
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GitAddRemote(configPath, name, url string) error {
|
func GitAddRemote(configPath, name, url string) error {
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
_, err := git.Output(context.Background(), nil, "remote", "add", name, url)
|
_, err := git.Output(context.Background(), nil, "remote", "add", name, url)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GitPush(configPath, remote, branch string) error {
|
func GitPush(configPath, remote, branch string) error {
|
||||||
git := &util.Git{}
|
git := &util.Git{}
|
||||||
_, err := git.Output(context.Background(), nil, "push", remote, branch, "-f")
|
_, err := git.Output(context.Background(), nil, "push", remote, branch, "-f")
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GitSaveConfig struct {
|
type GitSaveConfig struct {
|
||||||
|
@ -178,7 +178,7 @@ func (s *GitSave) RefsPrefix() string {
|
||||||
func (s *GitSave) Save(message, branchName string) (string, error) {
|
func (s *GitSave) Save(message, branchName string) (string, error) {
|
||||||
gitdir, err := GitDir()
|
gitdir, err := GitDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpIndexPath := filepath.Join(gitdir, "gitsave-index-"+uuid.Must(uuid.NewV4()).String())
|
tmpIndexPath := filepath.Join(gitdir, "gitsave-index-"+uuid.Must(uuid.NewV4()).String())
|
||||||
|
@ -188,25 +188,25 @@ func (s *GitSave) Save(message, branchName string) (string, error) {
|
||||||
|
|
||||||
curBranch, err := currentGitBranch()
|
curBranch, err := currentGitBranch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
indexExists, err := fileExists(indexPath)
|
indexExists, err := fileExists(indexPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if indexExists {
|
if indexExists {
|
||||||
// copy current git index to a temporary index
|
// copy current git index to a temporary index
|
||||||
if err := copyFile(indexPath, tmpIndexPath); err != nil {
|
if err := copyFile(indexPath, tmpIndexPath); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.log.Info().Msgf("created temporary index: %s", tmpIndexPath)
|
s.log.Info().Msgf("created temporary index: %s", tmpIndexPath)
|
||||||
// read the current branch tree information into the index
|
// read the current branch tree information into the index
|
||||||
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + tmpIndexPath}}
|
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + tmpIndexPath}}
|
||||||
_, err = git.Output(context.Background(), nil, "read-tree", curBranch)
|
_, err = git.Output(context.Background(), nil, "read-tree", curBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s.log.Info().Msgf("index %s does not exist", indexPath)
|
s.log.Info().Msgf("index %s does not exist", indexPath)
|
||||||
|
@ -214,40 +214,40 @@ func (s *GitSave) Save(message, branchName string) (string, error) {
|
||||||
|
|
||||||
s.log.Info().Msgf("updating files already in the index")
|
s.log.Info().Msgf("updating files already in the index")
|
||||||
if err := gitUpdateFiles(tmpIndexPath); err != nil {
|
if err := gitUpdateFiles(tmpIndexPath); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.AddUntracked {
|
if s.conf.AddUntracked {
|
||||||
s.log.Info().Msgf("adding untracked files")
|
s.log.Info().Msgf("adding untracked files")
|
||||||
if err := gitAddUntrackedFiles(tmpIndexPath); err != nil {
|
if err := gitAddUntrackedFiles(tmpIndexPath); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.AddIgnored {
|
if s.conf.AddIgnored {
|
||||||
s.log.Info().Msgf("adding ignored files")
|
s.log.Info().Msgf("adding ignored files")
|
||||||
if err := gitAddIgnoredFiles(tmpIndexPath); err != nil {
|
if err := gitAddIgnoredFiles(tmpIndexPath); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log.Info().Msgf("writing tree file")
|
s.log.Info().Msgf("writing tree file")
|
||||||
treeSHA, err := gitWriteTree(tmpIndexPath)
|
treeSHA, err := gitWriteTree(tmpIndexPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.log.Info().Msgf("tree: %s", treeSHA)
|
s.log.Info().Msgf("tree: %s", treeSHA)
|
||||||
|
|
||||||
s.log.Info().Msgf("committing tree")
|
s.log.Info().Msgf("committing tree")
|
||||||
commitSHA, err := gitCommitTree(message, treeSHA)
|
commitSHA, err := gitCommitTree(message, treeSHA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
s.log.Info().Msgf("commit: %s", commitSHA)
|
s.log.Info().Msgf("commit: %s", commitSHA)
|
||||||
|
|
||||||
s.log.Info().Msgf("updating ref")
|
s.log.Info().Msgf("updating ref")
|
||||||
if err = gitUpdateRef("git-save", filepath.Join(s.refsPrefix, branchName), commitSHA); err != nil {
|
if err = gitUpdateRef("git-save", filepath.Join(s.refsPrefix, branchName), commitSHA); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return commitSHA, nil
|
return commitSHA, nil
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gitsource "agola.io/agola/internal/gitsources"
|
gitsource "agola.io/agola/internal/gitsources"
|
||||||
"agola.io/agola/internal/services/types"
|
"agola.io/agola/internal/services/types"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
@ -75,29 +76,31 @@ func (c *Client) SetHTTPClient(client *http.Client) {
|
||||||
func (c *Client) doRequest(method, path string, query url.Values, header http.Header, ibody io.Reader) (*http.Response, error) {
|
func (c *Client) doRequest(method, path string, query url.Values, header http.Header, ibody io.Reader) (*http.Response, error) {
|
||||||
u, err := url.Parse(c.url + "/" + path)
|
u, err := url.Parse(c.url + "/" + path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
u.RawQuery = query.Encode()
|
u.RawQuery = query.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequest(method, u.String(), ibody)
|
req, err := http.NewRequest(method, u.String(), ibody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for k, v := range header {
|
for k, v := range header {
|
||||||
req.Header[k] = v
|
req.Header[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.client.Do(req)
|
res, err := c.client.Do(req)
|
||||||
|
|
||||||
|
return res, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getResponse(method, path string, query url.Values, header http.Header, ibody io.Reader) (*http.Response, error) {
|
func (c *Client) getResponse(method, path string, query url.Values, header http.Header, ibody io.Reader) (*http.Response, error) {
|
||||||
resp, err := c.doRequest(method, path, query, header, ibody)
|
resp, err := c.doRequest(method, path, query, header, ibody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := util.ErrFromRemote(resp); err != nil {
|
if err := util.ErrFromRemote(resp); err != nil {
|
||||||
return resp, err
|
return resp, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
@ -114,12 +117,12 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
||||||
resp, err := c.getResponse("GET", fmt.Sprintf("%s.git/raw/%s/%s", repopath, commit, file), nil, nil, nil)
|
resp, err := c.getResponse("GET", fmt.Sprintf("%s.git/raw/%s/%s", repopath, commit, file), nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
return data, err
|
return data, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
|
@ -174,7 +177,7 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
|
return -1, "", errors.Errorf("unsupported ref: %s", ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
||||||
|
|
|
@ -28,11 +28,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gitsource "agola.io/agola/internal/gitsources"
|
gitsource "agola.io/agola/internal/gitsources"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -146,7 +146,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
|
||||||
var config = c.oauth2Config(callbackURL)
|
var config = c.oauth2Config(callbackURL)
|
||||||
token, err := config.Exchange(ctx, code)
|
token, err := config.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot get oauth2 token: %w", err)
|
return nil, errors.Wrapf(err, "cannot get oauth2 token")
|
||||||
}
|
}
|
||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,9 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
|
||||||
var config = c.oauth2Config("")
|
var config = c.oauth2Config("")
|
||||||
token := &oauth2.Token{RefreshToken: refreshToken}
|
token := &oauth2.Token{RefreshToken: refreshToken}
|
||||||
ts := config.TokenSource(ctx, token)
|
ts := config.TokenSource(ctx, token)
|
||||||
return ts.Token()
|
ntoken, err := ts.Token()
|
||||||
|
|
||||||
|
return ntoken, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) LoginPassword(username, password, tokenName string) (string, error) {
|
func (c *Client) LoginPassword(username, password, tokenName string) (string, error) {
|
||||||
|
@ -172,16 +174,16 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
|
||||||
tokens := make([]*gitea.AccessToken, 0, 10)
|
tokens := make([]*gitea.AccessToken, 0, 10)
|
||||||
req, err := http.NewRequest("GET", c.APIURL+"/api/v1"+fmt.Sprintf("/users/%s/tokens", username), nil)
|
req, err := http.NewRequest("GET", c.APIURL+"/api/v1"+fmt.Sprintf("/users/%s/tokens", username), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))
|
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))
|
||||||
|
|
||||||
resp, err := c.oauth2HTTPClient.Do(req)
|
resp, err := c.oauth2HTTPClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if resp.StatusCode == http.StatusUnauthorized {
|
if resp.StatusCode == http.StatusUnauthorized {
|
||||||
return "", gitsource.ErrUnauthorized
|
return "", errors.WithStack(gitsource.ErrUnauthorized)
|
||||||
}
|
}
|
||||||
if resp.StatusCode/100 != 2 {
|
if resp.StatusCode/100 != 2 {
|
||||||
return "", errors.Errorf("gitea api status code %d", resp.StatusCode)
|
return "", errors.Errorf("gitea api status code %d", resp.StatusCode)
|
||||||
|
@ -190,7 +192,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
|
||||||
|
|
||||||
dec := json.NewDecoder(resp.Body)
|
dec := json.NewDecoder(resp.Body)
|
||||||
if err := dec.Decode(&tokens); err != nil {
|
if err := dec.Decode(&tokens); err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
if token.Name == tokenName {
|
if token.Name == tokenName {
|
||||||
|
@ -206,7 +208,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
|
||||||
gitea.CreateAccessTokenOption{Name: tokenName},
|
gitea.CreateAccessTokenOption{Name: tokenName},
|
||||||
)
|
)
|
||||||
if terr != nil {
|
if terr != nil {
|
||||||
return "", terr
|
return "", errors.WithStack(terr)
|
||||||
}
|
}
|
||||||
accessToken = token.Token
|
accessToken = token.Token
|
||||||
}
|
}
|
||||||
|
@ -217,7 +219,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
|
||||||
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
user, err := c.client.GetMyUserInfo()
|
user, err := c.client.GetMyUserInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return &gitsource.UserInfo{
|
return &gitsource.UserInfo{
|
||||||
ID: strconv.FormatInt(user.ID, 10),
|
ID: strconv.FormatInt(user.ID, 10),
|
||||||
|
@ -229,11 +231,11 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
rr, err := c.client.GetRepo(owner, reponame)
|
rr, err := c.client.GetRepo(owner, reponame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return fromGiteaRepo(rr), nil
|
return fromGiteaRepo(rr), nil
|
||||||
}
|
}
|
||||||
|
@ -241,23 +243,23 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
data, err := c.client.GetFile(owner, reponame, commit, file)
|
data, err := c.client.GetFile(owner, reponame, commit, file)
|
||||||
return data, err
|
return data, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, err = c.client.CreateDeployKey(owner, reponame, gitea.CreateKeyOption{
|
if _, err = c.client.CreateDeployKey(owner, reponame, gitea.CreateKeyOption{
|
||||||
Title: title,
|
Title: title,
|
||||||
Key: pubKey,
|
Key: pubKey,
|
||||||
ReadOnly: readonly,
|
ReadOnly: readonly,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Errorf("error creating deploy key: %w", err)
|
return errors.Wrapf(err, "error creating deploy key")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -266,7 +268,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// NOTE(sgotti) gitea has a bug where if we delete and remove the same key with
|
// NOTE(sgotti) gitea has a bug where if we delete and remove the same key with
|
||||||
// the same value it is correctly readded and the admin must force a
|
// the same value it is correctly readded and the admin must force a
|
||||||
|
@ -274,7 +276,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
// when the public key value has changed
|
// when the public key value has changed
|
||||||
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
|
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving existing deploy keys: %w", err)
|
return errors.Wrapf(err, "error retrieving existing deploy keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
|
@ -283,7 +285,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != nil {
|
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != nil {
|
||||||
return errors.Errorf("error removing existing deploy key: %w", err)
|
return errors.Wrapf(err, "error removing existing deploy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,7 +295,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
Key: pubKey,
|
Key: pubKey,
|
||||||
ReadOnly: readonly,
|
ReadOnly: readonly,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Errorf("error creating deploy key: %w", err)
|
return errors.Wrapf(err, "error creating deploy key")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -302,17 +304,17 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
func (c *Client) DeleteDeployKey(repopath, title string) error {
|
func (c *Client) DeleteDeployKey(repopath, title string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
|
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving existing deploy keys: %w", err)
|
return errors.Wrapf(err, "error retrieving existing deploy keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if key.Title == title {
|
if key.Title == title {
|
||||||
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != nil {
|
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != nil {
|
||||||
return errors.Errorf("error removing existing deploy key: %w", err)
|
return errors.Wrapf(err, "error removing existing deploy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,7 +325,7 @@ func (c *Client) DeleteDeployKey(repopath, title string) error {
|
||||||
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := gitea.CreateHookOption{
|
opts := gitea.CreateHookOption{
|
||||||
|
@ -338,7 +340,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = c.client.CreateRepoHook(owner, reponame, opts); err != nil {
|
if _, err = c.client.CreateRepoHook(owner, reponame, opts); err != nil {
|
||||||
return errors.Errorf("error creating repository webhook: %w", err)
|
return errors.Wrapf(err, "error creating repository webhook")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -347,11 +349,11 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
hooks, err := c.client.ListRepoHooks(owner, reponame, gitea.ListHooksOptions{})
|
hooks, err := c.client.ListRepoHooks(owner, reponame, gitea.ListHooksOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving repository webhooks: %w", err)
|
return errors.Wrapf(err, "error retrieving repository webhooks")
|
||||||
}
|
}
|
||||||
|
|
||||||
// match the full url so we can have multiple webhooks for different agola
|
// match the full url so we can have multiple webhooks for different agola
|
||||||
|
@ -359,7 +361,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
if hook.Config["url"] == u {
|
if hook.Config["url"] == u {
|
||||||
if err := c.client.DeleteRepoHook(owner, reponame, hook.ID); err != nil {
|
if err := c.client.DeleteRepoHook(owner, reponame, hook.ID); err != nil {
|
||||||
return errors.Errorf("error deleting existing repository webhook: %w", err)
|
return errors.Wrapf(err, "error deleting existing repository webhook")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +372,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, context string) error {
|
func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, context string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
_, err = c.client.CreateStatus(owner, reponame, commitSHA, gitea.CreateStatusOption{
|
_, err = c.client.CreateStatus(owner, reponame, commitSHA, gitea.CreateStatusOption{
|
||||||
State: fromCommitStatus(status),
|
State: fromCommitStatus(status),
|
||||||
|
@ -378,7 +380,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
|
||||||
Description: description,
|
Description: description,
|
||||||
Context: context,
|
Context: context,
|
||||||
})
|
})
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
||||||
|
@ -396,7 +398,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*gitsource.RepoInfo{}, err
|
return []*gitsource.RepoInfo{}, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range remoteRepos {
|
for _, repo := range remoteRepos {
|
||||||
|
@ -429,12 +431,12 @@ func fromGiteaRepo(rr *gitea.Repository) *gitsource.RepoInfo {
|
||||||
func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteRefs, err := c.client.GetRepoRefs(owner, reponame, ref)
|
remoteRefs, err := c.client.GetRepoRefs(owner, reponame, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if len(remoteRefs) == 0 {
|
if len(remoteRefs) == 0 {
|
||||||
return nil, errors.Errorf("no ref %q for repository %q", ref, repopath)
|
return nil, errors.Errorf("no ref %q for repository %q", ref, repopath)
|
||||||
|
@ -480,12 +482,12 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
|
||||||
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commit, err := c.client.GetSingleCommit(owner, reponame, commitSHA)
|
commit, err := c.client.GetSingleCommit(owner, reponame, commitSHA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gitsource.Commit{
|
return &gitsource.Commit{
|
||||||
|
|
|
@ -27,9 +27,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/services/types"
|
"agola.io/agola/internal/services/types"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -48,7 +47,7 @@ const (
|
||||||
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
|
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
|
||||||
data, err := ioutil.ReadAll(io.LimitReader(r.Body, 10*1024*1024))
|
data, err := ioutil.ReadAll(io.LimitReader(r.Body, 10*1024*1024))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify signature
|
// verify signature
|
||||||
|
@ -83,7 +82,7 @@ func parsePushHook(data []byte) (*types.WebhookData, error) {
|
||||||
push := new(pushHook)
|
push := new(pushHook)
|
||||||
err := json.Unmarshal(data, push)
|
err := json.Unmarshal(data, push)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return webhookDataFromPush(push)
|
return webhookDataFromPush(push)
|
||||||
|
@ -93,7 +92,7 @@ func parsePullRequestHook(data []byte) (*types.WebhookData, error) {
|
||||||
prhook := new(pullRequestHook)
|
prhook := new(pullRequestHook)
|
||||||
err := json.Unmarshal(data, prhook)
|
err := json.Unmarshal(data, prhook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip non open pull requests
|
// skip non open pull requests
|
||||||
|
@ -144,7 +143,7 @@ func webhookDataFromPush(hook *pushHook) (*types.WebhookData, error) {
|
||||||
whd.Message = fmt.Sprintf("Tag %s", whd.Tag)
|
whd.Message = fmt.Sprintf("Tag %s", whd.Tag)
|
||||||
default:
|
default:
|
||||||
// ignore received webhook since it doesn't have a ref we're interested in
|
// ignore received webhook since it doesn't have a ref we're interested in
|
||||||
return nil, fmt.Errorf("unsupported webhook ref %q", hook.Ref)
|
return nil, errors.Errorf("unsupported webhook ref %q", hook.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
return whd, nil
|
return whd, nil
|
||||||
|
|
|
@ -28,11 +28,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gitsource "agola.io/agola/internal/gitsources"
|
gitsource "agola.io/agola/internal/gitsources"
|
||||||
|
|
||||||
"github.com/google/go-github/v29/github"
|
"github.com/google/go-github/v29/github"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -81,7 +81,7 @@ func fromCommitStatus(status gitsource.CommitStatus) string {
|
||||||
case gitsource.CommitStatusFailed:
|
case gitsource.CommitStatusFailed:
|
||||||
return "failure"
|
return "failure"
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown commit status %q", status))
|
panic(errors.Errorf("unknown commit status %q", status))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,8 @@ func (t *TokenTransport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||||
if t.token != "" {
|
if t.token != "" {
|
||||||
r.Header.Set("Authorization", "Bearer "+t.token)
|
r.Header.Set("Authorization", "Bearer "+t.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:wrapcheck
|
||||||
return t.rt.RoundTrip(r)
|
return t.rt.RoundTrip(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +186,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
|
||||||
var config = c.oauth2Config(callbackURL)
|
var config = c.oauth2Config(callbackURL)
|
||||||
token, err := config.Exchange(ctx, code)
|
token, err := config.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot get oauth2 token: %w", err)
|
return nil, errors.Wrapf(err, "cannot get oauth2 token")
|
||||||
}
|
}
|
||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
@ -196,13 +198,15 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
|
||||||
var config = c.oauth2Config("")
|
var config = c.oauth2Config("")
|
||||||
token := &oauth2.Token{RefreshToken: refreshToken}
|
token := &oauth2.Token{RefreshToken: refreshToken}
|
||||||
ts := config.TokenSource(ctx, token)
|
ts := config.TokenSource(ctx, token)
|
||||||
return ts.Token()
|
ntoken, err := ts.Token()
|
||||||
|
|
||||||
|
return ntoken, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
user, _, err := c.client.Users.Get(context.TODO(), "")
|
user, _, err := c.client.Users.Get(context.TODO(), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo := &gitsource.UserInfo{
|
userInfo := &gitsource.UserInfo{
|
||||||
|
@ -219,11 +223,11 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
rr, _, err := c.client.Repositories.Get(context.TODO(), owner, reponame)
|
rr, _, err := c.client.Repositories.Get(context.TODO(), owner, reponame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return fromGithubRepo(rr), nil
|
return fromGithubRepo(rr), nil
|
||||||
}
|
}
|
||||||
|
@ -231,28 +235,29 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
r, err := c.client.Repositories.DownloadContents(context.TODO(), owner, reponame, file, &github.RepositoryContentGetOptions{Ref: commit})
|
r, err := c.client.Repositories.DownloadContents(context.TODO(), owner, reponame, file, &github.RepositoryContentGetOptions{Ref: commit})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
return ioutil.ReadAll(r)
|
d, err := ioutil.ReadAll(r)
|
||||||
|
return d, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, _, err = c.client.Repositories.CreateKey(context.TODO(), owner, reponame, &github.Key{
|
if _, _, err = c.client.Repositories.CreateKey(context.TODO(), owner, reponame, &github.Key{
|
||||||
Title: github.String(title),
|
Title: github.String(title),
|
||||||
Key: github.String(pubKey),
|
Key: github.String(pubKey),
|
||||||
ReadOnly: github.Bool(readonly),
|
ReadOnly: github.Bool(readonly),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Errorf("error creating deploy key: %w", err)
|
return errors.Wrapf(err, "error creating deploy key")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -260,7 +265,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// NOTE(sgotti) gitea has a bug where if we delete and remove the same key with
|
// NOTE(sgotti) gitea has a bug where if we delete and remove the same key with
|
||||||
// the same value it is correctly readded and the admin must force a
|
// the same value it is correctly readded and the admin must force a
|
||||||
|
@ -268,7 +273,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
// when the public key value has changed
|
// when the public key value has changed
|
||||||
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
|
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving existing deploy keys: %w", err)
|
return errors.Wrapf(err, "error retrieving existing deploy keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
|
@ -277,7 +282,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != nil {
|
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != nil {
|
||||||
return errors.Errorf("error removing existing deploy key: %w", err)
|
return errors.Wrapf(err, "error removing existing deploy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,7 +292,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
Key: github.String(pubKey),
|
Key: github.String(pubKey),
|
||||||
ReadOnly: github.Bool(readonly),
|
ReadOnly: github.Bool(readonly),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Errorf("error creating deploy key: %w", err)
|
return errors.Wrapf(err, "error creating deploy key")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -296,17 +301,17 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
func (c *Client) DeleteDeployKey(repopath, title string) error {
|
func (c *Client) DeleteDeployKey(repopath, title string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
|
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving existing deploy keys: %w", err)
|
return errors.Wrapf(err, "error retrieving existing deploy keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if *key.Title == title {
|
if *key.Title == title {
|
||||||
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != nil {
|
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != nil {
|
||||||
return errors.Errorf("error removing existing deploy key: %w", err)
|
return errors.Wrapf(err, "error removing existing deploy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,7 +322,7 @@ func (c *Client) DeleteDeployKey(repopath, title string) error {
|
||||||
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hook := &github.Hook{
|
hook := &github.Hook{
|
||||||
|
@ -331,7 +336,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, err = c.client.Repositories.CreateHook(context.TODO(), owner, reponame, hook); err != nil {
|
if _, _, err = c.client.Repositories.CreateHook(context.TODO(), owner, reponame, hook); err != nil {
|
||||||
return errors.Errorf("error creating repository webhook: %w", err)
|
return errors.Wrapf(err, "error creating repository webhook")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -340,7 +345,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks := []*github.Hook{}
|
hooks := []*github.Hook{}
|
||||||
|
@ -349,7 +354,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
for {
|
for {
|
||||||
pHooks, resp, err := c.client.Repositories.ListHooks(context.TODO(), owner, reponame, opt)
|
pHooks, resp, err := c.client.Repositories.ListHooks(context.TODO(), owner, reponame, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving repository webhooks: %w", err)
|
return errors.Wrapf(err, "error retrieving repository webhooks")
|
||||||
}
|
}
|
||||||
hooks = append(hooks, pHooks...)
|
hooks = append(hooks, pHooks...)
|
||||||
if resp.NextPage == 0 {
|
if resp.NextPage == 0 {
|
||||||
|
@ -363,7 +368,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
if hook.Config["url"] == u {
|
if hook.Config["url"] == u {
|
||||||
if _, err := c.client.Repositories.DeleteHook(context.TODO(), owner, reponame, *hook.ID); err != nil {
|
if _, err := c.client.Repositories.DeleteHook(context.TODO(), owner, reponame, *hook.ID); err != nil {
|
||||||
return errors.Errorf("error deleting existing repository webhook: %w", err)
|
return errors.Wrapf(err, "error deleting existing repository webhook")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,7 +379,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, statusContext string) error {
|
func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, statusContext string) error {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
_, _, err = c.client.Repositories.CreateStatus(context.TODO(), owner, reponame, commitSHA, &github.RepoStatus{
|
_, _, err = c.client.Repositories.CreateStatus(context.TODO(), owner, reponame, commitSHA, &github.RepoStatus{
|
||||||
State: github.String(fromCommitStatus(status)),
|
State: github.String(fromCommitStatus(status)),
|
||||||
|
@ -382,7 +387,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
|
||||||
Description: github.String(description),
|
Description: github.String(description),
|
||||||
Context: github.String(statusContext),
|
Context: github.String(statusContext),
|
||||||
})
|
})
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
||||||
|
@ -392,7 +397,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
||||||
for {
|
for {
|
||||||
pRemoteRepos, resp, err := c.client.Repositories.List(context.TODO(), "", opt)
|
pRemoteRepos, resp, err := c.client.Repositories.List(context.TODO(), "", opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
remoteRepos = append(remoteRepos, pRemoteRepos...)
|
remoteRepos = append(remoteRepos, pRemoteRepos...)
|
||||||
if resp.NextPage == 0 {
|
if resp.NextPage == 0 {
|
||||||
|
@ -429,12 +434,12 @@ func fromGithubRepo(rr *github.Repository) *gitsource.RepoInfo {
|
||||||
func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteRef, _, err := c.client.Git.GetRef(context.TODO(), owner, reponame, ref)
|
remoteRef, _, err := c.client.Git.GetRef(context.TODO(), owner, reponame, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromGithubRef(remoteRef)
|
return fromGithubRef(remoteRef)
|
||||||
|
@ -445,7 +450,7 @@ func fromGithubRef(remoteRef *github.Reference) (*gitsource.Ref, error) {
|
||||||
switch t {
|
switch t {
|
||||||
case "commit":
|
case "commit":
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported object type: %s", t)
|
return nil, errors.Errorf("unsupported object type: %s", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gitsource.Ref{
|
return &gitsource.Ref{
|
||||||
|
@ -467,19 +472,19 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
|
||||||
return gitsource.RefTypePullRequest, m[1], nil
|
return gitsource.RefTypePullRequest, m[1], nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
|
return -1, "", errors.Errorf("unsupported ref: %s", ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
||||||
owner, reponame, err := parseRepoPath(repopath)
|
owner, reponame, err := parseRepoPath(repopath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commit, _, err := c.client.Git.GetCommit(context.TODO(), owner, reponame, commitSHA)
|
commit, _, err := c.client.Git.GetCommit(context.TODO(), owner, reponame, commitSHA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gitsource.Commit{
|
return &gitsource.Commit{
|
||||||
|
|
|
@ -21,10 +21,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/services/types"
|
"agola.io/agola/internal/services/types"
|
||||||
|
|
||||||
"github.com/google/go-github/v29/github"
|
"github.com/google/go-github/v29/github"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -37,12 +37,12 @@ const (
|
||||||
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
|
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
|
||||||
payload, err := github.ValidatePayload(r, []byte(secret))
|
payload, err := github.ValidatePayload(r, []byte(secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("wrong webhook signature: %w", err)
|
return nil, errors.Wrapf(err, "wrong webhook signature")
|
||||||
}
|
}
|
||||||
webHookType := github.WebHookType(r)
|
webHookType := github.WebHookType(r)
|
||||||
event, err := github.ParseWebHook(webHookType, payload)
|
event, err := github.ParseWebHook(webHookType, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to parse webhook: %w", err)
|
return nil, errors.Wrapf(err, "failed to parse webhook")
|
||||||
}
|
}
|
||||||
switch event := event.(type) {
|
switch event := event.(type) {
|
||||||
case *github.PushEvent:
|
case *github.PushEvent:
|
||||||
|
@ -96,7 +96,7 @@ func webhookDataFromPush(hook *github.PushEvent) (*types.WebhookData, error) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// ignore received webhook since it doesn't have a ref we're interested in
|
// ignore received webhook since it doesn't have a ref we're interested in
|
||||||
return nil, fmt.Errorf("unsupported webhook ref %q", *hook.Ref)
|
return nil, errors.Errorf("unsupported webhook ref %q", *hook.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
return whd, nil
|
return whd, nil
|
||||||
|
|
|
@ -26,11 +26,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gitsource "agola.io/agola/internal/gitsources"
|
gitsource "agola.io/agola/internal/gitsources"
|
||||||
|
|
||||||
gitlab "github.com/xanzy/go-gitlab"
|
gitlab "github.com/xanzy/go-gitlab"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -70,7 +70,7 @@ func fromCommitStatus(status gitsource.CommitStatus) gitlab.BuildStateValue {
|
||||||
case gitsource.CommitStatusFailed:
|
case gitsource.CommitStatusFailed:
|
||||||
return gitlab.Failed
|
return gitlab.Failed
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown commit status %q", status))
|
panic(errors.Errorf("unknown commit status %q", status))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ func New(opts Opts) (*Client, error) {
|
||||||
|
|
||||||
client := gitlab.NewOAuthClient(httpClient, opts.Token)
|
client := gitlab.NewOAuthClient(httpClient, opts.Token)
|
||||||
if err := client.SetBaseURL(opts.APIURL); err != nil {
|
if err := client.SetBaseURL(opts.APIURL); err != nil {
|
||||||
return nil, errors.Errorf("failed to set gitlab client base url: %w", err)
|
return nil, errors.Wrapf(err, "failed to set gitlab client base url")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
|
@ -130,7 +130,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
|
||||||
var config = c.oauth2Config(callbackURL)
|
var config = c.oauth2Config(callbackURL)
|
||||||
token, err := config.Exchange(ctx, code)
|
token, err := config.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot get oauth2 token: %w", err)
|
return nil, errors.Wrapf(err, "cannot get oauth2 token")
|
||||||
}
|
}
|
||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
@ -142,13 +142,15 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
|
||||||
var config = c.oauth2Config("")
|
var config = c.oauth2Config("")
|
||||||
token := &oauth2.Token{RefreshToken: refreshToken}
|
token := &oauth2.Token{RefreshToken: refreshToken}
|
||||||
ts := config.TokenSource(ctx, token)
|
ts := config.TokenSource(ctx, token)
|
||||||
return ts.Token()
|
ntoken, err := ts.Token()
|
||||||
|
|
||||||
|
return ntoken, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
rr, _, err := c.client.Projects.GetProject(repopath, nil)
|
rr, _, err := c.client.Projects.GetProject(repopath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return fromGitlabRepo(rr), nil
|
return fromGitlabRepo(rr), nil
|
||||||
}
|
}
|
||||||
|
@ -156,7 +158,7 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
user, _, err := c.client.Users.CurrentUser()
|
user, _, err := c.client.Users.CurrentUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return &gitsource.UserInfo{
|
return &gitsource.UserInfo{
|
||||||
ID: strconv.Itoa(user.ID),
|
ID: strconv.Itoa(user.ID),
|
||||||
|
@ -168,13 +170,13 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
||||||
f, _, err := c.client.RepositoryFiles.GetFile(repopath, file, &gitlab.GetFileOptions{Ref: gitlab.String(commit)})
|
f, _, err := c.client.RepositoryFiles.GetFile(repopath, file, &gitlab.GetFileOptions{Ref: gitlab.String(commit)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
data, err := base64.StdEncoding.DecodeString(f.Content)
|
data, err := base64.StdEncoding.DecodeString(f.Content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return data, err
|
return data, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
|
@ -182,7 +184,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
Title: gitlab.String(title),
|
Title: gitlab.String(title),
|
||||||
Key: gitlab.String(pubKey),
|
Key: gitlab.String(pubKey),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Errorf("error creating deploy key: %w", err)
|
return errors.Wrapf(err, "error creating deploy key")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -191,7 +193,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
|
||||||
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
|
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving existing deploy keys: %w", err)
|
return errors.Wrapf(err, "error retrieving existing deploy keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
|
@ -200,7 +202,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != nil {
|
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != nil {
|
||||||
return errors.Errorf("error removing existing deploy key: %w", err)
|
return errors.Wrapf(err, "error removing existing deploy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +211,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
Title: &title,
|
Title: &title,
|
||||||
Key: &pubKey,
|
Key: &pubKey,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Errorf("error creating deploy key: %w", err)
|
return errors.Wrapf(err, "error creating deploy key")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -218,13 +220,13 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
|
||||||
func (c *Client) DeleteDeployKey(repopath, title string) error {
|
func (c *Client) DeleteDeployKey(repopath, title string) error {
|
||||||
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
|
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving existing deploy keys: %w", err)
|
return errors.Wrapf(err, "error retrieving existing deploy keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if key.Title == title {
|
if key.Title == title {
|
||||||
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != nil {
|
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != nil {
|
||||||
return errors.Errorf("error removing existing deploy key: %w", err)
|
return errors.Wrapf(err, "error removing existing deploy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,7 +243,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
Token: gitlab.String(secret),
|
Token: gitlab.String(secret),
|
||||||
}
|
}
|
||||||
if _, _, err := c.client.Projects.AddProjectHook(repopath, opts); err != nil {
|
if _, _, err := c.client.Projects.AddProjectHook(repopath, opts); err != nil {
|
||||||
return errors.Errorf("error creating repository webhook: %w", err)
|
return errors.Wrapf(err, "error creating repository webhook")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -250,7 +252,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
|
||||||
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
hooks, _, err := c.client.Projects.ListProjectHooks(repopath, nil)
|
hooks, _, err := c.client.Projects.ListProjectHooks(repopath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error retrieving repository webhooks: %w", err)
|
return errors.Wrapf(err, "error retrieving repository webhooks")
|
||||||
}
|
}
|
||||||
|
|
||||||
// match the full url so we can have multiple webhooks for different agola
|
// match the full url so we can have multiple webhooks for different agola
|
||||||
|
@ -258,7 +260,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
if hook.URL == u {
|
if hook.URL == u {
|
||||||
if _, err := c.client.Projects.DeleteProjectHook(repopath, hook.ID); err != nil {
|
if _, err := c.client.Projects.DeleteProjectHook(repopath, hook.ID); err != nil {
|
||||||
return errors.Errorf("error deleting existing repository webhook: %w", err)
|
return errors.Wrapf(err, "error deleting existing repository webhook")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,7 +275,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
|
||||||
Description: gitlab.String(description),
|
Description: gitlab.String(description),
|
||||||
Context: gitlab.String(context),
|
Context: gitlab.String(context),
|
||||||
})
|
})
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
||||||
|
@ -281,7 +283,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
|
||||||
opts := &gitlab.ListProjectsOptions{MinAccessLevel: gitlab.AccessLevel(gitlab.MaintainerPermissions)}
|
opts := &gitlab.ListProjectsOptions{MinAccessLevel: gitlab.AccessLevel(gitlab.MaintainerPermissions)}
|
||||||
remoteRepos, _, err := c.client.Projects.ListProjects(opts)
|
remoteRepos, _, err := c.client.Projects.ListProjects(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repos := []*gitsource.RepoInfo{}
|
repos := []*gitsource.RepoInfo{}
|
||||||
|
@ -311,7 +313,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
||||||
branch := strings.TrimPrefix(ref, "refs/heads/")
|
branch := strings.TrimPrefix(ref, "refs/heads/")
|
||||||
remoteBranch, _, err := c.client.Branches.GetBranch(repopath, branch)
|
remoteBranch, _, err := c.client.Branches.GetBranch(repopath, branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gitsource.Ref{
|
return &gitsource.Ref{
|
||||||
|
@ -323,7 +325,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
||||||
tag := strings.TrimPrefix(ref, "refs/heads/")
|
tag := strings.TrimPrefix(ref, "refs/heads/")
|
||||||
remoteTag, _, err := c.client.Tags.GetTag(repopath, tag)
|
remoteTag, _, err := c.client.Tags.GetTag(repopath, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gitsource.Ref{
|
return &gitsource.Ref{
|
||||||
|
@ -331,7 +333,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
|
||||||
CommitSHA: remoteTag.Commit.ID,
|
CommitSHA: remoteTag.Commit.ID,
|
||||||
}, nil
|
}, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported ref: %s", ref)
|
return nil, errors.Errorf("unsupported ref: %s", ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,14 +350,14 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
|
||||||
return gitsource.RefTypePullRequest, m[1], nil
|
return gitsource.RefTypePullRequest, m[1], nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
|
return -1, "", errors.Errorf("unsupported ref: %s", ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
|
||||||
commit, _, err := c.client.Commits.GetCommit(repopath, commitSHA, nil)
|
commit, _, err := c.client.Commits.GetCommit(repopath, commitSHA, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gitsource.Commit{
|
return &gitsource.Commit{
|
||||||
|
|
|
@ -23,9 +23,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/services/types"
|
"agola.io/agola/internal/services/types"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -40,7 +39,7 @@ const (
|
||||||
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
|
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
|
||||||
data, err := ioutil.ReadAll(io.LimitReader(r.Body, 10*1024*1024))
|
data, err := ioutil.ReadAll(io.LimitReader(r.Body, 10*1024*1024))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify token (gitlab doesn't sign the payload but just returns the provided
|
// verify token (gitlab doesn't sign the payload but just returns the provided
|
||||||
|
@ -68,7 +67,7 @@ func parsePushHook(data []byte) (*types.WebhookData, error) {
|
||||||
push := new(pushHook)
|
push := new(pushHook)
|
||||||
err := json.Unmarshal(data, push)
|
err := json.Unmarshal(data, push)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip push events with 0 commits. i.e. a tag deletion.
|
// skip push events with 0 commits. i.e. a tag deletion.
|
||||||
|
@ -83,7 +82,7 @@ func parsePullRequestHook(data []byte) (*types.WebhookData, error) {
|
||||||
prhook := new(pullRequestHook)
|
prhook := new(pullRequestHook)
|
||||||
err := json.Unmarshal(data, prhook)
|
err := json.Unmarshal(data, prhook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sgotti) skip non open pull requests
|
// TODO(sgotti) skip non open pull requests
|
||||||
|
@ -127,7 +126,7 @@ func webhookDataFromPush(hook *pushHook) (*types.WebhookData, error) {
|
||||||
whd.Message = fmt.Sprintf("Tag %s", whd.Tag)
|
whd.Message = fmt.Sprintf("Tag %s", whd.Tag)
|
||||||
default:
|
default:
|
||||||
// ignore received webhook since it doesn't have a ref we're interested in
|
// ignore received webhook since it doesn't have a ref we're interested in
|
||||||
return nil, fmt.Errorf("unsupported webhook ref %q", hook.Ref)
|
return nil, errors.Errorf("unsupported webhook ref %q", hook.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
return whd, nil
|
return whd, nil
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
package gitsource
|
package gitsource
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/services/types"
|
"agola.io/agola/internal/services/types"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// writeFileAtomicFunc atomically writes a file, it achieves this by creating a
|
// writeFileAtomicFunc atomically writes a file, it achieves this by creating a
|
||||||
|
@ -30,7 +32,7 @@ import (
|
||||||
func writeFileAtomicFunc(p, baseDir, tmpDir string, perm os.FileMode, persist bool, writeFunc func(f io.Writer) error) error {
|
func writeFileAtomicFunc(p, baseDir, tmpDir string, perm os.FileMode, persist bool, writeFunc func(f io.Writer) error) error {
|
||||||
f, err := ioutil.TempFile(tmpDir, "tmpfile")
|
f, err := ioutil.TempFile(tmpDir, "tmpfile")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
err = writeFunc(f)
|
err = writeFunc(f)
|
||||||
if persist && err == nil {
|
if persist && err == nil {
|
||||||
|
@ -47,7 +49,7 @@ func writeFileAtomicFunc(p, baseDir, tmpDir string, perm os.FileMode, persist bo
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(f.Name())
|
os.Remove(f.Name())
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !persist {
|
if !persist {
|
||||||
|
@ -80,7 +82,7 @@ func writeFileAtomic(filename, baseDir, tmpDir string, perm os.FileMode, persist
|
||||||
return writeFileAtomicFunc(filename, baseDir, tmpDir, perm, persist,
|
return writeFileAtomicFunc(filename, baseDir, tmpDir, perm, persist,
|
||||||
func(f io.Writer) error {
|
func(f io.Writer) error {
|
||||||
_, err := f.Write(data)
|
_, err := f.Write(data)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
"agola.io/agola/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
|
@ -36,10 +36,12 @@ type Storage interface {
|
||||||
|
|
||||||
type ErrNotExist struct {
|
type ErrNotExist struct {
|
||||||
err error
|
err error
|
||||||
|
|
||||||
|
*errors.Stack
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewErrNotExist(err error) error {
|
func NewErrNotExist(err error) error {
|
||||||
return &ErrNotExist{err: err}
|
return &ErrNotExist{err: err, Stack: errors.Callers(0)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ErrNotExist) Error() string {
|
func (e *ErrNotExist) Error() string {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
"agola.io/agola/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -36,15 +36,15 @@ type PosixStorage struct {
|
||||||
|
|
||||||
func NewPosix(baseDir string) (*PosixStorage, error) {
|
func NewPosix(baseDir string) (*PosixStorage, error) {
|
||||||
if err := os.MkdirAll(baseDir, 0770); err != nil {
|
if err := os.MkdirAll(baseDir, 0770); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataDir := filepath.Join(baseDir, dataDirName)
|
dataDir := filepath.Join(baseDir, dataDirName)
|
||||||
tmpDir := filepath.Join(baseDir, tmpDirName)
|
tmpDir := filepath.Join(baseDir, tmpDirName)
|
||||||
if err := os.MkdirAll(dataDir, 0770); err != nil {
|
if err := os.MkdirAll(dataDir, 0770); err != nil {
|
||||||
return nil, errors.Errorf("failed to create data dir: %w", err)
|
return nil, errors.Wrapf(err, "failed to create data dir")
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(tmpDir, 0770); err != nil {
|
if err := os.MkdirAll(tmpDir, 0770); err != nil {
|
||||||
return nil, errors.Errorf("failed to create tmp dir: %w", err)
|
return nil, errors.Wrapf(err, "failed to create tmp dir")
|
||||||
}
|
}
|
||||||
return &PosixStorage{
|
return &PosixStorage{
|
||||||
dataDir: dataDir,
|
dataDir: dataDir,
|
||||||
|
@ -59,7 +59,7 @@ func (s *PosixStorage) fsPath(p string) (string, error) {
|
||||||
func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
|
func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fi, err := os.Stat(fspath)
|
fi, err := os.Stat(fspath)
|
||||||
|
@ -67,7 +67,7 @@ func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ObjectInfo{Path: p, LastModified: fi.ModTime(), Size: fi.Size()}, nil
|
return &ObjectInfo{Path: p, LastModified: fi.ModTime(), Size: fi.Size()}, nil
|
||||||
|
@ -76,24 +76,24 @@ func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
|
||||||
func (s *PosixStorage) ReadObject(p string) (ReadSeekCloser, error) {
|
func (s *PosixStorage) ReadObject(p string) (ReadSeekCloser, error) {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(fspath)
|
f, err := os.Open(fspath)
|
||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return f, err
|
return f, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PosixStorage) WriteObject(p string, data io.Reader, size int64, persist bool) error {
|
func (s *PosixStorage) WriteObject(p string, data io.Reader, size int64, persist bool) error {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Dir(fspath), 0770); err != nil {
|
if err := os.MkdirAll(path.Dir(fspath), 0770); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := data
|
r := data
|
||||||
|
@ -102,21 +102,21 @@ func (s *PosixStorage) WriteObject(p string, data io.Reader, size int64, persist
|
||||||
}
|
}
|
||||||
return writeFileAtomicFunc(fspath, s.dataDir, s.tmpDir, 0660, persist, func(f io.Writer) error {
|
return writeFileAtomicFunc(fspath, s.dataDir, s.tmpDir, 0660, persist, func(f io.Writer) error {
|
||||||
_, err := io.Copy(f, r)
|
_, err := io.Copy(f, r)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PosixStorage) DeleteObject(p string) error {
|
func (s *PosixStorage) DeleteObject(p string) error {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Remove(fspath); err != nil {
|
if err := os.Remove(fspath); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to remove parent empty dirs
|
// try to remove parent empty dirs
|
||||||
|
@ -179,7 +179,7 @@ func (s *PosixStorage) List(prefix, startWith, delimiter string, doneCh <-chan s
|
||||||
defer close(objectCh)
|
defer close(objectCh)
|
||||||
err := filepath.Walk(root, func(ep string, info os.FileInfo, err error) error {
|
err := filepath.Walk(root, func(ep string, info os.FileInfo, err error) error {
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -191,7 +191,7 @@ func (s *PosixStorage) List(prefix, startWith, delimiter string, doneCh <-chan s
|
||||||
|
|
||||||
p, err = filepath.Rel(s.dataDir, p)
|
p, err = filepath.Rel(s.dataDir, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if !recursive && len(p) > len(prefix) {
|
if !recursive && len(p) > len(prefix) {
|
||||||
rel := strings.TrimPrefix(p, prefix)
|
rel := strings.TrimPrefix(p, prefix)
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
"agola.io/agola/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -207,15 +207,15 @@ type PosixFlatStorage struct {
|
||||||
|
|
||||||
func NewPosixFlat(baseDir string) (*PosixFlatStorage, error) {
|
func NewPosixFlat(baseDir string) (*PosixFlatStorage, error) {
|
||||||
if err := os.MkdirAll(baseDir, 0770); err != nil {
|
if err := os.MkdirAll(baseDir, 0770); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
dataDir := filepath.Join(baseDir, dataDirName)
|
dataDir := filepath.Join(baseDir, dataDirName)
|
||||||
tmpDir := filepath.Join(baseDir, tmpDirName)
|
tmpDir := filepath.Join(baseDir, tmpDirName)
|
||||||
if err := os.MkdirAll(dataDir, 0770); err != nil {
|
if err := os.MkdirAll(dataDir, 0770); err != nil {
|
||||||
return nil, errors.Errorf("failed to create data dir: %w", err)
|
return nil, errors.Wrapf(err, "failed to create data dir")
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(tmpDir, 0770); err != nil {
|
if err := os.MkdirAll(tmpDir, 0770); err != nil {
|
||||||
return nil, errors.Errorf("failed to create tmp dir: %w", err)
|
return nil, errors.Wrapf(err, "failed to create tmp dir")
|
||||||
}
|
}
|
||||||
return &PosixFlatStorage{
|
return &PosixFlatStorage{
|
||||||
dataDir: dataDir,
|
dataDir: dataDir,
|
||||||
|
@ -233,7 +233,7 @@ func (s *PosixFlatStorage) fsPath(p string) (string, error) {
|
||||||
func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
|
func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fi, err := os.Stat(fspath)
|
fi, err := os.Stat(fspath)
|
||||||
|
@ -241,7 +241,7 @@ func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ObjectInfo{Path: p, LastModified: fi.ModTime(), Size: fi.Size()}, nil
|
return &ObjectInfo{Path: p, LastModified: fi.ModTime(), Size: fi.Size()}, nil
|
||||||
|
@ -250,24 +250,24 @@ func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
|
||||||
func (s *PosixFlatStorage) ReadObject(p string) (ReadSeekCloser, error) {
|
func (s *PosixFlatStorage) ReadObject(p string) (ReadSeekCloser, error) {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(fspath)
|
f, err := os.Open(fspath)
|
||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return f, err
|
return f, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PosixFlatStorage) WriteObject(p string, data io.Reader, size int64, persist bool) error {
|
func (s *PosixFlatStorage) WriteObject(p string, data io.Reader, size int64, persist bool) error {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Dir(fspath), 0770); err != nil {
|
if err := os.MkdirAll(path.Dir(fspath), 0770); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := data
|
r := data
|
||||||
|
@ -276,21 +276,21 @@ func (s *PosixFlatStorage) WriteObject(p string, data io.Reader, size int64, per
|
||||||
}
|
}
|
||||||
return writeFileAtomicFunc(fspath, s.dataDir, s.tmpDir, 0660, persist, func(f io.Writer) error {
|
return writeFileAtomicFunc(fspath, s.dataDir, s.tmpDir, 0660, persist, func(f io.Writer) error {
|
||||||
_, err := io.Copy(f, r)
|
_, err := io.Copy(f, r)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PosixFlatStorage) DeleteObject(p string) error {
|
func (s *PosixFlatStorage) DeleteObject(p string) error {
|
||||||
fspath, err := s.fsPath(p)
|
fspath, err := s.fsPath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Remove(fspath); err != nil {
|
if err := os.Remove(fspath); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to remove parent empty dirs
|
// try to remove parent empty dirs
|
||||||
|
@ -354,7 +354,7 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch
|
||||||
defer close(objectCh)
|
defer close(objectCh)
|
||||||
err := filepath.Walk(root, func(ep string, info os.FileInfo, err error) error {
|
err := filepath.Walk(root, func(ep string, info os.FileInfo, err error) error {
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -366,11 +366,11 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch
|
||||||
|
|
||||||
p, err = filepath.Rel(s.dataDir, p)
|
p, err = filepath.Rel(s.dataDir, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
p, _, err = unescape(p)
|
p, _, err = unescape(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if !recursive && len(p) > len(prefix) {
|
if !recursive && len(p) > len(prefix) {
|
||||||
rel := strings.TrimPrefix(p, prefix)
|
rel := strings.TrimPrefix(p, prefix)
|
||||||
|
@ -390,7 +390,7 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch
|
||||||
hasFile := true
|
hasFile := true
|
||||||
_, err = os.Stat(ep + ".f")
|
_, err = os.Stat(ep + ".f")
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
hasFile = false
|
hasFile = false
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
"agola.io/agola/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEscapeUnescape(t *testing.T) {
|
func TestEscapeUnescape(t *testing.T) {
|
||||||
|
|
|
@ -21,8 +21,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
minio "github.com/minio/minio-go/v6"
|
minio "github.com/minio/minio-go/v6"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type S3Storage struct {
|
type S3Storage struct {
|
||||||
|
@ -35,21 +35,21 @@ type S3Storage struct {
|
||||||
func NewS3(bucket, location, endpoint, accessKeyID, secretAccessKey string, secure bool) (*S3Storage, error) {
|
func NewS3(bucket, location, endpoint, accessKeyID, secretAccessKey string, secure bool) (*S3Storage, error) {
|
||||||
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, secure)
|
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, secure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
minioCore, err := minio.NewCore(endpoint, accessKeyID, secretAccessKey, secure)
|
minioCore, err := minio.NewCore(endpoint, accessKeyID, secretAccessKey, secure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := minioClient.BucketExists(bucket)
|
exists, err := minioClient.BucketExists(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot check if bucket %q in location %q exits: %w", bucket, location, err)
|
return nil, errors.Wrapf(err, "cannot check if bucket %q in location %q exits", bucket, location)
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
if err := minioClient.MakeBucket(bucket, location); err != nil {
|
if err := minioClient.MakeBucket(bucket, location); err != nil {
|
||||||
return nil, errors.Errorf("cannot create bucket %q in location %q: %w", bucket, location, err)
|
return nil, errors.Wrapf(err, "cannot create bucket %q in location %q", bucket, location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ func (s *S3Storage) Stat(p string) (*ObjectInfo, error) {
|
||||||
if merr.StatusCode == http.StatusNotFound {
|
if merr.StatusCode == http.StatusNotFound {
|
||||||
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
|
||||||
}
|
}
|
||||||
return nil, merr
|
return nil, errors.WithStack(merr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ObjectInfo{Path: p, LastModified: oi.LastModified, Size: oi.Size}, nil
|
return &ObjectInfo{Path: p, LastModified: oi.LastModified, Size: oi.Size}, nil
|
||||||
|
@ -79,9 +79,12 @@ func (s *S3Storage) ReadObject(filepath string) (ReadSeekCloser, error) {
|
||||||
if merr.StatusCode == http.StatusNotFound {
|
if merr.StatusCode == http.StatusNotFound {
|
||||||
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", filepath))
|
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", filepath))
|
||||||
}
|
}
|
||||||
return nil, merr
|
return nil, errors.WithStack(merr)
|
||||||
}
|
}
|
||||||
return s.minioClient.GetObject(s.bucket, filepath, minio.GetObjectOptions{})
|
|
||||||
|
o, err := s.minioClient.GetObject(s.bucket, filepath, minio.GetObjectOptions{})
|
||||||
|
|
||||||
|
return o, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) WriteObject(filepath string, data io.Reader, size int64, persist bool) error {
|
func (s *S3Storage) WriteObject(filepath string, data io.Reader, size int64, persist bool) error {
|
||||||
|
@ -92,30 +95,30 @@ func (s *S3Storage) WriteObject(filepath string, data io.Reader, size int64, per
|
||||||
if size >= 0 {
|
if size >= 0 {
|
||||||
lr := io.LimitReader(data, size)
|
lr := io.LimitReader(data, size)
|
||||||
_, err := s.minioClient.PutObject(s.bucket, filepath, lr, size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
_, err := s.minioClient.PutObject(s.bucket, filepath, lr, size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hack to know the real file size or minio will do this in memory with big memory usage since s3 doesn't support real streaming of unknown sizes
|
// hack to know the real file size or minio will do this in memory with big memory usage since s3 doesn't support real streaming of unknown sizes
|
||||||
// TODO(sgotti) wait for minio client to expose an api to provide the max object size so we can remove this
|
// TODO(sgotti) wait for minio client to expose an api to provide the max object size so we can remove this
|
||||||
tmpfile, err := ioutil.TempFile(os.TempDir(), "s3")
|
tmpfile, err := ioutil.TempFile(os.TempDir(), "s3")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer tmpfile.Close()
|
defer tmpfile.Close()
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
size, err = io.Copy(tmpfile, data)
|
size, err = io.Copy(tmpfile, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if _, err := tmpfile.Seek(0, 0); err != nil {
|
if _, err := tmpfile.Seek(0, 0); err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
_, err = s.minioClient.PutObject(s.bucket, filepath, tmpfile, size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
_, err = s.minioClient.PutObject(s.bucket, filepath, tmpfile, size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) DeleteObject(filepath string) error {
|
func (s *S3Storage) DeleteObject(filepath string) error {
|
||||||
return s.minioClient.RemoveObject(s.bucket, filepath)
|
return errors.WithStack(s.minioClient.RemoveObject(s.bucket, filepath))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) List(prefix, startWith, delimiter string, doneCh <-chan struct{}) <-chan ObjectInfo {
|
func (s *S3Storage) List(prefix, startWith, delimiter string, doneCh <-chan struct{}) <-chan ObjectInfo {
|
||||||
|
|
|
@ -19,12 +19,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"agola.io/agola/internal/config"
|
"agola.io/agola/internal/config"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
itypes "agola.io/agola/internal/services/types"
|
itypes "agola.io/agola/internal/services/types"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
rstypes "agola.io/agola/services/runservice/types"
|
rstypes "agola.io/agola/services/runservice/types"
|
||||||
"agola.io/agola/services/types"
|
"agola.io/agola/services/types"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -192,7 +191,7 @@ fi
|
||||||
return rws
|
return rws
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown config step type: %s", util.Dump(cs)))
|
panic(errors.Errorf("unknown config step type: %s", util.Dump(cs)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +460,7 @@ func genValue(val config.Value, variables map[string]string) string {
|
||||||
case config.ValueTypeFromVariable:
|
case config.ValueTypeFromVariable:
|
||||||
return variables[val.Value]
|
return variables[val.Value]
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("wrong value type: %q", val.Value))
|
panic(errors.Errorf("wrong value type: %q", val.Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"agola.io/agola/internal/config"
|
"agola.io/agola/internal/config"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
rstypes "agola.io/agola/services/runservice/types"
|
rstypes "agola.io/agola/services/runservice/types"
|
||||||
"agola.io/agola/services/types"
|
"agola.io/agola/services/types"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var uuid = &util.TestUUIDGenerator{}
|
var uuid = &util.TestUUIDGenerator{}
|
||||||
|
@ -128,7 +128,7 @@ func TestGenTasksLevels(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
err: fmt.Errorf("circular dependency detected"),
|
err: errors.Errorf("circular dependency detected"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Test circular dependency between 3 tasks: a -> b -> c -> a",
|
name: "Test circular dependency between 3 tasks: a -> b -> c -> a",
|
||||||
|
@ -155,7 +155,7 @@ func TestGenTasksLevels(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
err: fmt.Errorf("circular dependency detected"),
|
err: errors.Errorf("circular dependency detected"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Test circular dependency between 3 tasks: a -> b -> c -> b",
|
name: "Test circular dependency between 3 tasks: a -> b -> c -> b",
|
||||||
|
@ -182,7 +182,7 @@ func TestGenTasksLevels(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
err: fmt.Errorf("circular dependency detected"),
|
err: errors.Errorf("circular dependency detected"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -23,8 +23,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Sequence struct {
|
type Sequence struct {
|
||||||
|
@ -55,11 +55,11 @@ func Parse(s string) (*Sequence, error) {
|
||||||
}
|
}
|
||||||
epoch, err := strconv.ParseUint(parts[0], 32, 64)
|
epoch, err := strconv.ParseUint(parts[0], 32, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot parse sequence epoch %q: %w", epoch, err)
|
return nil, errors.Wrapf(err, "cannot parse sequence epoch %q", epoch)
|
||||||
}
|
}
|
||||||
c, err := strconv.ParseUint(parts[1], 32, 64)
|
c, err := strconv.ParseUint(parts[1], 32, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot parse sequence count %q: %w", c, err)
|
return nil, errors.Wrapf(err, "cannot parse sequence count %q", c)
|
||||||
}
|
}
|
||||||
return &Sequence{
|
return &Sequence{
|
||||||
Epoch: epoch,
|
Epoch: epoch,
|
||||||
|
@ -74,7 +74,7 @@ func (s *Sequence) EqualEpoch(s2 *Sequence) bool {
|
||||||
func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, bool, error) {
|
func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, bool, error) {
|
||||||
resp, err := e.Get(ctx, key, 0)
|
resp, err := e.Get(ctx, key, 0)
|
||||||
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return nil, false, err
|
return nil, false, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if errors.Is(err, etcd.ErrKeyNotFound) {
|
if errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
|
@ -84,7 +84,7 @@ func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, boo
|
||||||
if !errors.Is(err, etcd.ErrKeyNotFound) {
|
if !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
kv := resp.Kvs[0]
|
kv := resp.Kvs[0]
|
||||||
if err := json.Unmarshal(kv.Value, &seq); err != nil {
|
if err := json.Unmarshal(kv.Value, &seq); err != nil {
|
||||||
return nil, false, err
|
return nil, false, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return seq, true, nil
|
return seq, true, nil
|
||||||
|
@ -93,7 +93,7 @@ func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, boo
|
||||||
func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, error) {
|
func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, error) {
|
||||||
resp, err := e.Get(ctx, key, 0)
|
resp, err := e.Get(ctx, key, 0)
|
||||||
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var revision int64
|
var revision int64
|
||||||
|
@ -101,7 +101,7 @@ func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, err
|
||||||
if !errors.Is(err, etcd.ErrKeyNotFound) {
|
if !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
kv := resp.Kvs[0]
|
kv := resp.Kvs[0]
|
||||||
if err := json.Unmarshal(kv.Value, &seq); err != nil {
|
if err := json.Unmarshal(kv.Value, &seq); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
revision = kv.ModRevision
|
revision = kv.ModRevision
|
||||||
}
|
}
|
||||||
|
@ -120,12 +120,12 @@ func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, err
|
||||||
|
|
||||||
seqj, err := json.Marshal(seq)
|
seqj, err := json.Marshal(seq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = e.AtomicPut(ctx, key, seqj, revision, nil)
|
_, err = e.AtomicPut(ctx, key, seqj, revision, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return seq, nil
|
return seq, nil
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
package sequence
|
package sequence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -15,43 +15,48 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
gitsource "agola.io/agola/internal/gitsources"
|
gitsource "agola.io/agola/internal/gitsources"
|
||||||
"agola.io/agola/internal/gitsources/gitea"
|
"agola.io/agola/internal/gitsources/gitea"
|
||||||
"agola.io/agola/internal/gitsources/github"
|
"agola.io/agola/internal/gitsources/github"
|
||||||
"agola.io/agola/internal/gitsources/gitlab"
|
"agola.io/agola/internal/gitsources/gitlab"
|
||||||
cstypes "agola.io/agola/services/configstore/types"
|
cstypes "agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newGitea(rs *cstypes.RemoteSource, accessToken string) (*gitea.Client, error) {
|
func newGitea(rs *cstypes.RemoteSource, accessToken string) (*gitea.Client, error) {
|
||||||
return gitea.New(gitea.Opts{
|
c, err := gitea.New(gitea.Opts{
|
||||||
APIURL: rs.APIURL,
|
APIURL: rs.APIURL,
|
||||||
SkipVerify: rs.SkipVerify,
|
SkipVerify: rs.SkipVerify,
|
||||||
Token: accessToken,
|
Token: accessToken,
|
||||||
Oauth2ClientID: rs.Oauth2ClientID,
|
Oauth2ClientID: rs.Oauth2ClientID,
|
||||||
Oauth2Secret: rs.Oauth2ClientSecret,
|
Oauth2Secret: rs.Oauth2ClientSecret,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return c, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGitlab(rs *cstypes.RemoteSource, accessToken string) (*gitlab.Client, error) {
|
func newGitlab(rs *cstypes.RemoteSource, accessToken string) (*gitlab.Client, error) {
|
||||||
return gitlab.New(gitlab.Opts{
|
c, err := gitlab.New(gitlab.Opts{
|
||||||
APIURL: rs.APIURL,
|
APIURL: rs.APIURL,
|
||||||
SkipVerify: rs.SkipVerify,
|
SkipVerify: rs.SkipVerify,
|
||||||
Token: accessToken,
|
Token: accessToken,
|
||||||
Oauth2ClientID: rs.Oauth2ClientID,
|
Oauth2ClientID: rs.Oauth2ClientID,
|
||||||
Oauth2Secret: rs.Oauth2ClientSecret,
|
Oauth2Secret: rs.Oauth2ClientSecret,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return c, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGithub(rs *cstypes.RemoteSource, accessToken string) (*github.Client, error) {
|
func newGithub(rs *cstypes.RemoteSource, accessToken string) (*github.Client, error) {
|
||||||
return github.New(github.Opts{
|
c, err := github.New(github.Opts{
|
||||||
APIURL: rs.APIURL,
|
APIURL: rs.APIURL,
|
||||||
SkipVerify: rs.SkipVerify,
|
SkipVerify: rs.SkipVerify,
|
||||||
Token: accessToken,
|
Token: accessToken,
|
||||||
Oauth2ClientID: rs.Oauth2ClientID,
|
Oauth2ClientID: rs.Oauth2ClientID,
|
||||||
Oauth2Secret: rs.Oauth2ClientSecret,
|
Oauth2Secret: rs.Oauth2ClientSecret,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return c, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAccessToken(rs *cstypes.RemoteSource, userAccessToken, oauth2AccessToken string) (string, error) {
|
func GetAccessToken(rs *cstypes.RemoteSource, userAccessToken, oauth2AccessToken string) (string, error) {
|
||||||
|
@ -71,7 +76,7 @@ func GetGitSource(rs *cstypes.RemoteSource, la *cstypes.LinkedAccount) (gitsourc
|
||||||
var err error
|
var err error
|
||||||
accessToken, err = GetAccessToken(rs, la.UserAccessToken, la.Oauth2AccessToken)
|
accessToken, err = GetAccessToken(rs, la.UserAccessToken, la.Oauth2AccessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +93,7 @@ func GetGitSource(rs *cstypes.RemoteSource, la *cstypes.LinkedAccount) (gitsourc
|
||||||
return nil, errors.Errorf("remote source %s isn't a valid git source", rs.Name)
|
return nil, errors.Errorf("remote source %s isn't a valid git source", rs.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gitSource, err
|
return gitSource, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.UserSource, error) {
|
func GetUserSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.UserSource, error) {
|
||||||
|
@ -103,7 +108,7 @@ func GetUserSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.User
|
||||||
return nil, errors.Errorf("unknown remote source auth type")
|
return nil, errors.Errorf("unknown remote source auth type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return userSource, err
|
return userSource, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOauth2Source(rs *cstypes.RemoteSource, accessToken string) (gitsource.Oauth2Source, error) {
|
func GetOauth2Source(rs *cstypes.RemoteSource, accessToken string) (gitsource.Oauth2Source, error) {
|
||||||
|
@ -120,7 +125,7 @@ func GetOauth2Source(rs *cstypes.RemoteSource, accessToken string) (gitsource.Oa
|
||||||
return nil, errors.Errorf("remote source %s isn't a valid oauth2 source", rs.Name)
|
return nil, errors.Errorf("remote source %s isn't a valid oauth2 source", rs.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return oauth2Source, err
|
return oauth2Source, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPasswordSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.PasswordSource, error) {
|
func GetPasswordSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.PasswordSource, error) {
|
||||||
|
@ -133,5 +138,5 @@ func GetPasswordSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.
|
||||||
return nil, errors.Errorf("remote source %s isn't a valid oauth2 source", rs.Name)
|
return nil, errors.Errorf("remote source %s isn't a valid oauth2 source", rs.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return passwordSource, err
|
return passwordSource, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TokenSigningData struct {
|
type TokenSigningData struct {
|
||||||
|
@ -44,13 +44,14 @@ func GenerateGenericJWTToken(sd *TokenSigningData, claims jwt.Claims) (string, e
|
||||||
return "", errors.Errorf("unsupported signing method %q", sd.Method.Alg())
|
return "", errors.Errorf("unsupported signing method %q", sd.Method.Alg())
|
||||||
}
|
}
|
||||||
// Sign and get the complete encoded token as a string
|
// Sign and get the complete encoded token as a string
|
||||||
return token.SignedString(key)
|
ts, err := token.SignedString(key)
|
||||||
|
return ts, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateOauth2JWTToken(sd *TokenSigningData, remoteSourceName, requestType string, request interface{}) (string, error) {
|
func GenerateOauth2JWTToken(sd *TokenSigningData, remoteSourceName, requestType string, request interface{}) (string, error) {
|
||||||
requestj, err := json.Marshal(request)
|
requestj, err := json.Marshal(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenerateGenericJWTToken(sd, jwt.MapClaims{
|
return GenerateGenericJWTToken(sd, jwt.MapClaims{
|
||||||
|
|
|
@ -15,13 +15,12 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/services/types"
|
"agola.io/agola/internal/services/types"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GroupType string
|
type GroupType string
|
||||||
|
@ -49,7 +48,7 @@ func WebHookEventToRunRefType(we types.WebhookEvent) types.RunRefType {
|
||||||
return types.RunRefTypePullRequest
|
return types.RunRefTypePullRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Errorf("invalid webhook event type: %q", we))
|
panic(errors.Errorf("invalid webhook event type: %q", we))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenRunGroup(baseGroupType GroupType, baseGroupID string, groupType GroupType, group string) string {
|
func GenRunGroup(baseGroupType GroupType, baseGroupID string, groupType GroupType, group string) string {
|
||||||
|
|
|
@ -18,9 +18,9 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -273,12 +273,12 @@ var defaultConfig = Config{
|
||||||
func Parse(configFile string, componentsNames []string) (*Config, error) {
|
func Parse(configFile string, componentsNames []string) (*Config, error) {
|
||||||
configData, err := ioutil.ReadFile(configFile)
|
configData, err := ioutil.ReadFile(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &defaultConfig
|
c := &defaultConfig
|
||||||
if err := yaml.Unmarshal(configData, &c); err != nil {
|
if err := yaml.Unmarshal(configData, &c); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, Validate(c, componentsNames)
|
return c, Validate(c, componentsNames)
|
||||||
|
@ -333,7 +333,7 @@ func Validate(c *Config, componentsNames []string) error {
|
||||||
return errors.Errorf("gateway runserviceURL is empty")
|
return errors.Errorf("gateway runserviceURL is empty")
|
||||||
}
|
}
|
||||||
if err := validateWeb(&c.Gateway.Web); err != nil {
|
if err := validateWeb(&c.Gateway.Web); err != nil {
|
||||||
return errors.Errorf("gateway web configuration error: %w", err)
|
return errors.Wrapf(err, "gateway web configuration error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ func Validate(c *Config, componentsNames []string) error {
|
||||||
return errors.Errorf("configstore dataDir is empty")
|
return errors.Errorf("configstore dataDir is empty")
|
||||||
}
|
}
|
||||||
if err := validateWeb(&c.Configstore.Web); err != nil {
|
if err := validateWeb(&c.Configstore.Web); err != nil {
|
||||||
return errors.Errorf("configstore web configuration error: %w", err)
|
return errors.Wrapf(err, "configstore web configuration error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ func Validate(c *Config, componentsNames []string) error {
|
||||||
return errors.Errorf("runservice dataDir is empty")
|
return errors.Errorf("runservice dataDir is empty")
|
||||||
}
|
}
|
||||||
if err := validateWeb(&c.Runservice.Web); err != nil {
|
if err := validateWeb(&c.Runservice.Web); err != nil {
|
||||||
return errors.Errorf("runservice web configuration error: %w", err)
|
return errors.Wrapf(err, "runservice web configuration error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ func Validate(c *Config, componentsNames []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateInitImage(&c.Executor.InitImage); err != nil {
|
if err := validateInitImage(&c.Executor.InitImage); err != nil {
|
||||||
return errors.Errorf("executor initImage configuration error: %w", err)
|
return errors.Wrapf(err, "executor initImage configuration error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
"agola.io/agola/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseConfig(t *testing.T) {
|
func TestParseConfig(t *testing.T) {
|
||||||
|
|
|
@ -17,13 +17,13 @@ package action
|
||||||
import (
|
import (
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
"agola.io/agola/internal/services/configstore/readdb"
|
"agola.io/agola/internal/services/configstore/readdb"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionHandler struct {
|
type ActionHandler struct {
|
||||||
|
@ -53,7 +53,7 @@ func (h *ActionHandler) ResolveConfigID(tx *db.Tx, configType types.ConfigType,
|
||||||
case types.ConfigTypeProjectGroup:
|
case types.ConfigTypeProjectGroup:
|
||||||
group, err := h.readDB.GetProjectGroup(tx, ref)
|
group, err := h.readDB.GetProjectGroup(tx, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("group with ref %q doesn't exists", ref))
|
return "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("group with ref %q doesn't exists", ref))
|
||||||
|
@ -63,7 +63,7 @@ func (h *ActionHandler) ResolveConfigID(tx *db.Tx, configType types.ConfigType,
|
||||||
case types.ConfigTypeProject:
|
case types.ConfigTypeProject:
|
||||||
project, err := h.readDB.GetProject(tx, ref)
|
project, err := h.readDB.GetProject(tx, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if project == nil {
|
if project == nil {
|
||||||
return "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exists", ref))
|
return "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exists", ref))
|
||||||
|
|
|
@ -18,17 +18,16 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/etcd"
|
"agola.io/agola/internal/etcd"
|
||||||
"agola.io/agola/internal/services/configstore/common"
|
"agola.io/agola/internal/services/configstore/common"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error {
|
func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error {
|
||||||
resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0)
|
resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0)
|
||||||
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enable && len(resp.Kvs) > 0 {
|
if enable && len(resp.Kvs) > 0 {
|
||||||
|
@ -41,7 +40,7 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
|
||||||
if enable {
|
if enable {
|
||||||
txResp, err := h.e.AtomicPut(ctx, common.EtcdMaintenanceKey, []byte{}, 0, nil)
|
txResp, err := h.e.AtomicPut(ctx, common.EtcdMaintenanceKey, []byte{}, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if !txResp.Succeeded {
|
if !txResp.Succeeded {
|
||||||
return errors.Errorf("failed to create maintenance mode key due to concurrent update")
|
return errors.Errorf("failed to create maintenance mode key due to concurrent update")
|
||||||
|
@ -51,7 +50,7 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
|
||||||
if !enable {
|
if !enable {
|
||||||
txResp, err := h.e.AtomicDelete(ctx, common.EtcdMaintenanceKey, resp.Kvs[0].ModRevision)
|
txResp, err := h.e.AtomicDelete(ctx, common.EtcdMaintenanceKey, resp.Kvs[0].ModRevision)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if !txResp.Succeeded {
|
if !txResp.Succeeded {
|
||||||
return errors.Errorf("failed to delete maintenance mode key due to concurrent update")
|
return errors.Errorf("failed to delete maintenance mode key due to concurrent update")
|
||||||
|
@ -62,12 +61,12 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) Export(ctx context.Context, w io.Writer) error {
|
func (h *ActionHandler) Export(ctx context.Context, w io.Writer) error {
|
||||||
return h.dm.Export(ctx, w)
|
return errors.WithStack(h.dm.Export(ctx, w))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) Import(ctx context.Context, r io.Reader) error {
|
func (h *ActionHandler) Import(ctx context.Context, r io.Reader) error {
|
||||||
if !h.maintenanceMode {
|
if !h.maintenanceMode {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("not in maintenance mode"))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("not in maintenance mode"))
|
||||||
}
|
}
|
||||||
return h.dm.Import(ctx, r)
|
return errors.WithStack(h.dm.Import(ctx, r))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,13 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/services/configstore/readdb"
|
"agola.io/agola/internal/services/configstore/readdb"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrgMemberResponse struct {
|
type OrgMemberResponse struct {
|
||||||
|
@ -48,17 +49,17 @@ func (h *ActionHandler) GetOrgMembers(ctx context.Context, orgRef string) ([]*Or
|
||||||
var err error
|
var err error
|
||||||
org, err := h.readDB.GetOrg(tx, orgRef)
|
org, err := h.readDB.GetOrg(tx, orgRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if org == nil {
|
if org == nil {
|
||||||
return util.NewAPIError(util.ErrNotExist, errors.Errorf("org %q doesn't exist", orgRef))
|
return util.NewAPIError(util.ErrNotExist, errors.Errorf("org %q doesn't exist", orgRef))
|
||||||
}
|
}
|
||||||
|
|
||||||
orgUsers, err = h.readDB.GetOrgUsers(tx, org.ID)
|
orgUsers, err = h.readDB.GetOrgUsers(tx, org.ID)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]*OrgMemberResponse, len(orgUsers))
|
res := make([]*OrgMemberResponse, len(orgUsers))
|
||||||
|
@ -89,13 +90,13 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
var err error
|
var err error
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check duplicate org name
|
// check duplicate org name
|
||||||
o, err := h.readDB.GetOrgByName(tx, org.Name)
|
o, err := h.readDB.GetOrgByName(tx, org.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if o != nil {
|
if o != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q already exists", o.Name))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q already exists", o.Name))
|
||||||
|
@ -104,7 +105,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
if org.CreatorUserID != "" {
|
if org.CreatorUserID != "" {
|
||||||
user, err := h.readDB.GetUser(tx, org.CreatorUserID)
|
user, err := h.readDB.GetUser(tx, org.CreatorUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("creator user %q doesn't exist", org.CreatorUserID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("creator user %q doesn't exist", org.CreatorUserID))
|
||||||
|
@ -114,7 +115,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{}
|
actions := []*datamanager.Action{}
|
||||||
|
@ -123,7 +124,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
org.CreatedAt = time.Now()
|
org.CreatedAt = time.Now()
|
||||||
orgj, err := json.Marshal(org)
|
orgj, err := json.Marshal(org)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal org: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal org")
|
||||||
}
|
}
|
||||||
actions = append(actions, &datamanager.Action{
|
actions = append(actions, &datamanager.Action{
|
||||||
ActionType: datamanager.ActionTypePut,
|
ActionType: datamanager.ActionTypePut,
|
||||||
|
@ -142,7 +143,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
}
|
}
|
||||||
orgmemberj, err := json.Marshal(orgmember)
|
orgmemberj, err := json.Marshal(orgmember)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project group: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project group")
|
||||||
}
|
}
|
||||||
actions = append(actions, &datamanager.Action{
|
actions = append(actions, &datamanager.Action{
|
||||||
ActionType: datamanager.ActionTypePut,
|
ActionType: datamanager.ActionTypePut,
|
||||||
|
@ -164,7 +165,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
}
|
}
|
||||||
pgj, err := json.Marshal(pg)
|
pgj, err := json.Marshal(pg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project group: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project group")
|
||||||
}
|
}
|
||||||
actions = append(actions, &datamanager.Action{
|
actions = append(actions, &datamanager.Action{
|
||||||
ActionType: datamanager.ActionTypePut,
|
ActionType: datamanager.ActionTypePut,
|
||||||
|
@ -174,7 +175,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return org, err
|
return org, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
|
func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
|
||||||
|
@ -187,7 +188,7 @@ func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
|
||||||
// check org existance
|
// check org existance
|
||||||
org, err = h.readDB.GetOrgByName(tx, orgRef)
|
org, err = h.readDB.GetOrgByName(tx, orgRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if org == nil {
|
if org == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exist", orgRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exist", orgRef))
|
||||||
|
@ -197,13 +198,13 @@ func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
|
||||||
cgNames := []string{util.EncodeSha256Hex("orgid-" + org.ID)}
|
cgNames := []string{util.EncodeSha256Hex("orgid-" + org.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sgotti) delete all project groups, projects etc...
|
// TODO(sgotti) delete all project groups, projects etc...
|
||||||
|
@ -216,7 +217,7 @@ func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddOrgMember add/updates an org member.
|
// AddOrgMember add/updates an org member.
|
||||||
|
@ -237,7 +238,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
|
||||||
// check existing org
|
// check existing org
|
||||||
org, err = h.readDB.GetOrg(tx, orgRef)
|
org, err = h.readDB.GetOrg(tx, orgRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if org == nil {
|
if org == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef))
|
||||||
|
@ -245,7 +246,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
|
||||||
// check existing user
|
// check existing user
|
||||||
user, err = h.readDB.GetUser(tx, userRef)
|
user, err = h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef))
|
||||||
|
@ -254,19 +255,19 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
|
||||||
// fetch org member if it already exist
|
// fetch org member if it already exist
|
||||||
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
|
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
|
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// update if role changed
|
// update if role changed
|
||||||
|
@ -287,7 +288,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
|
||||||
actions := []*datamanager.Action{}
|
actions := []*datamanager.Action{}
|
||||||
orgmemberj, err := json.Marshal(orgmember)
|
orgmemberj, err := json.Marshal(orgmember)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project group: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project group")
|
||||||
}
|
}
|
||||||
actions = append(actions, &datamanager.Action{
|
actions = append(actions, &datamanager.Action{
|
||||||
ActionType: datamanager.ActionTypePut,
|
ActionType: datamanager.ActionTypePut,
|
||||||
|
@ -297,7 +298,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return orgmember, err
|
return orgmember, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOrgMember removes an org member.
|
// RemoveOrgMember removes an org member.
|
||||||
|
@ -313,7 +314,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
|
||||||
// check existing org
|
// check existing org
|
||||||
org, err = h.readDB.GetOrg(tx, orgRef)
|
org, err = h.readDB.GetOrg(tx, orgRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if org == nil {
|
if org == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef))
|
||||||
|
@ -321,7 +322,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
|
||||||
// check existing user
|
// check existing user
|
||||||
user, err = h.readDB.GetUser(tx, userRef)
|
user, err = h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef))
|
||||||
|
@ -330,7 +331,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
|
||||||
// check that org member exists
|
// check that org member exists
|
||||||
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
|
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if orgmember == nil {
|
if orgmember == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("orgmember for org %q, user %q doesn't exists", orgRef, userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("orgmember for org %q, user %q doesn't exists", orgRef, userRef))
|
||||||
|
@ -339,13 +340,13 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
|
||||||
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
|
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{}
|
actions := []*datamanager.Action{}
|
||||||
|
@ -356,5 +357,5 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,12 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ActionHandler) ValidateProject(ctx context.Context, project *types.Project) error {
|
func (h *ActionHandler) ValidateProject(ctx context.Context, project *types.Project) error {
|
||||||
|
@ -69,10 +70,10 @@ func (h *ActionHandler) GetProject(ctx context.Context, projectRef string) (*typ
|
||||||
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
||||||
var err error
|
var err error
|
||||||
project, err = h.readDB.GetProject(tx, projectRef)
|
project, err = h.readDB.GetProject(tx, projectRef)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if project == nil {
|
if project == nil {
|
||||||
|
@ -84,7 +85,7 @@ func (h *ActionHandler) GetProject(ctx context.Context, projectRef string) (*typ
|
||||||
|
|
||||||
func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Project) (*types.Project, error) {
|
func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Project) (*types.Project, error) {
|
||||||
if err := h.ValidateProject(ctx, project); err != nil {
|
if err := h.ValidateProject(ctx, project); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -94,7 +95,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
var err error
|
var err error
|
||||||
group, err := h.readDB.GetProjectGroup(tx, project.Parent.ID)
|
group, err := h.readDB.GetProjectGroup(tx, project.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", project.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", project.Parent.ID))
|
||||||
|
@ -103,7 +104,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
|
|
||||||
groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
|
groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
pp := path.Join(groupPath, project.Name)
|
pp := path.Join(groupPath, project.Name)
|
||||||
|
|
||||||
|
@ -112,13 +113,13 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
|
cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check duplicate project name
|
// check duplicate project name
|
||||||
p, err := h.readDB.GetProjectByName(tx, project.Parent.ID, project.Name)
|
p, err := h.readDB.GetProjectByName(tx, project.Parent.ID, project.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if p != nil {
|
if p != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", p.Name, pp))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", p.Name, pp))
|
||||||
|
@ -128,7 +129,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
// check that the linked account matches the remote source
|
// check that the linked account matches the remote source
|
||||||
user, err := h.readDB.GetUserByLinkedAccount(tx, project.LinkedAccountID)
|
user, err := h.readDB.GetUserByLinkedAccount(tx, project.LinkedAccountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to get user with linked account id %q: %w", project.LinkedAccountID, err)
|
return errors.Wrapf(err, "failed to get user with linked account id %q", project.LinkedAccountID)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", project.LinkedAccountID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", project.LinkedAccountID))
|
||||||
|
@ -145,7 +146,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
project.ID = uuid.Must(uuid.NewV4()).String()
|
project.ID = uuid.Must(uuid.NewV4()).String()
|
||||||
|
@ -156,7 +157,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
|
|
||||||
pcj, err := json.Marshal(project)
|
pcj, err := json.Marshal(project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -168,7 +169,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return project, err
|
return project, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateProjectRequest struct {
|
type UpdateProjectRequest struct {
|
||||||
|
@ -179,7 +180,7 @@ type UpdateProjectRequest struct {
|
||||||
|
|
||||||
func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectRequest) (*types.Project, error) {
|
func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectRequest) (*types.Project, error) {
|
||||||
if err := h.ValidateProject(ctx, req.Project); err != nil {
|
if err := h.ValidateProject(ctx, req.Project); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -190,7 +191,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
// check project exists
|
// check project exists
|
||||||
p, err := h.readDB.GetProject(tx, req.ProjectRef)
|
p, err := h.readDB.GetProject(tx, req.ProjectRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", req.ProjectRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", req.ProjectRef))
|
||||||
|
@ -203,7 +204,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
// check parent project group exists
|
// check parent project group exists
|
||||||
group, err := h.readDB.GetProjectGroup(tx, req.Project.Parent.ID)
|
group, err := h.readDB.GetProjectGroup(tx, req.Project.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.Project.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.Project.Parent.ID))
|
||||||
|
@ -212,7 +213,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
|
|
||||||
groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
|
groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
pp := path.Join(groupPath, req.Project.Name)
|
pp := path.Join(groupPath, req.Project.Name)
|
||||||
|
|
||||||
|
@ -220,7 +221,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
// check duplicate project name
|
// check duplicate project name
|
||||||
ap, err := h.readDB.GetProjectByName(tx, req.Project.Parent.ID, req.Project.Name)
|
ap, err := h.readDB.GetProjectByName(tx, req.Project.Parent.ID, req.Project.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if ap != nil {
|
if ap != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", req.Project.Name, pp))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", req.Project.Name, pp))
|
||||||
|
@ -236,14 +237,14 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
// get old parent project group
|
// get old parent project group
|
||||||
curGroup, err := h.readDB.GetProjectGroup(tx, p.Parent.ID)
|
curGroup, err := h.readDB.GetProjectGroup(tx, p.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if curGroup == nil {
|
if curGroup == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", p.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", p.Parent.ID))
|
||||||
}
|
}
|
||||||
curGroupPath, err := h.readDB.GetProjectGroupPath(tx, curGroup)
|
curGroupPath, err := h.readDB.GetProjectGroupPath(tx, curGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
pp := path.Join(curGroupPath, req.Project.Name)
|
pp := path.Join(curGroupPath, req.Project.Name)
|
||||||
|
|
||||||
|
@ -252,14 +253,14 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
|
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Project.RemoteRepositoryConfigType == types.RemoteRepositoryConfigTypeRemoteSource {
|
if req.Project.RemoteRepositoryConfigType == types.RemoteRepositoryConfigTypeRemoteSource {
|
||||||
// check that the linked account matches the remote source
|
// check that the linked account matches the remote source
|
||||||
user, err := h.readDB.GetUserByLinkedAccount(tx, req.Project.LinkedAccountID)
|
user, err := h.readDB.GetUserByLinkedAccount(tx, req.Project.LinkedAccountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to get user with linked account id %q: %w", req.Project.LinkedAccountID, err)
|
return errors.Wrapf(err, "failed to get user with linked account id %q", req.Project.LinkedAccountID)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", req.Project.LinkedAccountID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", req.Project.LinkedAccountID))
|
||||||
|
@ -276,12 +277,12 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pcj, err := json.Marshal(req.Project)
|
pcj, err := json.Marshal(req.Project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -293,7 +294,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return req.Project, err
|
return req.Project, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) error {
|
func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) error {
|
||||||
|
@ -308,7 +309,7 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
|
||||||
// check project existance
|
// check project existance
|
||||||
project, err = h.readDB.GetProject(tx, projectRef)
|
project, err = h.readDB.GetProject(tx, projectRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if project == nil {
|
if project == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project %q doesn't exist", projectRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project %q doesn't exist", projectRef))
|
||||||
|
@ -318,13 +319,13 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
|
||||||
cgNames := []string{util.EncodeSha256Hex(project.ID)}
|
cgNames := []string{util.EncodeSha256Hex(project.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sgotti) implement childs garbage collection
|
// TODO(sgotti) implement childs garbage collection
|
||||||
|
@ -337,5 +338,5 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,12 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ActionHandler) GetProjectGroup(ctx context.Context, projectGroupRef string) (*types.ProjectGroup, error) {
|
func (h *ActionHandler) GetProjectGroup(ctx context.Context, projectGroupRef string) (*types.ProjectGroup, error) {
|
||||||
|
@ -34,10 +35,10 @@ func (h *ActionHandler) GetProjectGroup(ctx context.Context, projectGroupRef str
|
||||||
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
||||||
var err error
|
var err error
|
||||||
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
|
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if projectGroup == nil {
|
if projectGroup == nil {
|
||||||
|
@ -53,7 +54,7 @@ func (h *ActionHandler) GetProjectGroupSubgroups(ctx context.Context, projectGro
|
||||||
var err error
|
var err error
|
||||||
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
|
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if projectGroup == nil {
|
if projectGroup == nil {
|
||||||
|
@ -61,10 +62,10 @@ func (h *ActionHandler) GetProjectGroupSubgroups(ctx context.Context, projectGro
|
||||||
}
|
}
|
||||||
|
|
||||||
projectGroups, err = h.readDB.GetProjectGroupSubgroups(tx, projectGroup.ID)
|
projectGroups, err = h.readDB.GetProjectGroupSubgroups(tx, projectGroup.ID)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return projectGroups, nil
|
return projectGroups, nil
|
||||||
|
@ -76,7 +77,7 @@ func (h *ActionHandler) GetProjectGroupProjects(ctx context.Context, projectGrou
|
||||||
var err error
|
var err error
|
||||||
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
|
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if projectGroup == nil {
|
if projectGroup == nil {
|
||||||
|
@ -84,10 +85,10 @@ func (h *ActionHandler) GetProjectGroupProjects(ctx context.Context, projectGrou
|
||||||
}
|
}
|
||||||
|
|
||||||
projects, err = h.readDB.GetProjectGroupProjects(tx, projectGroup.ID)
|
projects, err = h.readDB.GetProjectGroupProjects(tx, projectGroup.ID)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return projects, nil
|
return projects, nil
|
||||||
}
|
}
|
||||||
|
@ -125,7 +126,7 @@ func (h *ActionHandler) ValidateProjectGroup(ctx context.Context, projectGroup *
|
||||||
|
|
||||||
func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *types.ProjectGroup) (*types.ProjectGroup, error) {
|
func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *types.ProjectGroup) (*types.ProjectGroup, error) {
|
||||||
if err := h.ValidateProjectGroup(ctx, projectGroup); err != nil {
|
if err := h.ValidateProjectGroup(ctx, projectGroup); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if projectGroup.Parent.Type != types.ConfigTypeProjectGroup {
|
if projectGroup.Parent.Type != types.ConfigTypeProjectGroup {
|
||||||
|
@ -138,7 +139,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
|
||||||
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
||||||
parentProjectGroup, err := h.readDB.GetProjectGroup(tx, projectGroup.Parent.ID)
|
parentProjectGroup, err := h.readDB.GetProjectGroup(tx, projectGroup.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if parentProjectGroup == nil {
|
if parentProjectGroup == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", projectGroup.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", projectGroup.Parent.ID))
|
||||||
|
@ -150,7 +151,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
|
||||||
|
|
||||||
groupPath, err := h.readDB.GetProjectGroupPath(tx, parentProjectGroup)
|
groupPath, err := h.readDB.GetProjectGroupPath(tx, parentProjectGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
pp := path.Join(groupPath, projectGroup.Name)
|
pp := path.Join(groupPath, projectGroup.Name)
|
||||||
|
|
||||||
|
@ -159,13 +160,13 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
|
||||||
cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
|
cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check duplicate project group name
|
// check duplicate project group name
|
||||||
pg, err := h.readDB.GetProjectGroupByName(tx, projectGroup.Parent.ID, projectGroup.Name)
|
pg, err := h.readDB.GetProjectGroupByName(tx, projectGroup.Parent.ID, projectGroup.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if pg != nil {
|
if pg != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", pg.Name, pp))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", pg.Name, pp))
|
||||||
|
@ -173,7 +174,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
projectGroup.ID = uuid.Must(uuid.NewV4()).String()
|
projectGroup.ID = uuid.Must(uuid.NewV4()).String()
|
||||||
|
@ -181,7 +182,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
|
||||||
|
|
||||||
pgj, err := json.Marshal(projectGroup)
|
pgj, err := json.Marshal(projectGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal projectGroup: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal projectGroup")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -193,7 +194,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return projectGroup, err
|
return projectGroup, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateProjectGroupRequest struct {
|
type UpdateProjectGroupRequest struct {
|
||||||
|
@ -204,7 +205,7 @@ type UpdateProjectGroupRequest struct {
|
||||||
|
|
||||||
func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProjectGroupRequest) (*types.ProjectGroup, error) {
|
func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProjectGroupRequest) (*types.ProjectGroup, error) {
|
||||||
if err := h.ValidateProjectGroup(ctx, req.ProjectGroup); err != nil {
|
if err := h.ValidateProjectGroup(ctx, req.ProjectGroup); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -215,7 +216,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
|
||||||
// check project exists
|
// check project exists
|
||||||
pg, err := h.readDB.GetProjectGroup(tx, req.ProjectGroupRef)
|
pg, err := h.readDB.GetProjectGroup(tx, req.ProjectGroupRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if pg == nil {
|
if pg == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with ref %q doesn't exist", req.ProjectGroupRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with ref %q doesn't exist", req.ProjectGroupRef))
|
||||||
|
@ -244,7 +245,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
|
||||||
// check parent exists
|
// check parent exists
|
||||||
group, err := h.readDB.GetProjectGroup(tx, req.ProjectGroup.Parent.ID)
|
group, err := h.readDB.GetProjectGroup(tx, req.ProjectGroup.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.ProjectGroup.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.ProjectGroup.Parent.ID))
|
||||||
|
@ -257,13 +258,13 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
|
||||||
|
|
||||||
curPGParentPath, err := h.readDB.GetPath(tx, pg.Parent.Type, pg.Parent.ID)
|
curPGParentPath, err := h.readDB.GetPath(tx, pg.Parent.Type, pg.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
curPGP := path.Join(curPGParentPath, pg.Name)
|
curPGP := path.Join(curPGParentPath, pg.Name)
|
||||||
|
|
||||||
pgParentPath, err := h.readDB.GetPath(tx, req.ProjectGroup.Parent.Type, req.ProjectGroup.Parent.ID)
|
pgParentPath, err := h.readDB.GetPath(tx, req.ProjectGroup.Parent.Type, req.ProjectGroup.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
pgp := path.Join(pgParentPath, req.ProjectGroup.Name)
|
pgp := path.Join(pgParentPath, req.ProjectGroup.Name)
|
||||||
|
|
||||||
|
@ -271,7 +272,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
|
||||||
// check duplicate project group name
|
// check duplicate project group name
|
||||||
ap, err := h.readDB.GetProjectGroupByName(tx, req.ProjectGroup.Parent.ID, req.ProjectGroup.Name)
|
ap, err := h.readDB.GetProjectGroupByName(tx, req.ProjectGroup.Parent.ID, req.ProjectGroup.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if ap != nil {
|
if ap != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", req.ProjectGroup.Name, pgp))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", req.ProjectGroup.Name, pgp))
|
||||||
|
@ -293,18 +294,18 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
|
||||||
|
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pgj, err := json.Marshal(req.ProjectGroup)
|
pgj, err := json.Marshal(req.ProjectGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -316,7 +317,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return req.ProjectGroup, err
|
return req.ProjectGroup, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef string) error {
|
func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef string) error {
|
||||||
|
@ -331,7 +332,7 @@ func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef
|
||||||
// check project group existance
|
// check project group existance
|
||||||
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
|
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if projectGroup == nil {
|
if projectGroup == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group %q doesn't exist", projectGroupRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group %q doesn't exist", projectGroupRef))
|
||||||
|
@ -347,13 +348,13 @@ func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef
|
||||||
cgNames := []string{util.EncodeSha256Hex(projectGroup.ID)}
|
cgNames := []string{util.EncodeSha256Hex(projectGroup.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sgotti) implement childs garbage collection
|
// TODO(sgotti) implement childs garbage collection
|
||||||
|
@ -366,5 +367,5 @@ func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,12 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ActionHandler) ValidateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) error {
|
func (h *ActionHandler) ValidateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) error {
|
||||||
|
@ -66,7 +67,7 @@ func (h *ActionHandler) ValidateRemoteSource(ctx context.Context, remoteSource *
|
||||||
|
|
||||||
func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) (*types.RemoteSource, error) {
|
func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) (*types.RemoteSource, error) {
|
||||||
if err := h.ValidateRemoteSource(ctx, remoteSource); err != nil {
|
if err := h.ValidateRemoteSource(ctx, remoteSource); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -78,13 +79,13 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
|
||||||
var err error
|
var err error
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check duplicate remoteSource name
|
// check duplicate remoteSource name
|
||||||
u, err := h.readDB.GetRemoteSourceByName(tx, remoteSource.Name)
|
u, err := h.readDB.GetRemoteSourceByName(tx, remoteSource.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name))
|
||||||
|
@ -92,14 +93,14 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSource.ID = uuid.Must(uuid.NewV4()).String()
|
remoteSource.ID = uuid.Must(uuid.NewV4()).String()
|
||||||
|
|
||||||
rsj, err := json.Marshal(remoteSource)
|
rsj, err := json.Marshal(remoteSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal remotesource: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal remotesource")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -111,7 +112,7 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return remoteSource, err
|
return remoteSource, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateRemoteSourceRequest struct {
|
type UpdateRemoteSourceRequest struct {
|
||||||
|
@ -122,7 +123,7 @@ type UpdateRemoteSourceRequest struct {
|
||||||
|
|
||||||
func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemoteSourceRequest) (*types.RemoteSource, error) {
|
func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemoteSourceRequest) (*types.RemoteSource, error) {
|
||||||
if err := h.ValidateRemoteSource(ctx, req.RemoteSource); err != nil {
|
if err := h.ValidateRemoteSource(ctx, req.RemoteSource); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var curRemoteSource *types.RemoteSource
|
var curRemoteSource *types.RemoteSource
|
||||||
|
@ -135,7 +136,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
|
||||||
// check remotesource exists
|
// check remotesource exists
|
||||||
curRemoteSource, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceRef)
|
curRemoteSource, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if curRemoteSource == nil {
|
if curRemoteSource == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource with ref %q doesn't exist", req.RemoteSourceRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource with ref %q doesn't exist", req.RemoteSourceRef))
|
||||||
|
@ -145,7 +146,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
|
||||||
// check duplicate remoteSource name
|
// check duplicate remoteSource name
|
||||||
u, err := h.readDB.GetRemoteSourceByName(tx, req.RemoteSource.Name)
|
u, err := h.readDB.GetRemoteSourceByName(tx, req.RemoteSource.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name))
|
||||||
|
@ -160,17 +161,17 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
|
||||||
cgNames := []string{util.EncodeSha256Hex("remotesourcename-" + req.RemoteSource.Name), util.EncodeSha256Hex("remotesourceid-" + req.RemoteSource.ID)}
|
cgNames := []string{util.EncodeSha256Hex("remotesourcename-" + req.RemoteSource.Name), util.EncodeSha256Hex("remotesourceid-" + req.RemoteSource.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rsj, err := json.Marshal(req.RemoteSource)
|
rsj, err := json.Marshal(req.RemoteSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal remotesource: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal remotesource")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -182,7 +183,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return req.RemoteSource, err
|
return req.RemoteSource, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName string) error {
|
func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName string) error {
|
||||||
|
@ -196,7 +197,7 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
|
||||||
// check remoteSource existance
|
// check remoteSource existance
|
||||||
remoteSource, err = h.readDB.GetRemoteSourceByName(tx, remoteSourceName)
|
remoteSource, err = h.readDB.GetRemoteSourceByName(tx, remoteSourceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if remoteSource == nil {
|
if remoteSource == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q doesn't exist", remoteSourceName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q doesn't exist", remoteSourceName))
|
||||||
|
@ -206,13 +207,13 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
|
||||||
cgNames := []string{util.EncodeSha256Hex("remotesourceid-" + remoteSource.ID)}
|
cgNames := []string{util.EncodeSha256Hex("remotesourceid-" + remoteSource.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
|
@ -225,5 +226,5 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
|
||||||
|
|
||||||
// changegroup is all the remotesources
|
// changegroup is all the remotesources
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,12 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ActionHandler) GetSecret(ctx context.Context, secretID string) (*types.Secret, error) {
|
func (h *ActionHandler) GetSecret(ctx context.Context, secretID string) (*types.Secret, error) {
|
||||||
|
@ -32,10 +33,10 @@ func (h *ActionHandler) GetSecret(ctx context.Context, secretID string) (*types.
|
||||||
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
||||||
var err error
|
var err error
|
||||||
secret, err = h.readDB.GetSecretByID(tx, secretID)
|
secret, err = h.readDB.GetSecretByID(tx, secretID)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if secret == nil {
|
if secret == nil {
|
||||||
|
@ -50,17 +51,17 @@ func (h *ActionHandler) GetSecrets(ctx context.Context, parentType types.ConfigT
|
||||||
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
||||||
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if tree {
|
if tree {
|
||||||
secrets, err = h.readDB.GetSecretsTree(tx, parentType, parentID)
|
secrets, err = h.readDB.GetSecretsTree(tx, parentType, parentID)
|
||||||
} else {
|
} else {
|
||||||
secrets, err = h.readDB.GetSecrets(tx, parentID)
|
secrets, err = h.readDB.GetSecrets(tx, parentID)
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return secrets, nil
|
return secrets, nil
|
||||||
|
@ -97,7 +98,7 @@ func (h *ActionHandler) ValidateSecret(ctx context.Context, secret *types.Secret
|
||||||
|
|
||||||
func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret) (*types.Secret, error) {
|
func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret) (*types.Secret, error) {
|
||||||
if err := h.ValidateSecret(ctx, secret); err != nil {
|
if err := h.ValidateSecret(ctx, secret); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -109,19 +110,19 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
|
||||||
var err error
|
var err error
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parentID, err := h.ResolveConfigID(tx, secret.Parent.Type, secret.Parent.ID)
|
parentID, err := h.ResolveConfigID(tx, secret.Parent.Type, secret.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
secret.Parent.ID = parentID
|
secret.Parent.ID = parentID
|
||||||
|
|
||||||
// check duplicate secret name
|
// check duplicate secret name
|
||||||
s, err := h.readDB.GetSecretByName(tx, secret.Parent.ID, secret.Name)
|
s, err := h.readDB.GetSecretByName(tx, secret.Parent.ID, secret.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if s != nil {
|
if s != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q already exists", secret.Name, secret.Parent.Type, secret.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q already exists", secret.Name, secret.Parent.Type, secret.Parent.ID))
|
||||||
|
@ -130,14 +131,14 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secret.ID = uuid.Must(uuid.NewV4()).String()
|
secret.ID = uuid.Must(uuid.NewV4()).String()
|
||||||
|
|
||||||
secretj, err := json.Marshal(secret)
|
secretj, err := json.Marshal(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal secret: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal secret")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -149,7 +150,7 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return secret, err
|
return secret, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateSecretRequest struct {
|
type UpdateSecretRequest struct {
|
||||||
|
@ -160,7 +161,7 @@ type UpdateSecretRequest struct {
|
||||||
|
|
||||||
func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretRequest) (*types.Secret, error) {
|
func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretRequest) (*types.Secret, error) {
|
||||||
if err := h.ValidateSecret(ctx, req.Secret); err != nil {
|
if err := h.ValidateSecret(ctx, req.Secret); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var curSecret *types.Secret
|
var curSecret *types.Secret
|
||||||
|
@ -173,14 +174,14 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
|
||||||
|
|
||||||
parentID, err := h.ResolveConfigID(tx, req.Secret.Parent.Type, req.Secret.Parent.ID)
|
parentID, err := h.ResolveConfigID(tx, req.Secret.Parent.Type, req.Secret.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
req.Secret.Parent.ID = parentID
|
req.Secret.Parent.ID = parentID
|
||||||
|
|
||||||
// check secret exists
|
// check secret exists
|
||||||
curSecret, err = h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.SecretName)
|
curSecret, err = h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.SecretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if curSecret == nil {
|
if curSecret == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q doesn't exists", req.SecretName, req.Secret.Parent.Type, req.Secret.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q doesn't exists", req.SecretName, req.Secret.Parent.Type, req.Secret.Parent.ID))
|
||||||
|
@ -190,7 +191,7 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
|
||||||
// check duplicate secret name
|
// check duplicate secret name
|
||||||
u, err := h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.Secret.Name)
|
u, err := h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.Secret.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q already exists", req.Secret.Name, req.Secret.Parent.Type, req.Secret.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q already exists", req.Secret.Name, req.Secret.Parent.Type, req.Secret.Parent.ID))
|
||||||
|
@ -206,18 +207,18 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
|
||||||
}
|
}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secretj, err := json.Marshal(req.Secret)
|
secretj, err := json.Marshal(req.Secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal secret: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal secret")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -229,7 +230,7 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return req.Secret, err
|
return req.Secret, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.ConfigType, parentRef, secretName string) error {
|
func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.ConfigType, parentRef, secretName string) error {
|
||||||
|
@ -242,13 +243,13 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
|
||||||
var err error
|
var err error
|
||||||
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check secret existance
|
// check secret existance
|
||||||
secret, err = h.readDB.GetSecretByName(tx, parentID, secretName)
|
secret, err = h.readDB.GetSecretByName(tx, parentID, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if secret == nil {
|
if secret == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q doesn't exist", secretName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q doesn't exist", secretName))
|
||||||
|
@ -258,13 +259,13 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
|
||||||
cgNames := []string{util.EncodeSha256Hex("secretid-" + secret.ID)}
|
cgNames := []string{util.EncodeSha256Hex("secretid-" + secret.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
|
@ -276,5 +277,5 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,13 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/services/configstore/readdb"
|
"agola.io/agola/internal/services/configstore/readdb"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateUserRequest struct {
|
type CreateUserRequest struct {
|
||||||
|
@ -54,13 +55,13 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
||||||
var err error
|
var err error
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check duplicate user name
|
// check duplicate user name
|
||||||
u, err := h.readDB.GetUserByName(tx, req.UserName)
|
u, err := h.readDB.GetUserByName(tx, req.UserName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name))
|
||||||
|
@ -69,14 +70,14 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
||||||
if req.CreateUserLARequest != nil {
|
if req.CreateUserLARequest != nil {
|
||||||
rs, err = h.readDB.GetRemoteSourceByName(tx, req.CreateUserLARequest.RemoteSourceName)
|
rs, err = h.readDB.GetRemoteSourceByName(tx, req.CreateUserLARequest.RemoteSourceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if rs == nil {
|
if rs == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.CreateUserLARequest.RemoteSourceName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.CreateUserLARequest.RemoteSourceName))
|
||||||
}
|
}
|
||||||
user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.CreateUserLARequest.RemoteUserID, rs.ID)
|
user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.CreateUserLARequest.RemoteUserID, rs.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to get user for remote user id %q and remote source %q: %w", req.CreateUserLARequest.RemoteUserID, rs.ID, err)
|
return errors.Wrapf(err, "failed to get user for remote user id %q and remote source %q", req.CreateUserLARequest.RemoteUserID, rs.ID)
|
||||||
}
|
}
|
||||||
if user != nil {
|
if user != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for remote user id %q for remote source %q already exists", req.CreateUserLARequest.RemoteUserID, req.CreateUserLARequest.RemoteSourceName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for remote user id %q for remote source %q already exists", req.CreateUserLARequest.RemoteUserID, req.CreateUserLARequest.RemoteSourceName))
|
||||||
|
@ -85,7 +86,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
user := &types.User{
|
user := &types.User{
|
||||||
|
@ -114,7 +115,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal user: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
|
|
||||||
// create root user project group
|
// create root user project group
|
||||||
|
@ -129,7 +130,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
||||||
}
|
}
|
||||||
pgj, err := json.Marshal(pg)
|
pgj, err := json.Marshal(pg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal project group: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal project group")
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
|
@ -148,7 +149,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return user, err
|
return user, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
|
func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
|
||||||
|
@ -162,7 +163,7 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
|
||||||
// check user existance
|
// check user existance
|
||||||
user, err = h.readDB.GetUser(tx, userRef)
|
user, err = h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
||||||
|
@ -172,13 +173,13 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
|
||||||
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
|
@ -190,7 +191,7 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateUserRequest struct {
|
type UpdateUserRequest struct {
|
||||||
|
@ -210,7 +211,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
|
||||||
var err error
|
var err error
|
||||||
user, err = h.readDB.GetUser(tx, req.UserRef)
|
user, err = h.readDB.GetUser(tx, req.UserRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
|
||||||
|
@ -218,14 +219,14 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
|
||||||
|
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.UserName != "" {
|
if req.UserName != "" {
|
||||||
// check duplicate user name
|
// check duplicate user name
|
||||||
u, err := h.readDB.GetUserByName(tx, req.UserName)
|
u, err := h.readDB.GetUserByName(tx, req.UserName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name))
|
||||||
|
@ -238,7 +239,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.UserName != "" {
|
if req.UserName != "" {
|
||||||
|
@ -247,7 +248,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal user: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
|
@ -260,7 +261,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return user, err
|
return user, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateUserLARequest struct {
|
type CreateUserLARequest struct {
|
||||||
|
@ -293,7 +294,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
|
||||||
var err error
|
var err error
|
||||||
user, err = h.readDB.GetUser(tx, req.UserRef)
|
user, err = h.readDB.GetUser(tx, req.UserRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
|
||||||
|
@ -303,12 +304,12 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
|
||||||
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rs, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceName)
|
rs, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if rs == nil {
|
if rs == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.RemoteSourceName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.RemoteSourceName))
|
||||||
|
@ -316,7 +317,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
|
||||||
|
|
||||||
user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.RemoteUserID, rs.ID)
|
user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.RemoteUserID, rs.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to get user for remote user id %q and remote source %q: %w", req.RemoteUserID, rs.ID, err)
|
return errors.Wrapf(err, "failed to get user for remote user id %q and remote source %q", req.RemoteUserID, rs.ID)
|
||||||
}
|
}
|
||||||
if user != nil {
|
if user != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for remote user id %q for remote source %q already exists", req.RemoteUserID, req.RemoteSourceName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for remote user id %q for remote source %q already exists", req.RemoteUserID, req.RemoteSourceName))
|
||||||
|
@ -324,7 +325,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.LinkedAccounts == nil {
|
if user.LinkedAccounts == nil {
|
||||||
|
@ -346,7 +347,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal user: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -358,7 +359,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return la, err
|
return la, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string) error {
|
func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string) error {
|
||||||
|
@ -378,7 +379,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
|
||||||
var err error
|
var err error
|
||||||
user, err = h.readDB.GetUser(tx, userRef)
|
user, err = h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
||||||
|
@ -388,13 +389,13 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
|
||||||
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := user.LinkedAccounts[laID]
|
_, ok := user.LinkedAccounts[laID]
|
||||||
|
@ -406,7 +407,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to marshal user: %w", err)
|
return errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -418,7 +419,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateUserLARequest struct {
|
type UpdateUserLARequest struct {
|
||||||
|
@ -448,7 +449,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
|
||||||
var err error
|
var err error
|
||||||
user, err = h.readDB.GetUser(tx, req.UserRef)
|
user, err = h.readDB.GetUser(tx, req.UserRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
|
||||||
|
@ -458,7 +459,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
|
||||||
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
la, ok := user.LinkedAccounts[req.LinkedAccountID]
|
la, ok := user.LinkedAccounts[req.LinkedAccountID]
|
||||||
|
@ -468,7 +469,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
|
||||||
|
|
||||||
rs, err = h.readDB.GetRemoteSource(tx, la.RemoteSourceID)
|
rs, err = h.readDB.GetRemoteSource(tx, la.RemoteSourceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if rs == nil {
|
if rs == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source with id %q doesn't exist", la.RemoteSourceID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source with id %q doesn't exist", la.RemoteSourceID))
|
||||||
|
@ -476,7 +477,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
la := user.LinkedAccounts[req.LinkedAccountID]
|
la := user.LinkedAccounts[req.LinkedAccountID]
|
||||||
|
@ -490,7 +491,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal user: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -502,7 +503,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return la, err
|
return la, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName string) (string, error) {
|
func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName string) (string, error) {
|
||||||
|
@ -522,7 +523,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
|
||||||
var err error
|
var err error
|
||||||
user, err = h.readDB.GetUser(tx, userRef)
|
user, err = h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
||||||
|
@ -532,13 +533,13 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
|
||||||
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user.Tokens != nil {
|
if user.Tokens != nil {
|
||||||
if _, ok := user.Tokens[tokenName]; ok {
|
if _, ok := user.Tokens[tokenName]; ok {
|
||||||
|
@ -555,7 +556,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Errorf("failed to marshal user: %w", err)
|
return "", errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -567,7 +568,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return token, err
|
return token, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName string) error {
|
func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName string) error {
|
||||||
|
@ -587,7 +588,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
|
||||||
var err error
|
var err error
|
||||||
user, err = h.readDB.GetUser(tx, userRef)
|
user, err = h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
|
||||||
|
@ -597,13 +598,13 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
|
||||||
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := user.Tokens[tokenName]
|
_, ok := user.Tokens[tokenName]
|
||||||
|
@ -615,7 +616,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
|
||||||
|
|
||||||
userj, err := json.Marshal(user)
|
userj, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("failed to marshal user: %w", err)
|
return errors.Wrapf(err, "failed to marshal user")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -627,7 +628,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserOrgsResponse struct {
|
type UserOrgsResponse struct {
|
||||||
|
@ -648,17 +649,17 @@ func (h *ActionHandler) GetUserOrgs(ctx context.Context, userRef string) ([]*Use
|
||||||
var err error
|
var err error
|
||||||
user, err := h.readDB.GetUser(tx, userRef)
|
user, err := h.readDB.GetUser(tx, userRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return util.NewAPIError(util.ErrNotExist, errors.Errorf("user %q doesn't exist", userRef))
|
return util.NewAPIError(util.ErrNotExist, errors.Errorf("user %q doesn't exist", userRef))
|
||||||
}
|
}
|
||||||
|
|
||||||
userOrgs, err = h.readDB.GetUserOrgs(tx, user.ID)
|
userOrgs, err = h.readDB.GetUserOrgs(tx, user.ID)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]*UserOrgsResponse, len(userOrgs))
|
res := make([]*UserOrgsResponse, len(userOrgs))
|
||||||
|
|
|
@ -20,11 +20,12 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/datamanager"
|
"agola.io/agola/internal/datamanager"
|
||||||
"agola.io/agola/internal/db"
|
"agola.io/agola/internal/db"
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
|
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ActionHandler) GetVariables(ctx context.Context, parentType types.ConfigType, parentRef string, tree bool) ([]*types.Variable, error) {
|
func (h *ActionHandler) GetVariables(ctx context.Context, parentType types.ConfigType, parentRef string, tree bool) ([]*types.Variable, error) {
|
||||||
|
@ -32,17 +33,17 @@ func (h *ActionHandler) GetVariables(ctx context.Context, parentType types.Confi
|
||||||
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
|
||||||
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if tree {
|
if tree {
|
||||||
variables, err = h.readDB.GetVariablesTree(tx, parentType, parentID)
|
variables, err = h.readDB.GetVariablesTree(tx, parentType, parentID)
|
||||||
} else {
|
} else {
|
||||||
variables, err = h.readDB.GetVariables(tx, parentID)
|
variables, err = h.readDB.GetVariables(tx, parentID)
|
||||||
}
|
}
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return variables, nil
|
return variables, nil
|
||||||
|
@ -73,7 +74,7 @@ func (h *ActionHandler) ValidateVariable(ctx context.Context, variable *types.Va
|
||||||
|
|
||||||
func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Variable) (*types.Variable, error) {
|
func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Variable) (*types.Variable, error) {
|
||||||
if err := h.ValidateVariable(ctx, variable); err != nil {
|
if err := h.ValidateVariable(ctx, variable); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -85,19 +86,19 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
|
||||||
var err error
|
var err error
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parentID, err := h.ResolveConfigID(tx, variable.Parent.Type, variable.Parent.ID)
|
parentID, err := h.ResolveConfigID(tx, variable.Parent.Type, variable.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
variable.Parent.ID = parentID
|
variable.Parent.ID = parentID
|
||||||
|
|
||||||
// check duplicate variable name
|
// check duplicate variable name
|
||||||
s, err := h.readDB.GetVariableByName(tx, variable.Parent.ID, variable.Name)
|
s, err := h.readDB.GetVariableByName(tx, variable.Parent.ID, variable.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if s != nil {
|
if s != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q already exists", variable.Name, variable.Parent.Type, variable.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q already exists", variable.Name, variable.Parent.Type, variable.Parent.ID))
|
||||||
|
@ -106,14 +107,14 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
variable.ID = uuid.Must(uuid.NewV4()).String()
|
variable.ID = uuid.Must(uuid.NewV4()).String()
|
||||||
|
|
||||||
variablej, err := json.Marshal(variable)
|
variablej, err := json.Marshal(variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal variable: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal variable")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -125,7 +126,7 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return variable, err
|
return variable, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateVariableRequest struct {
|
type UpdateVariableRequest struct {
|
||||||
|
@ -136,7 +137,7 @@ type UpdateVariableRequest struct {
|
||||||
|
|
||||||
func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableRequest) (*types.Variable, error) {
|
func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableRequest) (*types.Variable, error) {
|
||||||
if err := h.ValidateVariable(ctx, req.Variable); err != nil {
|
if err := h.ValidateVariable(ctx, req.Variable); err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var curVariable *types.Variable
|
var curVariable *types.Variable
|
||||||
|
@ -149,14 +150,14 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
|
||||||
|
|
||||||
parentID, err := h.ResolveConfigID(tx, req.Variable.Parent.Type, req.Variable.Parent.ID)
|
parentID, err := h.ResolveConfigID(tx, req.Variable.Parent.Type, req.Variable.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
req.Variable.Parent.ID = parentID
|
req.Variable.Parent.ID = parentID
|
||||||
|
|
||||||
// check variable exists
|
// check variable exists
|
||||||
curVariable, err = h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.VariableName)
|
curVariable, err = h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.VariableName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if curVariable == nil {
|
if curVariable == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q doesn't exists", req.VariableName, req.Variable.Parent.Type, req.Variable.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q doesn't exists", req.VariableName, req.Variable.Parent.Type, req.Variable.Parent.ID))
|
||||||
|
@ -166,7 +167,7 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
|
||||||
// check duplicate variable name
|
// check duplicate variable name
|
||||||
u, err := h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.Variable.Name)
|
u, err := h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.Variable.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q already exists", req.Variable.Name, req.Variable.Parent.Type, req.Variable.Parent.ID))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q already exists", req.Variable.Name, req.Variable.Parent.Type, req.Variable.Parent.ID))
|
||||||
|
@ -182,18 +183,18 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
|
||||||
}
|
}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
variablej, err := json.Marshal(req.Variable)
|
variablej, err := json.Marshal(req.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("failed to marshal variable: %w", err)
|
return nil, errors.Wrapf(err, "failed to marshal variable")
|
||||||
}
|
}
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
{
|
{
|
||||||
|
@ -205,7 +206,7 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return req.Variable, err
|
return req.Variable, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.ConfigType, parentRef, variableName string) error {
|
func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.ConfigType, parentRef, variableName string) error {
|
||||||
|
@ -218,13 +219,13 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
|
||||||
var err error
|
var err error
|
||||||
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check variable existance
|
// check variable existance
|
||||||
variable, err = h.readDB.GetVariableByName(tx, parentID, variableName)
|
variable, err = h.readDB.GetVariableByName(tx, parentID, variableName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
if variable == nil {
|
if variable == nil {
|
||||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q doesn't exist", variableName))
|
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q doesn't exist", variableName))
|
||||||
|
@ -234,12 +235,12 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
|
||||||
cgNames := []string{util.EncodeSha256Hex("variableid-" + variable.ID)}
|
cgNames := []string{util.EncodeSha256Hex("variableid-" + variable.ID)}
|
||||||
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := []*datamanager.Action{
|
actions := []*datamanager.Action{
|
||||||
|
@ -251,5 +252,5 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
return err
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"agola.io/agola/internal/errors"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
"agola.io/agola/services/configstore/types"
|
"agola.io/agola/services/configstore/types"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
errors "golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ErrorResponse struct {
|
type ErrorResponse struct {
|
||||||
|
@ -33,7 +33,7 @@ func GetConfigTypeRef(r *http.Request) (types.ConfigType, string, error) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
projectRef, err := url.PathUnescape(vars["projectref"])
|
projectRef, err := url.PathUnescape(vars["projectref"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("wrong projectref %q: %w", vars["projectref"], err))
|
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Wrapf(err, "wrong projectref %q", vars["projectref"]))
|
||||||
}
|
}
|
||||||
if projectRef != "" {
|
if projectRef != "" {
|
||||||
return types.ConfigTypeProject, projectRef, nil
|
return types.ConfigTypeProject, projectRef, nil
|
||||||
|
@ -41,7 +41,7 @@ func GetConfigTypeRef(r *http.Request) (types.ConfigType, string, error) {
|
||||||
|
|
||||||
projectGroupRef, err := url.PathUnescape(vars["projectgroupref"])
|
projectGroupRef, err := url.PathUnescape(vars["projectgroupref"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("wrong projectgroupref %q: %w", vars["projectgroupref"], err))
|
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Wrapf(err, "wrong projectgroupref %q", vars["projectgroupref"]))
|
||||||
}
|
}
|
||||||
if projectGroupRef != "" {
|
if projectGroupRef != "" {
|
||||||
return types.ConfigTypeProjectGroup, projectGroupRef, nil
|
return types.ConfigTypeProjectGroup, projectGroupRef, nil
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue