mirror of
https://github.com/juanfont/headscale.git
synced 2026-04-05 00:37:13 +02:00
errors: rewrite errors to follow go best practices
Errors should not start capitalised and they should not contain the word error or state that they "failed" as we already know it is an error Signed-off-by: Kristoffer Dalby <kristoffer@dalby.cc>
This commit is contained in:
@@ -121,7 +121,7 @@ func NewHeadscale(cfg *types.Config) (*Headscale, error) {
|
||||
|
||||
noisePrivateKey, err := readOrCreatePrivateKey(cfg.NoisePrivateKeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read or create Noise protocol private key: %w", err)
|
||||
return nil, fmt.Errorf("reading or creating Noise protocol private key: %w", err)
|
||||
}
|
||||
|
||||
s, err := state.NewState(cfg)
|
||||
@@ -206,7 +206,7 @@ func NewHeadscale(cfg *types.Config) (*Headscale, error) {
|
||||
if cfg.DERP.ServerEnabled {
|
||||
derpServerKey, err := readOrCreatePrivateKey(cfg.DERP.ServerPrivateKeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read or create DERP server private key: %w", err)
|
||||
return nil, fmt.Errorf("reading or creating DERP server private key: %w", err)
|
||||
}
|
||||
|
||||
if derpServerKey.Equal(*noisePrivateKey) {
|
||||
@@ -339,7 +339,7 @@ func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context,
|
||||
if !ok {
|
||||
return ctx, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"Retrieving metadata is failed",
|
||||
"retrieving metadata",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context,
|
||||
if !ok {
|
||||
return ctx, status.Errorf(
|
||||
codes.Unauthenticated,
|
||||
"Authorization token is not supplied",
|
||||
"authorization token not supplied",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context,
|
||||
|
||||
valid, err := h.state.ValidateAPIKey(strings.TrimPrefix(token, AuthPrefix))
|
||||
if err != nil {
|
||||
return ctx, status.Error(codes.Internal, "failed to validate token")
|
||||
return ctx, status.Error(codes.Internal, "validating token")
|
||||
}
|
||||
|
||||
if !valid {
|
||||
@@ -526,7 +526,7 @@ func (h *Headscale) Serve() error {
|
||||
|
||||
derpMap, err := derp.GetDERPMap(h.cfg.DERP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get DERPMap: %w", err)
|
||||
return fmt.Errorf("getting DERPMap: %w", err)
|
||||
}
|
||||
|
||||
if h.cfg.DERP.ServerEnabled && h.cfg.DERP.AutomaticallyAddEmbeddedDerpRegion {
|
||||
@@ -586,7 +586,7 @@ func (h *Headscale) Serve() error {
|
||||
|
||||
err = h.ensureUnixSocketIsAbsent()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to remove old socket file: %w", err)
|
||||
return fmt.Errorf("removing old socket file: %w", err)
|
||||
}
|
||||
|
||||
socketDir := filepath.Dir(h.cfg.UnixSocket)
|
||||
@@ -597,12 +597,12 @@ func (h *Headscale) Serve() error {
|
||||
|
||||
socketListener, err := net.Listen("unix", h.cfg.UnixSocket)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set up gRPC socket: %w", err)
|
||||
return fmt.Errorf("setting up gRPC socket: %w", err)
|
||||
}
|
||||
|
||||
// Change socket permissions
|
||||
if err := os.Chmod(h.cfg.UnixSocket, h.cfg.UnixSocketPermission); err != nil {
|
||||
return fmt.Errorf("failed change permission of gRPC socket: %w", err)
|
||||
return fmt.Errorf("changing gRPC socket permission: %w", err)
|
||||
}
|
||||
|
||||
grpcGatewayMux := grpcRuntime.NewServeMux()
|
||||
@@ -687,7 +687,7 @@ func (h *Headscale) Serve() error {
|
||||
|
||||
grpcListener, err = net.Listen("tcp", h.cfg.GRPCAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
||||
return fmt.Errorf("binding to TCP address: %w", err)
|
||||
}
|
||||
|
||||
errorGroup.Go(func() error { return grpcServer.Serve(grpcListener) })
|
||||
@@ -722,7 +722,7 @@ func (h *Headscale) Serve() error {
|
||||
httpListener, err = net.Listen("tcp", h.cfg.Addr)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
||||
return fmt.Errorf("binding to TCP address: %w", err)
|
||||
}
|
||||
|
||||
errorGroup.Go(func() error { return httpServer.Serve(httpListener) })
|
||||
@@ -738,7 +738,7 @@ func (h *Headscale) Serve() error {
|
||||
if h.cfg.MetricsAddr != "" {
|
||||
debugHTTPListener, err = (&net.ListenConfig{}).Listen(ctx, "tcp", h.cfg.MetricsAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
||||
return fmt.Errorf("binding to TCP address: %w", err)
|
||||
}
|
||||
|
||||
debugHTTPServer = h.debugHTTPServer()
|
||||
@@ -977,14 +977,14 @@ func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) {
|
||||
machineKeyStr, err := machineKey.MarshalText()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to convert private key to string for saving: %w",
|
||||
"converting private key to string for saving: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
err = os.WriteFile(path, machineKeyStr, privateKeyFileMode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to save private key to disk at path %q: %w",
|
||||
"saving private key to disk at path %q: %w",
|
||||
path,
|
||||
err,
|
||||
)
|
||||
@@ -992,14 +992,14 @@ func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) {
|
||||
|
||||
return &machineKey, nil
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("failed to read private key file: %w", err)
|
||||
return nil, fmt.Errorf("reading private key file: %w", err)
|
||||
}
|
||||
|
||||
trimmedPrivateKey := strings.TrimSpace(string(privateKey))
|
||||
|
||||
var machineKey key.MachinePrivate
|
||||
if err = machineKey.UnmarshalText([]byte(trimmedPrivateKey)); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse private key: %w", err)
|
||||
return nil, fmt.Errorf("parsing private key: %w", err)
|
||||
}
|
||||
|
||||
return &machineKey, nil
|
||||
|
||||
@@ -78,7 +78,7 @@ func (hsdb *HSDatabase) CreateAPIKey(
|
||||
}
|
||||
|
||||
if err := hsdb.DB.Save(&key).Error; err != nil {
|
||||
return "", nil, fmt.Errorf("failed to save API key to database: %w", err)
|
||||
return "", nil, fmt.Errorf("saving API key to database: %w", err)
|
||||
}
|
||||
|
||||
return keyStr, &key, nil
|
||||
|
||||
@@ -290,7 +290,7 @@ func (db *HSDatabase) BackfillNodeIPs(i *IPAllocator) ([]string, error) {
|
||||
if i.prefix4 != nil && node.IPv4 == nil {
|
||||
ret4, err := i.nextLocked(i.prev4, i.prefix4)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to allocate ipv4 for node(%d): %w", node.ID, err)
|
||||
return fmt.Errorf("allocating IPv4 for node(%d): %w", node.ID, err)
|
||||
}
|
||||
|
||||
node.IPv4 = ret4
|
||||
@@ -302,7 +302,7 @@ func (db *HSDatabase) BackfillNodeIPs(i *IPAllocator) ([]string, error) {
|
||||
if i.prefix6 != nil && node.IPv6 == nil {
|
||||
ret6, err := i.nextLocked(i.prev6, i.prefix6)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to allocate ipv6 for node(%d): %w", node.ID, err)
|
||||
return fmt.Errorf("allocating IPv6 for node(%d): %w", node.ID, err)
|
||||
}
|
||||
|
||||
node.IPv6 = ret6
|
||||
|
||||
@@ -290,7 +290,7 @@ func RenameNode(tx *gorm.DB,
|
||||
|
||||
err = tx.Model(&types.Node{}).Where("given_name = ? AND id != ?", newName, nodeID).Count(&count).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check name uniqueness: %w", err)
|
||||
return fmt.Errorf("checking name uniqueness: %w", err)
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
@@ -298,7 +298,7 @@ func RenameNode(tx *gorm.DB,
|
||||
}
|
||||
|
||||
if err := tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("given_name", newName).Error; err != nil {
|
||||
return fmt.Errorf("failed to rename node in the database: %w", err)
|
||||
return fmt.Errorf("renaming node in database: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -396,7 +396,7 @@ func RegisterNodeForTest(tx *gorm.DB, node types.Node, ipv4 *netip.Addr, ipv6 *n
|
||||
// adding it to the registrationCache
|
||||
if node.IPv4 != nil || node.IPv6 != nil {
|
||||
if err := tx.Save(&node).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed register existing node in the database: %w", err)
|
||||
return nil, fmt.Errorf("registering existing node in database: %w", err)
|
||||
}
|
||||
|
||||
log.Trace().
|
||||
@@ -425,14 +425,14 @@ func RegisterNodeForTest(tx *gorm.DB, node types.Node, ipv4 *netip.Addr, ipv6 *n
|
||||
if node.GivenName == "" {
|
||||
givenName, err := EnsureUniqueGivenName(tx, node.Hostname)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure unique given name: %w", err)
|
||||
return nil, fmt.Errorf("ensuring unique given name: %w", err)
|
||||
}
|
||||
|
||||
node.GivenName = givenName
|
||||
}
|
||||
|
||||
if err := tx.Save(&node).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed register(save) node in the database: %w", err)
|
||||
return nil, fmt.Errorf("saving node to database: %w", err)
|
||||
}
|
||||
|
||||
log.Trace().
|
||||
|
||||
@@ -139,7 +139,7 @@ func CreatePreAuthKey(
|
||||
}
|
||||
|
||||
if err := tx.Save(&key).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to create key in the database: %w", err)
|
||||
return nil, fmt.Errorf("creating key in database: %w", err)
|
||||
}
|
||||
|
||||
return &types.PreAuthKeyNew{
|
||||
@@ -296,7 +296,7 @@ func DestroyPreAuthKey(tx *gorm.DB, id uint64) error {
|
||||
Where("auth_key_id = ?", id).
|
||||
Update("auth_key_id", nil).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to clear auth_key_id on nodes: %w", err)
|
||||
return fmt.Errorf("clearing auth_key_id on nodes: %w", err)
|
||||
}
|
||||
|
||||
// Then delete the pre-auth key
|
||||
@@ -325,7 +325,7 @@ func (hsdb *HSDatabase) DeletePreAuthKey(id uint64) error {
|
||||
func UsePreAuthKey(tx *gorm.DB, k *types.PreAuthKey) error {
|
||||
err := tx.Model(k).Update("used", true).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update key used status in the database: %w", err)
|
||||
return fmt.Errorf("updating key used status in database: %w", err)
|
||||
}
|
||||
|
||||
k.Used = true
|
||||
|
||||
@@ -24,7 +24,7 @@ func maybeInstantiatePtr(rv reflect.Value) {
|
||||
}
|
||||
|
||||
func decodingError(name string, err error) error {
|
||||
return fmt.Errorf("error decoding to %s: %w", name, err)
|
||||
return fmt.Errorf("decoding to %s: %w", name, err)
|
||||
}
|
||||
|
||||
// TextSerialiser implements the Serialiser interface for fields that
|
||||
@@ -48,7 +48,7 @@ func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect
|
||||
case string:
|
||||
bytes = []byte(v)
|
||||
default:
|
||||
return fmt.Errorf("failed to unmarshal text value: %#v", dbValue)
|
||||
return fmt.Errorf("unmarshalling text value: %#v", dbValue)
|
||||
}
|
||||
|
||||
if isTextUnmarshaler(fieldValue) {
|
||||
|
||||
@@ -55,7 +55,7 @@ func (api headscaleV1APIServer) CreateUser(
|
||||
}
|
||||
user, policyChanged, err := api.h.state.CreateUser(newUser)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to create user: %s", err)
|
||||
return nil, status.Errorf(codes.Internal, "creating user: %s", err)
|
||||
}
|
||||
|
||||
// CreateUser returns a policy change response if the user creation affected policy.
|
||||
@@ -423,7 +423,7 @@ func validateTag(tag string) error {
|
||||
return errors.New("tag should be lowercase")
|
||||
}
|
||||
if len(strings.Fields(tag)) > 1 {
|
||||
return errors.New("tag should not contains space")
|
||||
return errors.New("tags must not contain spaces")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -817,7 +817,7 @@ func (api headscaleV1APIServer) Health(
|
||||
response := &v1.HealthResponse{}
|
||||
|
||||
if err := api.h.state.PingDB(ctx); err != nil {
|
||||
healthErr = fmt.Errorf("database ping failed: %w", err)
|
||||
healthErr = fmt.Errorf("pinging database: %w", err)
|
||||
} else {
|
||||
response.DatabaseConnectivity = true
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func NewHTTPError(code int, msg string, err error) HTTPError {
|
||||
var errMethodNotAllowed = NewHTTPError(http.StatusMethodNotAllowed, "method not allowed", nil)
|
||||
|
||||
var ErrRegisterMethodCLIDoesNotSupportExpire = errors.New(
|
||||
"machines registered with CLI does not support expire",
|
||||
"machines registered with CLI do not support expiry",
|
||||
)
|
||||
|
||||
func parseCapabilityVersion(req *http.Request) (tailcfg.CapabilityVersion, error) {
|
||||
@@ -76,7 +76,7 @@ func parseCapabilityVersion(req *http.Request) (tailcfg.CapabilityVersion, error
|
||||
|
||||
clientCapabilityVersion, err := strconv.Atoi(clientCapabilityStr)
|
||||
if err != nil {
|
||||
return 0, NewHTTPError(http.StatusBadRequest, "invalid capability version", fmt.Errorf("failed to parse capability version: %w", err))
|
||||
return 0, NewHTTPError(http.StatusBadRequest, "invalid capability version", fmt.Errorf("parsing capability version: %w", err))
|
||||
}
|
||||
|
||||
return tailcfg.CapabilityVersion(clientCapabilityVersion), nil
|
||||
@@ -88,12 +88,12 @@ func (h *Headscale) handleVerifyRequest(
|
||||
) error {
|
||||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read request body: %w", err)
|
||||
return fmt.Errorf("reading request body: %w", err)
|
||||
}
|
||||
|
||||
var derpAdmitClientRequest tailcfg.DERPAdmitClientRequest
|
||||
if err := json.Unmarshal(body, &derpAdmitClientRequest); err != nil {
|
||||
return NewHTTPError(http.StatusBadRequest, "Bad Request: invalid JSON", fmt.Errorf("cannot parse derpAdmitClientRequest: %w", err))
|
||||
return NewHTTPError(http.StatusBadRequest, "Bad Request: invalid JSON", fmt.Errorf("parsing DERP client request: %w", err))
|
||||
}
|
||||
|
||||
nodes := h.state.ListNodes()
|
||||
|
||||
@@ -81,7 +81,7 @@ func (b *LockFreeBatcher) AddNode(id types.NodeID, c chan<- *tailcfg.MapResponse
|
||||
if err != nil {
|
||||
nlog.Error().Err(err).Msg("initial map generation failed")
|
||||
nodeConn.removeConnectionByChannel(c)
|
||||
return fmt.Errorf("failed to generate initial map for node %d: %w", id, err)
|
||||
return fmt.Errorf("generating initial map for node %d: %w", id, err)
|
||||
}
|
||||
|
||||
// Use a blocking send with timeout for initial map since the channel should be ready
|
||||
@@ -94,7 +94,7 @@ func (b *LockFreeBatcher) AddNode(id types.NodeID, c chan<- *tailcfg.MapResponse
|
||||
nlog.Debug().Caller().Dur("timeout.duration", 5*time.Second). //nolint:mnd
|
||||
Msg("initial map send timed out because channel was blocked or receiver not ready")
|
||||
nodeConn.removeConnectionByChannel(c)
|
||||
return fmt.Errorf("failed to send initial map to node %d: timeout", id)
|
||||
return fmt.Errorf("sending initial map to node %d: timeout", id)
|
||||
}
|
||||
|
||||
// Update connection status
|
||||
|
||||
@@ -79,7 +79,7 @@ func (h *Headscale) NoiseUpgradeHandler(
|
||||
noiseServer.earlyNoise,
|
||||
)
|
||||
if err != nil {
|
||||
httpError(writer, fmt.Errorf("noise upgrade failed: %w", err))
|
||||
httpError(writer, fmt.Errorf("upgrading noise connection: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ const (
|
||||
|
||||
var (
|
||||
errEmptyOIDCCallbackParams = errors.New("empty OIDC callback params")
|
||||
errNoOIDCIDToken = errors.New("could not extract ID Token for OIDC callback")
|
||||
errNoOIDCRegistrationInfo = errors.New("could not get registration info from cache")
|
||||
errNoOIDCIDToken = errors.New("extracting ID token")
|
||||
errNoOIDCRegistrationInfo = errors.New("registration info not in cache")
|
||||
errOIDCAllowedDomains = errors.New(
|
||||
"authenticated principal does not match any allowed domain",
|
||||
)
|
||||
@@ -377,7 +377,7 @@ func (a *AuthProviderOIDC) getOauth2Token(
|
||||
|
||||
oauth2Token, err := a.oauth2Config.Exchange(ctx, code, exchangeOpts...)
|
||||
if err != nil {
|
||||
return nil, NewHTTPError(http.StatusForbidden, "invalid code", fmt.Errorf("could not exchange code for token: %w", err))
|
||||
return nil, NewHTTPError(http.StatusForbidden, "invalid code", fmt.Errorf("exchanging code for token: %w", err))
|
||||
}
|
||||
|
||||
return oauth2Token, err
|
||||
@@ -396,7 +396,7 @@ func (a *AuthProviderOIDC) extractIDToken(
|
||||
verifier := a.oidcProvider.Verifier(&oidc.Config{ClientID: a.cfg.ClientID})
|
||||
idToken, err := verifier.Verify(ctx, rawIDToken)
|
||||
if err != nil {
|
||||
return nil, NewHTTPError(http.StatusForbidden, "failed to verify id_token", fmt.Errorf("failed to verify ID token: %w", err))
|
||||
return nil, NewHTTPError(http.StatusForbidden, "failed to verify id_token", fmt.Errorf("verifying ID token: %w", err))
|
||||
}
|
||||
|
||||
return idToken, nil
|
||||
@@ -561,7 +561,7 @@ func (a *AuthProviderOIDC) handleRegistration(
|
||||
util.RegisterMethodOIDC,
|
||||
)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not register node: %w", err)
|
||||
return false, fmt.Errorf("registering node: %w", err)
|
||||
}
|
||||
|
||||
// This is a bit of a back and forth, but we have a bit of a chicken and egg
|
||||
|
||||
@@ -138,7 +138,7 @@ func (u Username) Validate() error {
|
||||
if isUser(string(u)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Username has to contain @, got: %q", u)
|
||||
return fmt.Errorf("username must contain @, got: %q", u)
|
||||
}
|
||||
|
||||
func (u *Username) String() string {
|
||||
@@ -243,7 +243,7 @@ func (g Group) Validate() error {
|
||||
if isGroup(string(g)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf(`Group has to start with "group:", got: %q`, g)
|
||||
return fmt.Errorf(`group must start with "group:", got: %q`, g)
|
||||
}
|
||||
|
||||
func (g *Group) UnmarshalJSON(b []byte) error {
|
||||
@@ -354,7 +354,7 @@ func (h Host) Validate() error {
|
||||
if isHost(string(h)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Hostname %q is invalid", h)
|
||||
return fmt.Errorf("hostname %q is invalid", h)
|
||||
}
|
||||
|
||||
func (h *Host) UnmarshalJSON(b []byte) error {
|
||||
@@ -372,7 +372,7 @@ func (h Host) Resolve(p *Policy, _ types.Users, nodes views.Slice[types.NodeView
|
||||
|
||||
pref, ok := p.Hosts[h]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to resolve host: %q", h)
|
||||
return nil, fmt.Errorf("resolving host: %q", h)
|
||||
}
|
||||
err := pref.Validate()
|
||||
if err != nil {
|
||||
@@ -406,7 +406,7 @@ func (p Prefix) Validate() error {
|
||||
if netip.Prefix(p).IsValid() {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Prefix %q is invalid", p)
|
||||
return fmt.Errorf("prefix %q is invalid", p)
|
||||
}
|
||||
|
||||
func (p Prefix) String() string {
|
||||
@@ -505,7 +505,7 @@ func (ag AutoGroup) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("AutoGroup is invalid, got: %q, must be one of %v", ag, autogroups)
|
||||
return fmt.Errorf("autogroup is invalid, got: %q, must be one of %v", ag, autogroups)
|
||||
}
|
||||
|
||||
func (ag *AutoGroup) UnmarshalJSON(b []byte) error {
|
||||
@@ -1003,14 +1003,14 @@ func (g *Groups) UnmarshalJSON(b []byte) error {
|
||||
if str, ok := item.(string); ok {
|
||||
stringSlice = append(stringSlice, str)
|
||||
} else {
|
||||
return fmt.Errorf(`Group "%s" contains invalid member type, expected string but got %T`, key, item)
|
||||
return fmt.Errorf(`group "%s" contains invalid member type, expected string but got %T`, key, item)
|
||||
}
|
||||
}
|
||||
rawGroups[key] = stringSlice
|
||||
case string:
|
||||
return fmt.Errorf(`Group "%s" value must be an array of users, got string: "%s"`, key, v)
|
||||
return fmt.Errorf(`group "%s" value must be an array of users, got string: "%s"`, key, v)
|
||||
default:
|
||||
return fmt.Errorf(`Group "%s" value must be an array of users, got %T`, key, v)
|
||||
return fmt.Errorf(`group "%s" value must be an array of users, got %T`, key, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,7 +1024,7 @@ func (g *Groups) UnmarshalJSON(b []byte) error {
|
||||
username := Username(u)
|
||||
if err := username.Validate(); err != nil {
|
||||
if isGroup(u) {
|
||||
return fmt.Errorf("Nested groups are not allowed, found %q inside %q", u, group)
|
||||
return fmt.Errorf("nested groups are not allowed, found %q inside %q", u, group)
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -1056,7 +1056,7 @@ func (h *Hosts) UnmarshalJSON(b []byte) error {
|
||||
|
||||
var prefix Prefix
|
||||
if err := prefix.parseString(value); err != nil {
|
||||
return fmt.Errorf(`Hostname "%s" contains an invalid IP address: "%s"`, key, value)
|
||||
return fmt.Errorf(`hostname "%s" contains an invalid IP address: "%s"`, key, value)
|
||||
}
|
||||
|
||||
(*h)[host] = prefix
|
||||
@@ -1128,7 +1128,7 @@ func (to TagOwners) Contains(tagOwner *Tag) error {
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf(`Tag %q is not defined in the Policy, please define or remove the reference to it`, tagOwner)
|
||||
return fmt.Errorf(`tag %q is not defined in the policy, please define or remove the reference to it`, tagOwner)
|
||||
}
|
||||
|
||||
type AutoApproverPolicy struct {
|
||||
@@ -1750,7 +1750,7 @@ func (p *Policy) validate() error {
|
||||
case *Host:
|
||||
h := src
|
||||
if !p.Hosts.exist(*h) {
|
||||
errs = append(errs, fmt.Errorf(`Host %q is not defined in the Policy, please define or remove the reference to it`, *h))
|
||||
errs = append(errs, fmt.Errorf(`host %q is not defined in the policy, please define or remove the reference to it`, *h))
|
||||
}
|
||||
case *AutoGroup:
|
||||
ag := src
|
||||
@@ -1782,7 +1782,7 @@ func (p *Policy) validate() error {
|
||||
case *Host:
|
||||
h := dst.Alias.(*Host)
|
||||
if !p.Hosts.exist(*h) {
|
||||
errs = append(errs, fmt.Errorf(`Host %q is not defined in the Policy, please define or remove the reference to it`, *h))
|
||||
errs = append(errs, fmt.Errorf(`host %q is not defined in the policy, please define or remove the reference to it`, *h))
|
||||
}
|
||||
case *AutoGroup:
|
||||
ag := dst.Alias.(*AutoGroup)
|
||||
|
||||
@@ -380,7 +380,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
wantErr: `Username has to contain @, got: "invalid"`,
|
||||
wantErr: `username must contain @, got: "invalid"`,
|
||||
},
|
||||
{
|
||||
name: "invalid-group",
|
||||
@@ -393,7 +393,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
wantErr: `Group has to start with "group:", got: "grou:example"`,
|
||||
wantErr: `group must start with "group:", got: "grou:example"`,
|
||||
},
|
||||
{
|
||||
name: "group-in-group",
|
||||
@@ -407,8 +407,8 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
// wantErr: `Username has to contain @, got: "group:inner"`,
|
||||
wantErr: `Nested groups are not allowed, found "group:inner" inside "group:example"`,
|
||||
// wantErr: `username must contain @, got: "group:inner"`,
|
||||
wantErr: `nested groups are not allowed, found "group:inner" inside "group:example"`,
|
||||
},
|
||||
{
|
||||
name: "invalid-addr",
|
||||
@@ -419,7 +419,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
wantErr: `Hostname "derp" contains an invalid IP address: "10.0"`,
|
||||
wantErr: `hostname "derp" contains an invalid IP address: "10.0"`,
|
||||
},
|
||||
{
|
||||
name: "invalid-prefix",
|
||||
@@ -430,7 +430,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
wantErr: `Hostname "derp" contains an invalid IP address: "10.0/42"`,
|
||||
wantErr: `hostname "derp" contains an invalid IP address: "10.0/42"`,
|
||||
},
|
||||
// TODO(kradalby): Figure out why this doesn't work.
|
||||
// {
|
||||
@@ -459,7 +459,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
],
|
||||
}
|
||||
`,
|
||||
wantErr: `AutoGroup is invalid, got: "autogroup:invalid", must be one of [autogroup:internet autogroup:member autogroup:nonroot autogroup:tagged autogroup:self]`,
|
||||
wantErr: `autogroup is invalid, got: "autogroup:invalid", must be one of [autogroup:internet autogroup:member autogroup:nonroot autogroup:tagged autogroup:self]`,
|
||||
},
|
||||
{
|
||||
name: "undefined-hostname-errors-2490",
|
||||
@@ -478,7 +478,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
]
|
||||
}
|
||||
`,
|
||||
wantErr: `Host "user1" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `host "user1" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "defined-hostname-does-not-err-2490",
|
||||
@@ -854,7 +854,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
]
|
||||
}
|
||||
`,
|
||||
wantErr: `Tag "tag:notdefined" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `tag "tag:notdefined" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "tag-must-be-defined-acl-dst",
|
||||
@@ -873,7 +873,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
]
|
||||
}
|
||||
`,
|
||||
wantErr: `Tag "tag:notdefined" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `tag "tag:notdefined" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "tag-must-be-defined-acl-ssh-src",
|
||||
@@ -892,7 +892,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
]
|
||||
}
|
||||
`,
|
||||
wantErr: `Tag "tag:notdefined" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `tag "tag:notdefined" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "tag-must-be-defined-acl-ssh-dst",
|
||||
@@ -914,7 +914,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
]
|
||||
}
|
||||
`,
|
||||
wantErr: `Tag "tag:notdefined" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `tag "tag:notdefined" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "tag-must-be-defined-acl-autoapprover-route",
|
||||
@@ -927,7 +927,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
wantErr: `Tag "tag:notdefined" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `tag "tag:notdefined" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "tag-must-be-defined-acl-autoapprover-exitnode",
|
||||
@@ -938,7 +938,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
`,
|
||||
wantErr: `Tag "tag:notdefined" is not defined in the Policy, please define or remove the reference to it`,
|
||||
wantErr: `tag "tag:notdefined" is not defined in the policy, please define or remove the reference to it`,
|
||||
},
|
||||
{
|
||||
name: "missing-dst-port-is-err",
|
||||
@@ -1010,7 +1010,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
wantErr: `Group has to start with "group:", got: "INVALID_GROUP_FIELD"`,
|
||||
wantErr: `group must start with "group:", got: "INVALID_GROUP_FIELD"`,
|
||||
},
|
||||
{
|
||||
name: "invalid-group-datatype",
|
||||
@@ -1022,7 +1022,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
wantErr: `Group "group:invalid" value must be an array of users, got string: "should fail"`,
|
||||
wantErr: `group "group:invalid" value must be an array of users, got string: "should fail"`,
|
||||
},
|
||||
{
|
||||
name: "invalid-group-name-and-datatype-fails-on-name-first",
|
||||
@@ -1034,7 +1034,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
wantErr: `Group has to start with "group:", got: "INVALID_GROUP_FIELD"`,
|
||||
wantErr: `group must start with "group:", got: "INVALID_GROUP_FIELD"`,
|
||||
},
|
||||
{
|
||||
name: "disallow-unsupported-fields-hosts-level",
|
||||
@@ -1046,7 +1046,7 @@ func TestUnmarshalPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
wantErr: `Hostname "INVALID_HOST_FIELD" contains an invalid IP address: "should fail"`,
|
||||
wantErr: `hostname "INVALID_HOST_FIELD" contains an invalid IP address: "should fail"`,
|
||||
},
|
||||
{
|
||||
name: "disallow-unsupported-fields-tagowners-level",
|
||||
@@ -2045,7 +2045,7 @@ func TestResolvePolicy(t *testing.T) {
|
||||
"testhost": p("100.100.101.102/32"),
|
||||
},
|
||||
},
|
||||
wantErr: `unable to resolve host: "invalidhost"`,
|
||||
wantErr: `resolving host: "invalidhost"`,
|
||||
},
|
||||
{
|
||||
name: "multiple-groups",
|
||||
@@ -2909,7 +2909,7 @@ func TestNodeCanHaveTag(t *testing.T) {
|
||||
node: nodes[0],
|
||||
tag: "tag:test",
|
||||
want: false,
|
||||
wantErr: "Username has to contain @",
|
||||
wantErr: "username must contain @",
|
||||
},
|
||||
{
|
||||
name: "node-cannot-have-tag",
|
||||
|
||||
@@ -119,12 +119,12 @@ func NewState(cfg *types.Config) (*State, error) {
|
||||
registrationCache,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init database: %w", err)
|
||||
return nil, fmt.Errorf("initializing database: %w", err)
|
||||
}
|
||||
|
||||
ipAlloc, err := hsdb.NewIPAllocator(db, cfg.PrefixV4, cfg.PrefixV6, cfg.IPAllocation)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init ip allocatior: %w", err)
|
||||
return nil, fmt.Errorf("initializing IP allocator: %w", err)
|
||||
}
|
||||
|
||||
nodes, err := db.ListNodes()
|
||||
@@ -150,7 +150,7 @@ func NewState(cfg *types.Config) (*State, error) {
|
||||
|
||||
polMan, err := policy.NewPolicyManager(pol, users, nodes.ViewSlice())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init policy manager: %w", err)
|
||||
return nil, fmt.Errorf("initializing policy manager: %w", err)
|
||||
}
|
||||
|
||||
// Apply defaults for NodeStore batch configuration if not set.
|
||||
@@ -268,7 +268,7 @@ func (s *State) CreateUser(user types.User) (*types.User, change.Change, error)
|
||||
c, err := s.updatePolicyManagerUsers()
|
||||
if err != nil {
|
||||
// Log the error but don't fail the user creation
|
||||
return &user, change.Change{}, fmt.Errorf("failed to update policy manager after user creation: %w", err)
|
||||
return &user, change.Change{}, fmt.Errorf("updating policy manager after user creation: %w", err)
|
||||
}
|
||||
|
||||
// Even if the policy manager doesn't detect a filter change, SSH policies
|
||||
@@ -313,7 +313,7 @@ func (s *State) UpdateUser(userID types.UserID, updateFn func(*types.User) error
|
||||
// Check if policy manager needs updating
|
||||
c, err := s.updatePolicyManagerUsers()
|
||||
if err != nil {
|
||||
return user, change.Change{}, fmt.Errorf("failed to update policy manager after user update: %w", err)
|
||||
return user, change.Change{}, fmt.Errorf("updating policy manager after user update: %w", err)
|
||||
}
|
||||
|
||||
// TODO(kradalby): We might want to update nodestore with the user data
|
||||
@@ -422,7 +422,7 @@ func (s *State) persistNodeToDB(node types.NodeView) (types.NodeView, change.Cha
|
||||
// Check if policy manager needs updating
|
||||
c, err := s.updatePolicyManagerNodes()
|
||||
if err != nil {
|
||||
return nodePtr.View(), change.Change{}, fmt.Errorf("failed to update policy manager after node save: %w", err)
|
||||
return nodePtr.View(), change.Change{}, fmt.Errorf("updating policy manager after node save: %w", err)
|
||||
}
|
||||
|
||||
if c.IsEmpty() {
|
||||
@@ -459,7 +459,7 @@ func (s *State) DeleteNode(node types.NodeView) (change.Change, error) {
|
||||
// Check if policy manager needs updating after node deletion
|
||||
policyChange, err := s.updatePolicyManagerNodes()
|
||||
if err != nil {
|
||||
return change.Change{}, fmt.Errorf("failed to update policy manager after node deletion: %w", err)
|
||||
return change.Change{}, fmt.Errorf("updating policy manager after node deletion: %w", err)
|
||||
}
|
||||
|
||||
if !policyChange.IsEmpty() {
|
||||
@@ -797,7 +797,7 @@ func (s *State) BackfillNodeIPs() ([]string, error) {
|
||||
if len(changes) > 0 {
|
||||
nodes, err := s.db.ListNodes()
|
||||
if err != nil {
|
||||
return changes, fmt.Errorf("failed to refresh NodeStore after IP backfill: %w", err)
|
||||
return changes, fmt.Errorf("refreshing NodeStore after IP backfill: %w", err)
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
@@ -1242,7 +1242,7 @@ func (s *State) applyAuthNodeUpdate(params authNodeUpdateParams) (types.NodeView
|
||||
_, err := hsdb.Write(s.db.DB, func(tx *gorm.DB) (*types.Node, error) {
|
||||
err := tx.Omit("AuthKeyID", "AuthKey").Updates(updatedNodeView.AsStruct()).Error
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save node: %w", err)
|
||||
return nil, fmt.Errorf("saving node: %w", err)
|
||||
}
|
||||
|
||||
return nil, nil //nolint:nilnil // side-effect only write
|
||||
@@ -1373,7 +1373,7 @@ func (s *State) createAndSaveNewNode(params newNodeParams) (types.NodeView, erro
|
||||
if nodeToRegister.GivenName == "" {
|
||||
givenName, err := hsdb.EnsureUniqueGivenName(s.db.DB, nodeToRegister.Hostname)
|
||||
if err != nil {
|
||||
return types.NodeView{}, fmt.Errorf("failed to ensure unique given name: %w", err)
|
||||
return types.NodeView{}, fmt.Errorf("ensuring unique given name: %w", err)
|
||||
}
|
||||
|
||||
nodeToRegister.GivenName = givenName
|
||||
@@ -1383,7 +1383,7 @@ func (s *State) createAndSaveNewNode(params newNodeParams) (types.NodeView, erro
|
||||
savedNode, err := hsdb.Write(s.db.DB, func(tx *gorm.DB) (*types.Node, error) {
|
||||
err := tx.Save(&nodeToRegister).Error
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save node: %w", err)
|
||||
return nil, fmt.Errorf("saving node: %w", err)
|
||||
}
|
||||
|
||||
if params.PreAuthKey != nil && !params.PreAuthKey.Reusable {
|
||||
@@ -1527,7 +1527,7 @@ func (s *State) HandleNodeFromAuthPath(
|
||||
// Get the user
|
||||
user, err := s.db.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return types.NodeView{}, change.Change{}, fmt.Errorf("failed to find user: %w", err)
|
||||
return types.NodeView{}, change.Change{}, fmt.Errorf("finding user: %w", err)
|
||||
}
|
||||
|
||||
// Ensure we have a valid hostname from the registration cache entry
|
||||
@@ -1632,12 +1632,12 @@ func (s *State) HandleNodeFromAuthPath(
|
||||
// Update policy managers
|
||||
usersChange, err := s.updatePolicyManagerUsers()
|
||||
if err != nil {
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("failed to update policy manager users: %w", err)
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("updating policy manager users: %w", err)
|
||||
}
|
||||
|
||||
nodesChange, err := s.updatePolicyManagerNodes()
|
||||
if err != nil {
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("failed to update policy manager nodes: %w", err)
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("updating policy manager nodes: %w", err)
|
||||
}
|
||||
|
||||
var c change.Change
|
||||
@@ -1840,7 +1840,7 @@ func (s *State) HandleNodeFromPreAuthKey(
|
||||
// Omit AuthKeyID/AuthKey to prevent stale PreAuthKey references from causing FK errors.
|
||||
err := tx.Omit("AuthKeyID", "AuthKey").Updates(updatedNodeView.AsStruct()).Error
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save node: %w", err)
|
||||
return nil, fmt.Errorf("saving node: %w", err)
|
||||
}
|
||||
|
||||
if !pak.Reusable {
|
||||
@@ -1922,12 +1922,12 @@ func (s *State) HandleNodeFromPreAuthKey(
|
||||
// Update policy managers
|
||||
usersChange, err := s.updatePolicyManagerUsers()
|
||||
if err != nil {
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("failed to update policy manager users: %w", err)
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("updating policy manager users: %w", err)
|
||||
}
|
||||
|
||||
nodesChange, err := s.updatePolicyManagerNodes()
|
||||
if err != nil {
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("failed to update policy manager nodes: %w", err)
|
||||
return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("updating policy manager nodes: %w", err)
|
||||
}
|
||||
|
||||
var c change.Change
|
||||
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNodeAddressesInvalid = errors.New("failed to parse node addresses")
|
||||
ErrHostnameTooLong = errors.New("hostname too long, cannot except 255 ASCII chars")
|
||||
ErrNodeAddressesInvalid = errors.New("parsing node addresses")
|
||||
ErrHostnameTooLong = errors.New("hostname too long, cannot accept more than 255 ASCII chars")
|
||||
ErrNodeHasNoGivenName = errors.New("node has no given name")
|
||||
ErrNodeUserHasNoName = errors.New("node user has no name")
|
||||
ErrCannotRemoveAllTags = errors.New("cannot remove all tags from node")
|
||||
@@ -417,7 +417,7 @@ func (node *Node) Proto() *v1.Node {
|
||||
|
||||
func (node *Node) GetFQDN(baseDomain string) (string, error) {
|
||||
if node.GivenName == "" {
|
||||
return "", fmt.Errorf("failed to create valid FQDN: %w", ErrNodeHasNoGivenName)
|
||||
return "", fmt.Errorf("creating valid FQDN: %w", ErrNodeHasNoGivenName)
|
||||
}
|
||||
|
||||
hostname := node.GivenName
|
||||
@@ -432,7 +432,7 @@ func (node *Node) GetFQDN(baseDomain string) (string, error) {
|
||||
|
||||
if len(hostname) > MaxHostnameLength {
|
||||
return "", fmt.Errorf(
|
||||
"failed to create valid FQDN (%s): %w",
|
||||
"creating valid FQDN (%s): %w",
|
||||
hostname,
|
||||
ErrHostnameTooLong,
|
||||
)
|
||||
@@ -897,7 +897,7 @@ func (nv NodeView) PeerChangeFromMapRequest(req tailcfg.MapRequest) tailcfg.Peer
|
||||
// GetFQDN returns the fully qualified domain name for the node.
|
||||
func (nv NodeView) GetFQDN(baseDomain string) (string, error) {
|
||||
if !nv.Valid() {
|
||||
return "", errors.New("failed to create valid FQDN: node view is invalid")
|
||||
return "", errors.New("creating valid FQDN: node view is invalid")
|
||||
}
|
||||
|
||||
return nv.ж.GetFQDN(baseDomain)
|
||||
|
||||
@@ -165,7 +165,7 @@ func TestNodeFQDN(t *testing.T) {
|
||||
},
|
||||
},
|
||||
domain: "example.com",
|
||||
wantErr: "failed to create valid FQDN: node has no given name",
|
||||
wantErr: "creating valid FQDN: node has no given name",
|
||||
},
|
||||
{
|
||||
name: "too-long-username",
|
||||
@@ -173,7 +173,7 @@ func TestNodeFQDN(t *testing.T) {
|
||||
GivenName: strings.Repeat("a", 256),
|
||||
},
|
||||
domain: "example.com",
|
||||
wantErr: fmt.Sprintf("failed to create valid FQDN (%s.example.com.): hostname too long, cannot except 255 ASCII chars", strings.Repeat("a", 256)),
|
||||
wantErr: fmt.Sprintf("creating valid FQDN (%s.example.com.): hostname too long, cannot accept more than 255 ASCII chars", strings.Repeat("a", 256)),
|
||||
},
|
||||
{
|
||||
name: "no-dnsconfig",
|
||||
|
||||
@@ -231,7 +231,7 @@ func (bit *FlexibleBoolean) UnmarshalJSON(data []byte) error {
|
||||
var val any
|
||||
err := json.Unmarshal(data, &val)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not unmarshal data: %w", err)
|
||||
return fmt.Errorf("unmarshalling data: %w", err)
|
||||
}
|
||||
|
||||
switch v := val.(type) {
|
||||
@@ -240,12 +240,12 @@ func (bit *FlexibleBoolean) UnmarshalJSON(data []byte) error {
|
||||
case string:
|
||||
pv, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as boolean: %w", v, err)
|
||||
return fmt.Errorf("parsing %s as boolean: %w", v, err)
|
||||
}
|
||||
*bit = FlexibleBoolean(pv)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("could not parse %v as boolean", v)
|
||||
return fmt.Errorf("parsing %v as boolean", v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,6 +5,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCannotDecryptResponse = errors.New("cannot decrypt response")
|
||||
ErrCannotDecryptResponse = errors.New("decrypting response")
|
||||
ZstdCompression = "zstd"
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ func ParseLoginURLFromCLILogin(output string) (*url.URL, error) {
|
||||
|
||||
loginURL, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
||||
return nil, fmt.Errorf("parsing URL: %w", err)
|
||||
}
|
||||
|
||||
return loginURL, nil
|
||||
|
||||
Reference in New Issue
Block a user