diff --git a/ent/client.go b/ent/client.go index 8a93c0c..7ad2890 100644 --- a/ent/client.go +++ b/ent/client.go @@ -18,6 +18,8 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "github.com/shinobistack/gokakashi/ent/integrations" "github.com/shinobistack/gokakashi/ent/integrationtype" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" ) // Client is the client that holds all ent builders. @@ -29,6 +31,10 @@ type Client struct { IntegrationType *IntegrationTypeClient // Integrations is the client for interacting with the Integrations builders. Integrations *IntegrationsClient + // Policies is the client for interacting with the Policies builders. + Policies *PoliciesClient + // PolicyLabels is the client for interacting with the PolicyLabels builders. + PolicyLabels *PolicyLabelsClient } // NewClient creates a new client configured with the given options. @@ -42,6 +48,8 @@ func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) c.IntegrationType = NewIntegrationTypeClient(c.config) c.Integrations = NewIntegrationsClient(c.config) + c.Policies = NewPoliciesClient(c.config) + c.PolicyLabels = NewPolicyLabelsClient(c.config) } type ( @@ -136,6 +144,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { config: cfg, IntegrationType: NewIntegrationTypeClient(cfg), Integrations: NewIntegrationsClient(cfg), + Policies: NewPoliciesClient(cfg), + PolicyLabels: NewPolicyLabelsClient(cfg), }, nil } @@ -157,6 +167,8 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) config: cfg, IntegrationType: NewIntegrationTypeClient(cfg), Integrations: NewIntegrationsClient(cfg), + Policies: NewPoliciesClient(cfg), + PolicyLabels: NewPolicyLabelsClient(cfg), }, nil } @@ -187,6 +199,8 @@ func (c *Client) Close() error { func (c *Client) Use(hooks ...Hook) { c.IntegrationType.Use(hooks...) c.Integrations.Use(hooks...) + c.Policies.Use(hooks...) + c.PolicyLabels.Use(hooks...) } // Intercept adds the query interceptors to all the entity clients. @@ -194,6 +208,8 @@ func (c *Client) Use(hooks ...Hook) { func (c *Client) Intercept(interceptors ...Interceptor) { c.IntegrationType.Intercept(interceptors...) c.Integrations.Intercept(interceptors...) + c.Policies.Intercept(interceptors...) + c.PolicyLabels.Intercept(interceptors...) } // Mutate implements the ent.Mutator interface. @@ -203,6 +219,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.IntegrationType.mutate(ctx, m) case *IntegrationsMutation: return c.Integrations.mutate(ctx, m) + case *PoliciesMutation: + return c.Policies.mutate(ctx, m) + case *PolicyLabelsMutation: + return c.PolicyLabels.mutate(ctx, m) default: return nil, fmt.Errorf("ent: unknown mutation type %T", m) } @@ -490,12 +510,310 @@ func (c *IntegrationsClient) mutate(ctx context.Context, m *IntegrationsMutation } } +// PoliciesClient is a client for the Policies schema. +type PoliciesClient struct { + config +} + +// NewPoliciesClient returns a client for the Policies from the given config. +func NewPoliciesClient(c config) *PoliciesClient { + return &PoliciesClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `policies.Hooks(f(g(h())))`. +func (c *PoliciesClient) Use(hooks ...Hook) { + c.hooks.Policies = append(c.hooks.Policies, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `policies.Intercept(f(g(h())))`. +func (c *PoliciesClient) Intercept(interceptors ...Interceptor) { + c.inters.Policies = append(c.inters.Policies, interceptors...) +} + +// Create returns a builder for creating a Policies entity. +func (c *PoliciesClient) Create() *PoliciesCreate { + mutation := newPoliciesMutation(c.config, OpCreate) + return &PoliciesCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Policies entities. +func (c *PoliciesClient) CreateBulk(builders ...*PoliciesCreate) *PoliciesCreateBulk { + return &PoliciesCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *PoliciesClient) MapCreateBulk(slice any, setFunc func(*PoliciesCreate, int)) *PoliciesCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &PoliciesCreateBulk{err: fmt.Errorf("calling to PoliciesClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*PoliciesCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &PoliciesCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Policies. +func (c *PoliciesClient) Update() *PoliciesUpdate { + mutation := newPoliciesMutation(c.config, OpUpdate) + return &PoliciesUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *PoliciesClient) UpdateOne(po *Policies) *PoliciesUpdateOne { + mutation := newPoliciesMutation(c.config, OpUpdateOne, withPolicies(po)) + return &PoliciesUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *PoliciesClient) UpdateOneID(id uuid.UUID) *PoliciesUpdateOne { + mutation := newPoliciesMutation(c.config, OpUpdateOne, withPoliciesID(id)) + return &PoliciesUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Policies. +func (c *PoliciesClient) Delete() *PoliciesDelete { + mutation := newPoliciesMutation(c.config, OpDelete) + return &PoliciesDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *PoliciesClient) DeleteOne(po *Policies) *PoliciesDeleteOne { + return c.DeleteOneID(po.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *PoliciesClient) DeleteOneID(id uuid.UUID) *PoliciesDeleteOne { + builder := c.Delete().Where(policies.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &PoliciesDeleteOne{builder} +} + +// Query returns a query builder for Policies. +func (c *PoliciesClient) Query() *PoliciesQuery { + return &PoliciesQuery{ + config: c.config, + ctx: &QueryContext{Type: TypePolicies}, + inters: c.Interceptors(), + } +} + +// Get returns a Policies entity by its id. +func (c *PoliciesClient) Get(ctx context.Context, id uuid.UUID) (*Policies, error) { + return c.Query().Where(policies.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *PoliciesClient) GetX(ctx context.Context, id uuid.UUID) *Policies { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryPolicyLabels queries the policy_labels edge of a Policies. +func (c *PoliciesClient) QueryPolicyLabels(po *Policies) *PolicyLabelsQuery { + query := (&PolicyLabelsClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := po.ID + step := sqlgraph.NewStep( + sqlgraph.From(policies.Table, policies.FieldID, id), + sqlgraph.To(policylabels.Table, policylabels.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, policies.PolicyLabelsTable, policies.PolicyLabelsColumn), + ) + fromV = sqlgraph.Neighbors(po.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *PoliciesClient) Hooks() []Hook { + return c.hooks.Policies +} + +// Interceptors returns the client interceptors. +func (c *PoliciesClient) Interceptors() []Interceptor { + return c.inters.Policies +} + +func (c *PoliciesClient) mutate(ctx context.Context, m *PoliciesMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&PoliciesCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&PoliciesUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&PoliciesUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&PoliciesDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Policies mutation op: %q", m.Op()) + } +} + +// PolicyLabelsClient is a client for the PolicyLabels schema. +type PolicyLabelsClient struct { + config +} + +// NewPolicyLabelsClient returns a client for the PolicyLabels from the given config. +func NewPolicyLabelsClient(c config) *PolicyLabelsClient { + return &PolicyLabelsClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `policylabels.Hooks(f(g(h())))`. +func (c *PolicyLabelsClient) Use(hooks ...Hook) { + c.hooks.PolicyLabels = append(c.hooks.PolicyLabels, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `policylabels.Intercept(f(g(h())))`. +func (c *PolicyLabelsClient) Intercept(interceptors ...Interceptor) { + c.inters.PolicyLabels = append(c.inters.PolicyLabels, interceptors...) +} + +// Create returns a builder for creating a PolicyLabels entity. +func (c *PolicyLabelsClient) Create() *PolicyLabelsCreate { + mutation := newPolicyLabelsMutation(c.config, OpCreate) + return &PolicyLabelsCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of PolicyLabels entities. +func (c *PolicyLabelsClient) CreateBulk(builders ...*PolicyLabelsCreate) *PolicyLabelsCreateBulk { + return &PolicyLabelsCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *PolicyLabelsClient) MapCreateBulk(slice any, setFunc func(*PolicyLabelsCreate, int)) *PolicyLabelsCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &PolicyLabelsCreateBulk{err: fmt.Errorf("calling to PolicyLabelsClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*PolicyLabelsCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &PolicyLabelsCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for PolicyLabels. +func (c *PolicyLabelsClient) Update() *PolicyLabelsUpdate { + mutation := newPolicyLabelsMutation(c.config, OpUpdate) + return &PolicyLabelsUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *PolicyLabelsClient) UpdateOne(pl *PolicyLabels) *PolicyLabelsUpdateOne { + mutation := newPolicyLabelsMutation(c.config, OpUpdateOne, withPolicyLabels(pl)) + return &PolicyLabelsUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *PolicyLabelsClient) UpdateOneID(id int) *PolicyLabelsUpdateOne { + mutation := newPolicyLabelsMutation(c.config, OpUpdateOne, withPolicyLabelsID(id)) + return &PolicyLabelsUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for PolicyLabels. +func (c *PolicyLabelsClient) Delete() *PolicyLabelsDelete { + mutation := newPolicyLabelsMutation(c.config, OpDelete) + return &PolicyLabelsDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *PolicyLabelsClient) DeleteOne(pl *PolicyLabels) *PolicyLabelsDeleteOne { + return c.DeleteOneID(pl.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *PolicyLabelsClient) DeleteOneID(id int) *PolicyLabelsDeleteOne { + builder := c.Delete().Where(policylabels.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &PolicyLabelsDeleteOne{builder} +} + +// Query returns a query builder for PolicyLabels. +func (c *PolicyLabelsClient) Query() *PolicyLabelsQuery { + return &PolicyLabelsQuery{ + config: c.config, + ctx: &QueryContext{Type: TypePolicyLabels}, + inters: c.Interceptors(), + } +} + +// Get returns a PolicyLabels entity by its id. +func (c *PolicyLabelsClient) Get(ctx context.Context, id int) (*PolicyLabels, error) { + return c.Query().Where(policylabels.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *PolicyLabelsClient) GetX(ctx context.Context, id int) *PolicyLabels { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryPolicy queries the policy edge of a PolicyLabels. +func (c *PolicyLabelsClient) QueryPolicy(pl *PolicyLabels) *PoliciesQuery { + query := (&PoliciesClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := pl.ID + step := sqlgraph.NewStep( + sqlgraph.From(policylabels.Table, policylabels.FieldID, id), + sqlgraph.To(policies.Table, policies.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, policylabels.PolicyTable, policylabels.PolicyColumn), + ) + fromV = sqlgraph.Neighbors(pl.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *PolicyLabelsClient) Hooks() []Hook { + return c.hooks.PolicyLabels +} + +// Interceptors returns the client interceptors. +func (c *PolicyLabelsClient) Interceptors() []Interceptor { + return c.inters.PolicyLabels +} + +func (c *PolicyLabelsClient) mutate(ctx context.Context, m *PolicyLabelsMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&PolicyLabelsCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&PolicyLabelsUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&PolicyLabelsUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&PolicyLabelsDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown PolicyLabels mutation op: %q", m.Op()) + } +} + // hooks and interceptors per client, for fast access. type ( hooks struct { - IntegrationType, Integrations []ent.Hook + IntegrationType, Integrations, Policies, PolicyLabels []ent.Hook } inters struct { - IntegrationType, Integrations []ent.Interceptor + IntegrationType, Integrations, Policies, PolicyLabels []ent.Interceptor } ) diff --git a/ent/ent.go b/ent/ent.go index 6c14803..7d4689c 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -14,6 +14,8 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "github.com/shinobistack/gokakashi/ent/integrations" "github.com/shinobistack/gokakashi/ent/integrationtype" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" ) // ent aliases to avoid import conflicts in user's code. @@ -76,6 +78,8 @@ func checkColumn(table, column string) error { columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ integrationtype.Table: integrationtype.ValidColumn, integrations.Table: integrations.ValidColumn, + policies.Table: policies.ValidColumn, + policylabels.Table: policylabels.ValidColumn, }) }) return columnCheck(table, column) diff --git a/ent/hook/hook.go b/ent/hook/hook.go index 5ee321b..9c70373 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -33,6 +33,30 @@ func (f IntegrationsFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IntegrationsMutation", m) } +// The PoliciesFunc type is an adapter to allow the use of ordinary +// function as Policies mutator. +type PoliciesFunc func(context.Context, *ent.PoliciesMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f PoliciesFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.PoliciesMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PoliciesMutation", m) +} + +// The PolicyLabelsFunc type is an adapter to allow the use of ordinary +// function as PolicyLabels mutator. +type PolicyLabelsFunc func(context.Context, *ent.PolicyLabelsMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f PolicyLabelsFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.PolicyLabelsMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PolicyLabelsMutation", m) +} + // Condition is a hook condition function. type Condition func(context.Context, ent.Mutation) bool diff --git a/ent/integrationtype.go b/ent/integrationtype.go index 402e66d..9a18bec 100644 --- a/ent/integrationtype.go +++ b/ent/integrationtype.go @@ -16,7 +16,7 @@ type IntegrationType struct { config `json:"-"` // ID of the ent. ID string `json:"id,omitempty"` - // Types of Integration e.g., linear,jira + // Human-readable name for the integration type DisplayName string `json:"display_name,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the IntegrationTypeQuery when eager-loading is set. diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 05c4e8e..a2cda70 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -41,13 +41,52 @@ var ( }, }, } + // PoliciesColumns holds the columns for the "policies" table. + PoliciesColumns = []*schema.Column{ + {Name: "id", Type: field.TypeUUID, Unique: true}, + {Name: "name", Type: field.TypeString, Unique: true}, + {Name: "image", Type: field.TypeJSON}, + {Name: "labels", Type: field.TypeJSON, Nullable: true}, + {Name: "trigger", Type: field.TypeJSON, Nullable: true}, + {Name: "check", Type: field.TypeJSON, Nullable: true}, + } + // PoliciesTable holds the schema information for the "policies" table. + PoliciesTable = &schema.Table{ + Name: "policies", + Columns: PoliciesColumns, + PrimaryKey: []*schema.Column{PoliciesColumns[0]}, + } + // PolicyLabelsColumns holds the columns for the "policy_labels" table. + PolicyLabelsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "key", Type: field.TypeString}, + {Name: "value", Type: field.TypeString}, + {Name: "policy_id", Type: field.TypeUUID}, + } + // PolicyLabelsTable holds the schema information for the "policy_labels" table. + PolicyLabelsTable = &schema.Table{ + Name: "policy_labels", + Columns: PolicyLabelsColumns, + PrimaryKey: []*schema.Column{PolicyLabelsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "policy_labels_policies_policy_labels", + Columns: []*schema.Column{PolicyLabelsColumns[3]}, + RefColumns: []*schema.Column{PoliciesColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + } // Tables holds all the tables in the schema. Tables = []*schema.Table{ IntegrationTypesTable, IntegrationsTable, + PoliciesTable, + PolicyLabelsTable, } ) func init() { IntegrationsTable.ForeignKeys[0].RefTable = IntegrationTypesTable + PolicyLabelsTable.ForeignKeys[0].RefTable = PoliciesTable } diff --git a/ent/mutation.go b/ent/mutation.go index c785505..c67af8d 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -13,7 +13,10 @@ import ( "github.com/google/uuid" "github.com/shinobistack/gokakashi/ent/integrations" "github.com/shinobistack/gokakashi/ent/integrationtype" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" "github.com/shinobistack/gokakashi/ent/predicate" + "github.com/shinobistack/gokakashi/ent/schema" ) const ( @@ -27,6 +30,8 @@ const ( // Node types. TypeIntegrationType = "IntegrationType" TypeIntegrations = "Integrations" + TypePolicies = "Policies" + TypePolicyLabels = "PolicyLabels" ) // IntegrationTypeMutation represents an operation that mutates the IntegrationType nodes in the graph. @@ -893,3 +898,1192 @@ func (m *IntegrationsMutation) ClearEdge(name string) error { func (m *IntegrationsMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Integrations edge %s", name) } + +// PoliciesMutation represents an operation that mutates the Policies nodes in the graph. +type PoliciesMutation struct { + config + op Op + typ string + id *uuid.UUID + name *string + image *schema.Image + labels *schema.PolicyLabels + trigger *map[string]interface{} + check *schema.Check + clearedFields map[string]struct{} + policy_labels map[int]struct{} + removedpolicy_labels map[int]struct{} + clearedpolicy_labels bool + done bool + oldValue func(context.Context) (*Policies, error) + predicates []predicate.Policies +} + +var _ ent.Mutation = (*PoliciesMutation)(nil) + +// policiesOption allows management of the mutation configuration using functional options. +type policiesOption func(*PoliciesMutation) + +// newPoliciesMutation creates new mutation for the Policies entity. +func newPoliciesMutation(c config, op Op, opts ...policiesOption) *PoliciesMutation { + m := &PoliciesMutation{ + config: c, + op: op, + typ: TypePolicies, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withPoliciesID sets the ID field of the mutation. +func withPoliciesID(id uuid.UUID) policiesOption { + return func(m *PoliciesMutation) { + var ( + err error + once sync.Once + value *Policies + ) + m.oldValue = func(ctx context.Context) (*Policies, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Policies.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withPolicies sets the old Policies of the mutation. +func withPolicies(node *Policies) policiesOption { + return func(m *PoliciesMutation) { + m.oldValue = func(context.Context) (*Policies, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m PoliciesMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m PoliciesMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Policies entities. +func (m *PoliciesMutation) SetID(id uuid.UUID) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *PoliciesMutation) ID() (id uuid.UUID, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *PoliciesMutation) IDs(ctx context.Context) ([]uuid.UUID, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []uuid.UUID{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Policies.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetName sets the "name" field. +func (m *PoliciesMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *PoliciesMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the Policies entity. +// If the Policies object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PoliciesMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *PoliciesMutation) ResetName() { + m.name = nil +} + +// SetImage sets the "image" field. +func (m *PoliciesMutation) SetImage(s schema.Image) { + m.image = &s +} + +// Image returns the value of the "image" field in the mutation. +func (m *PoliciesMutation) Image() (r schema.Image, exists bool) { + v := m.image + if v == nil { + return + } + return *v, true +} + +// OldImage returns the old "image" field's value of the Policies entity. +// If the Policies object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PoliciesMutation) OldImage(ctx context.Context) (v schema.Image, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldImage is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldImage requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldImage: %w", err) + } + return oldValue.Image, nil +} + +// ResetImage resets all changes to the "image" field. +func (m *PoliciesMutation) ResetImage() { + m.image = nil +} + +// SetLabels sets the "labels" field. +func (m *PoliciesMutation) SetLabels(sl schema.PolicyLabels) { + m.labels = &sl +} + +// Labels returns the value of the "labels" field in the mutation. +func (m *PoliciesMutation) Labels() (r schema.PolicyLabels, exists bool) { + v := m.labels + if v == nil { + return + } + return *v, true +} + +// OldLabels returns the old "labels" field's value of the Policies entity. +// If the Policies object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PoliciesMutation) OldLabels(ctx context.Context) (v schema.PolicyLabels, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLabels is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLabels requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLabels: %w", err) + } + return oldValue.Labels, nil +} + +// ClearLabels clears the value of the "labels" field. +func (m *PoliciesMutation) ClearLabels() { + m.labels = nil + m.clearedFields[policies.FieldLabels] = struct{}{} +} + +// LabelsCleared returns if the "labels" field was cleared in this mutation. +func (m *PoliciesMutation) LabelsCleared() bool { + _, ok := m.clearedFields[policies.FieldLabels] + return ok +} + +// ResetLabels resets all changes to the "labels" field. +func (m *PoliciesMutation) ResetLabels() { + m.labels = nil + delete(m.clearedFields, policies.FieldLabels) +} + +// SetTrigger sets the "trigger" field. +func (m *PoliciesMutation) SetTrigger(value map[string]interface{}) { + m.trigger = &value +} + +// Trigger returns the value of the "trigger" field in the mutation. +func (m *PoliciesMutation) Trigger() (r map[string]interface{}, exists bool) { + v := m.trigger + if v == nil { + return + } + return *v, true +} + +// OldTrigger returns the old "trigger" field's value of the Policies entity. +// If the Policies object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PoliciesMutation) OldTrigger(ctx context.Context) (v map[string]interface{}, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTrigger is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTrigger requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTrigger: %w", err) + } + return oldValue.Trigger, nil +} + +// ClearTrigger clears the value of the "trigger" field. +func (m *PoliciesMutation) ClearTrigger() { + m.trigger = nil + m.clearedFields[policies.FieldTrigger] = struct{}{} +} + +// TriggerCleared returns if the "trigger" field was cleared in this mutation. +func (m *PoliciesMutation) TriggerCleared() bool { + _, ok := m.clearedFields[policies.FieldTrigger] + return ok +} + +// ResetTrigger resets all changes to the "trigger" field. +func (m *PoliciesMutation) ResetTrigger() { + m.trigger = nil + delete(m.clearedFields, policies.FieldTrigger) +} + +// SetCheck sets the "check" field. +func (m *PoliciesMutation) SetCheck(s schema.Check) { + m.check = &s +} + +// Check returns the value of the "check" field in the mutation. +func (m *PoliciesMutation) Check() (r schema.Check, exists bool) { + v := m.check + if v == nil { + return + } + return *v, true +} + +// OldCheck returns the old "check" field's value of the Policies entity. +// If the Policies object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PoliciesMutation) OldCheck(ctx context.Context) (v schema.Check, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCheck is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCheck requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCheck: %w", err) + } + return oldValue.Check, nil +} + +// ClearCheck clears the value of the "check" field. +func (m *PoliciesMutation) ClearCheck() { + m.check = nil + m.clearedFields[policies.FieldCheck] = struct{}{} +} + +// CheckCleared returns if the "check" field was cleared in this mutation. +func (m *PoliciesMutation) CheckCleared() bool { + _, ok := m.clearedFields[policies.FieldCheck] + return ok +} + +// ResetCheck resets all changes to the "check" field. +func (m *PoliciesMutation) ResetCheck() { + m.check = nil + delete(m.clearedFields, policies.FieldCheck) +} + +// AddPolicyLabelIDs adds the "policy_labels" edge to the PolicyLabels entity by ids. +func (m *PoliciesMutation) AddPolicyLabelIDs(ids ...int) { + if m.policy_labels == nil { + m.policy_labels = make(map[int]struct{}) + } + for i := range ids { + m.policy_labels[ids[i]] = struct{}{} + } +} + +// ClearPolicyLabels clears the "policy_labels" edge to the PolicyLabels entity. +func (m *PoliciesMutation) ClearPolicyLabels() { + m.clearedpolicy_labels = true +} + +// PolicyLabelsCleared reports if the "policy_labels" edge to the PolicyLabels entity was cleared. +func (m *PoliciesMutation) PolicyLabelsCleared() bool { + return m.clearedpolicy_labels +} + +// RemovePolicyLabelIDs removes the "policy_labels" edge to the PolicyLabels entity by IDs. +func (m *PoliciesMutation) RemovePolicyLabelIDs(ids ...int) { + if m.removedpolicy_labels == nil { + m.removedpolicy_labels = make(map[int]struct{}) + } + for i := range ids { + delete(m.policy_labels, ids[i]) + m.removedpolicy_labels[ids[i]] = struct{}{} + } +} + +// RemovedPolicyLabels returns the removed IDs of the "policy_labels" edge to the PolicyLabels entity. +func (m *PoliciesMutation) RemovedPolicyLabelsIDs() (ids []int) { + for id := range m.removedpolicy_labels { + ids = append(ids, id) + } + return +} + +// PolicyLabelsIDs returns the "policy_labels" edge IDs in the mutation. +func (m *PoliciesMutation) PolicyLabelsIDs() (ids []int) { + for id := range m.policy_labels { + ids = append(ids, id) + } + return +} + +// ResetPolicyLabels resets all changes to the "policy_labels" edge. +func (m *PoliciesMutation) ResetPolicyLabels() { + m.policy_labels = nil + m.clearedpolicy_labels = false + m.removedpolicy_labels = nil +} + +// Where appends a list predicates to the PoliciesMutation builder. +func (m *PoliciesMutation) Where(ps ...predicate.Policies) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the PoliciesMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *PoliciesMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Policies, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *PoliciesMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *PoliciesMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Policies). +func (m *PoliciesMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *PoliciesMutation) Fields() []string { + fields := make([]string, 0, 5) + if m.name != nil { + fields = append(fields, policies.FieldName) + } + if m.image != nil { + fields = append(fields, policies.FieldImage) + } + if m.labels != nil { + fields = append(fields, policies.FieldLabels) + } + if m.trigger != nil { + fields = append(fields, policies.FieldTrigger) + } + if m.check != nil { + fields = append(fields, policies.FieldCheck) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *PoliciesMutation) Field(name string) (ent.Value, bool) { + switch name { + case policies.FieldName: + return m.Name() + case policies.FieldImage: + return m.Image() + case policies.FieldLabels: + return m.Labels() + case policies.FieldTrigger: + return m.Trigger() + case policies.FieldCheck: + return m.Check() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *PoliciesMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case policies.FieldName: + return m.OldName(ctx) + case policies.FieldImage: + return m.OldImage(ctx) + case policies.FieldLabels: + return m.OldLabels(ctx) + case policies.FieldTrigger: + return m.OldTrigger(ctx) + case policies.FieldCheck: + return m.OldCheck(ctx) + } + return nil, fmt.Errorf("unknown Policies field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *PoliciesMutation) SetField(name string, value ent.Value) error { + switch name { + case policies.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case policies.FieldImage: + v, ok := value.(schema.Image) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetImage(v) + return nil + case policies.FieldLabels: + v, ok := value.(schema.PolicyLabels) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLabels(v) + return nil + case policies.FieldTrigger: + v, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTrigger(v) + return nil + case policies.FieldCheck: + v, ok := value.(schema.Check) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCheck(v) + return nil + } + return fmt.Errorf("unknown Policies field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *PoliciesMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *PoliciesMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *PoliciesMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown Policies numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *PoliciesMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(policies.FieldLabels) { + fields = append(fields, policies.FieldLabels) + } + if m.FieldCleared(policies.FieldTrigger) { + fields = append(fields, policies.FieldTrigger) + } + if m.FieldCleared(policies.FieldCheck) { + fields = append(fields, policies.FieldCheck) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *PoliciesMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *PoliciesMutation) ClearField(name string) error { + switch name { + case policies.FieldLabels: + m.ClearLabels() + return nil + case policies.FieldTrigger: + m.ClearTrigger() + return nil + case policies.FieldCheck: + m.ClearCheck() + return nil + } + return fmt.Errorf("unknown Policies nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *PoliciesMutation) ResetField(name string) error { + switch name { + case policies.FieldName: + m.ResetName() + return nil + case policies.FieldImage: + m.ResetImage() + return nil + case policies.FieldLabels: + m.ResetLabels() + return nil + case policies.FieldTrigger: + m.ResetTrigger() + return nil + case policies.FieldCheck: + m.ResetCheck() + return nil + } + return fmt.Errorf("unknown Policies field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *PoliciesMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.policy_labels != nil { + edges = append(edges, policies.EdgePolicyLabels) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *PoliciesMutation) AddedIDs(name string) []ent.Value { + switch name { + case policies.EdgePolicyLabels: + ids := make([]ent.Value, 0, len(m.policy_labels)) + for id := range m.policy_labels { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *PoliciesMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + if m.removedpolicy_labels != nil { + edges = append(edges, policies.EdgePolicyLabels) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *PoliciesMutation) RemovedIDs(name string) []ent.Value { + switch name { + case policies.EdgePolicyLabels: + ids := make([]ent.Value, 0, len(m.removedpolicy_labels)) + for id := range m.removedpolicy_labels { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *PoliciesMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedpolicy_labels { + edges = append(edges, policies.EdgePolicyLabels) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *PoliciesMutation) EdgeCleared(name string) bool { + switch name { + case policies.EdgePolicyLabels: + return m.clearedpolicy_labels + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *PoliciesMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown Policies unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *PoliciesMutation) ResetEdge(name string) error { + switch name { + case policies.EdgePolicyLabels: + m.ResetPolicyLabels() + return nil + } + return fmt.Errorf("unknown Policies edge %s", name) +} + +// PolicyLabelsMutation represents an operation that mutates the PolicyLabels nodes in the graph. +type PolicyLabelsMutation struct { + config + op Op + typ string + id *int + key *string + value *string + clearedFields map[string]struct{} + policy *uuid.UUID + clearedpolicy bool + done bool + oldValue func(context.Context) (*PolicyLabels, error) + predicates []predicate.PolicyLabels +} + +var _ ent.Mutation = (*PolicyLabelsMutation)(nil) + +// policylabelsOption allows management of the mutation configuration using functional options. +type policylabelsOption func(*PolicyLabelsMutation) + +// newPolicyLabelsMutation creates new mutation for the PolicyLabels entity. +func newPolicyLabelsMutation(c config, op Op, opts ...policylabelsOption) *PolicyLabelsMutation { + m := &PolicyLabelsMutation{ + config: c, + op: op, + typ: TypePolicyLabels, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withPolicyLabelsID sets the ID field of the mutation. +func withPolicyLabelsID(id int) policylabelsOption { + return func(m *PolicyLabelsMutation) { + var ( + err error + once sync.Once + value *PolicyLabels + ) + m.oldValue = func(ctx context.Context) (*PolicyLabels, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().PolicyLabels.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withPolicyLabels sets the old PolicyLabels of the mutation. +func withPolicyLabels(node *PolicyLabels) policylabelsOption { + return func(m *PolicyLabelsMutation) { + m.oldValue = func(context.Context) (*PolicyLabels, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m PolicyLabelsMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m PolicyLabelsMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *PolicyLabelsMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *PolicyLabelsMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().PolicyLabels.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetPolicyID sets the "policy_id" field. +func (m *PolicyLabelsMutation) SetPolicyID(u uuid.UUID) { + m.policy = &u +} + +// PolicyID returns the value of the "policy_id" field in the mutation. +func (m *PolicyLabelsMutation) PolicyID() (r uuid.UUID, exists bool) { + v := m.policy + if v == nil { + return + } + return *v, true +} + +// OldPolicyID returns the old "policy_id" field's value of the PolicyLabels entity. +// If the PolicyLabels object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PolicyLabelsMutation) OldPolicyID(ctx context.Context) (v uuid.UUID, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPolicyID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPolicyID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPolicyID: %w", err) + } + return oldValue.PolicyID, nil +} + +// ResetPolicyID resets all changes to the "policy_id" field. +func (m *PolicyLabelsMutation) ResetPolicyID() { + m.policy = nil +} + +// SetKey sets the "key" field. +func (m *PolicyLabelsMutation) SetKey(s string) { + m.key = &s +} + +// Key returns the value of the "key" field in the mutation. +func (m *PolicyLabelsMutation) Key() (r string, exists bool) { + v := m.key + if v == nil { + return + } + return *v, true +} + +// OldKey returns the old "key" field's value of the PolicyLabels entity. +// If the PolicyLabels object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PolicyLabelsMutation) OldKey(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldKey is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldKey requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldKey: %w", err) + } + return oldValue.Key, nil +} + +// ResetKey resets all changes to the "key" field. +func (m *PolicyLabelsMutation) ResetKey() { + m.key = nil +} + +// SetValue sets the "value" field. +func (m *PolicyLabelsMutation) SetValue(s string) { + m.value = &s +} + +// Value returns the value of the "value" field in the mutation. +func (m *PolicyLabelsMutation) Value() (r string, exists bool) { + v := m.value + if v == nil { + return + } + return *v, true +} + +// OldValue returns the old "value" field's value of the PolicyLabels entity. +// If the PolicyLabels object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PolicyLabelsMutation) OldValue(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldValue is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldValue requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldValue: %w", err) + } + return oldValue.Value, nil +} + +// ResetValue resets all changes to the "value" field. +func (m *PolicyLabelsMutation) ResetValue() { + m.value = nil +} + +// ClearPolicy clears the "policy" edge to the Policies entity. +func (m *PolicyLabelsMutation) ClearPolicy() { + m.clearedpolicy = true + m.clearedFields[policylabels.FieldPolicyID] = struct{}{} +} + +// PolicyCleared reports if the "policy" edge to the Policies entity was cleared. +func (m *PolicyLabelsMutation) PolicyCleared() bool { + return m.clearedpolicy +} + +// PolicyIDs returns the "policy" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// PolicyID instead. It exists only for internal usage by the builders. +func (m *PolicyLabelsMutation) PolicyIDs() (ids []uuid.UUID) { + if id := m.policy; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetPolicy resets all changes to the "policy" edge. +func (m *PolicyLabelsMutation) ResetPolicy() { + m.policy = nil + m.clearedpolicy = false +} + +// Where appends a list predicates to the PolicyLabelsMutation builder. +func (m *PolicyLabelsMutation) Where(ps ...predicate.PolicyLabels) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the PolicyLabelsMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *PolicyLabelsMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.PolicyLabels, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *PolicyLabelsMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *PolicyLabelsMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (PolicyLabels). +func (m *PolicyLabelsMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *PolicyLabelsMutation) Fields() []string { + fields := make([]string, 0, 3) + if m.policy != nil { + fields = append(fields, policylabels.FieldPolicyID) + } + if m.key != nil { + fields = append(fields, policylabels.FieldKey) + } + if m.value != nil { + fields = append(fields, policylabels.FieldValue) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *PolicyLabelsMutation) Field(name string) (ent.Value, bool) { + switch name { + case policylabels.FieldPolicyID: + return m.PolicyID() + case policylabels.FieldKey: + return m.Key() + case policylabels.FieldValue: + return m.Value() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *PolicyLabelsMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case policylabels.FieldPolicyID: + return m.OldPolicyID(ctx) + case policylabels.FieldKey: + return m.OldKey(ctx) + case policylabels.FieldValue: + return m.OldValue(ctx) + } + return nil, fmt.Errorf("unknown PolicyLabels field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *PolicyLabelsMutation) SetField(name string, value ent.Value) error { + switch name { + case policylabels.FieldPolicyID: + v, ok := value.(uuid.UUID) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPolicyID(v) + return nil + case policylabels.FieldKey: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetKey(v) + return nil + case policylabels.FieldValue: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetValue(v) + return nil + } + return fmt.Errorf("unknown PolicyLabels field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *PolicyLabelsMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *PolicyLabelsMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *PolicyLabelsMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown PolicyLabels numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *PolicyLabelsMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *PolicyLabelsMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *PolicyLabelsMutation) ClearField(name string) error { + return fmt.Errorf("unknown PolicyLabels nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *PolicyLabelsMutation) ResetField(name string) error { + switch name { + case policylabels.FieldPolicyID: + m.ResetPolicyID() + return nil + case policylabels.FieldKey: + m.ResetKey() + return nil + case policylabels.FieldValue: + m.ResetValue() + return nil + } + return fmt.Errorf("unknown PolicyLabels field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *PolicyLabelsMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.policy != nil { + edges = append(edges, policylabels.EdgePolicy) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *PolicyLabelsMutation) AddedIDs(name string) []ent.Value { + switch name { + case policylabels.EdgePolicy: + if id := m.policy; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *PolicyLabelsMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *PolicyLabelsMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *PolicyLabelsMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedpolicy { + edges = append(edges, policylabels.EdgePolicy) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *PolicyLabelsMutation) EdgeCleared(name string) bool { + switch name { + case policylabels.EdgePolicy: + return m.clearedpolicy + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *PolicyLabelsMutation) ClearEdge(name string) error { + switch name { + case policylabels.EdgePolicy: + m.ClearPolicy() + return nil + } + return fmt.Errorf("unknown PolicyLabels unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *PolicyLabelsMutation) ResetEdge(name string) error { + switch name { + case policylabels.EdgePolicy: + m.ResetPolicy() + return nil + } + return fmt.Errorf("unknown PolicyLabels edge %s", name) +} diff --git a/ent/policies.go b/ent/policies.go new file mode 100644 index 0000000..36978bf --- /dev/null +++ b/ent/policies.go @@ -0,0 +1,187 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "encoding/json" + "fmt" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/schema" +) + +// Policies is the model entity for the Policies schema. +type Policies struct { + config `json:"-"` + // ID of the ent. + // Primary key, unique identifier. + ID uuid.UUID `json:"id,omitempty"` + // Policy name. + Name string `json:"name,omitempty"` + // Stores image details like registry, tags. + Image schema.Image `json:"image,omitempty"` + // Policies labels key:value + Labels schema.PolicyLabels `json:"labels,omitempty"` + // Stores trigger details (e.g., cron schedule). + Trigger map[string]interface{} `json:"trigger,omitempty"` + // Stores conditions for evaluation. + Check schema.Check `json:"check,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the PoliciesQuery when eager-loading is set. + Edges PoliciesEdges `json:"edges"` + selectValues sql.SelectValues +} + +// PoliciesEdges holds the relations/edges for other nodes in the graph. +type PoliciesEdges struct { + // PolicyLabels holds the value of the policy_labels edge. + PolicyLabels []*PolicyLabels `json:"policy_labels,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// PolicyLabelsOrErr returns the PolicyLabels value or an error if the edge +// was not loaded in eager-loading. +func (e PoliciesEdges) PolicyLabelsOrErr() ([]*PolicyLabels, error) { + if e.loadedTypes[0] { + return e.PolicyLabels, nil + } + return nil, &NotLoadedError{edge: "policy_labels"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Policies) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case policies.FieldImage, policies.FieldLabels, policies.FieldTrigger, policies.FieldCheck: + values[i] = new([]byte) + case policies.FieldName: + values[i] = new(sql.NullString) + case policies.FieldID: + values[i] = new(uuid.UUID) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Policies fields. +func (po *Policies) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case policies.FieldID: + if value, ok := values[i].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field id", values[i]) + } else if value != nil { + po.ID = *value + } + case policies.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + po.Name = value.String + } + case policies.FieldImage: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field image", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &po.Image); err != nil { + return fmt.Errorf("unmarshal field image: %w", err) + } + } + case policies.FieldLabels: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field labels", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &po.Labels); err != nil { + return fmt.Errorf("unmarshal field labels: %w", err) + } + } + case policies.FieldTrigger: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field trigger", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &po.Trigger); err != nil { + return fmt.Errorf("unmarshal field trigger: %w", err) + } + } + case policies.FieldCheck: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field check", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &po.Check); err != nil { + return fmt.Errorf("unmarshal field check: %w", err) + } + } + default: + po.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Policies. +// This includes values selected through modifiers, order, etc. +func (po *Policies) Value(name string) (ent.Value, error) { + return po.selectValues.Get(name) +} + +// QueryPolicyLabels queries the "policy_labels" edge of the Policies entity. +func (po *Policies) QueryPolicyLabels() *PolicyLabelsQuery { + return NewPoliciesClient(po.config).QueryPolicyLabels(po) +} + +// Update returns a builder for updating this Policies. +// Note that you need to call Policies.Unwrap() before calling this method if this Policies +// was returned from a transaction, and the transaction was committed or rolled back. +func (po *Policies) Update() *PoliciesUpdateOne { + return NewPoliciesClient(po.config).UpdateOne(po) +} + +// Unwrap unwraps the Policies entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (po *Policies) Unwrap() *Policies { + _tx, ok := po.config.driver.(*txDriver) + if !ok { + panic("ent: Policies is not a transactional entity") + } + po.config.driver = _tx.drv + return po +} + +// String implements the fmt.Stringer. +func (po *Policies) String() string { + var builder strings.Builder + builder.WriteString("Policies(") + builder.WriteString(fmt.Sprintf("id=%v, ", po.ID)) + builder.WriteString("name=") + builder.WriteString(po.Name) + builder.WriteString(", ") + builder.WriteString("image=") + builder.WriteString(fmt.Sprintf("%v", po.Image)) + builder.WriteString(", ") + builder.WriteString("labels=") + builder.WriteString(fmt.Sprintf("%v", po.Labels)) + builder.WriteString(", ") + builder.WriteString("trigger=") + builder.WriteString(fmt.Sprintf("%v", po.Trigger)) + builder.WriteString(", ") + builder.WriteString("check=") + builder.WriteString(fmt.Sprintf("%v", po.Check)) + builder.WriteByte(')') + return builder.String() +} + +// PoliciesSlice is a parsable slice of Policies. +type PoliciesSlice []*Policies diff --git a/ent/policies/policies.go b/ent/policies/policies.go new file mode 100644 index 0000000..92d31b5 --- /dev/null +++ b/ent/policies/policies.go @@ -0,0 +1,98 @@ +// Code generated by ent, DO NOT EDIT. + +package policies + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/google/uuid" +) + +const ( + // Label holds the string label denoting the policies type in the database. + Label = "policies" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldImage holds the string denoting the image field in the database. + FieldImage = "image" + // FieldLabels holds the string denoting the labels field in the database. + FieldLabels = "labels" + // FieldTrigger holds the string denoting the trigger field in the database. + FieldTrigger = "trigger" + // FieldCheck holds the string denoting the check field in the database. + FieldCheck = "check" + // EdgePolicyLabels holds the string denoting the policy_labels edge name in mutations. + EdgePolicyLabels = "policy_labels" + // Table holds the table name of the policies in the database. + Table = "policies" + // PolicyLabelsTable is the table that holds the policy_labels relation/edge. + PolicyLabelsTable = "policy_labels" + // PolicyLabelsInverseTable is the table name for the PolicyLabels entity. + // It exists in this package in order to avoid circular dependency with the "policylabels" package. + PolicyLabelsInverseTable = "policy_labels" + // PolicyLabelsColumn is the table column denoting the policy_labels relation/edge. + PolicyLabelsColumn = "policy_id" +) + +// Columns holds all SQL columns for policies fields. +var Columns = []string{ + FieldID, + FieldName, + FieldImage, + FieldLabels, + FieldTrigger, + FieldCheck, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // DefaultID holds the default value on creation for the "id" field. + DefaultID func() uuid.UUID +) + +// OrderOption defines the ordering options for the Policies queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByPolicyLabelsCount orders the results by policy_labels count. +func ByPolicyLabelsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newPolicyLabelsStep(), opts...) + } +} + +// ByPolicyLabels orders the results by policy_labels terms. +func ByPolicyLabels(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newPolicyLabelsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} +func newPolicyLabelsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(PolicyLabelsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, PolicyLabelsTable, PolicyLabelsColumn), + ) +} diff --git a/ent/policies/where.go b/ent/policies/where.go new file mode 100644 index 0000000..8ff6617 --- /dev/null +++ b/ent/policies/where.go @@ -0,0 +1,193 @@ +// Code generated by ent, DO NOT EDIT. + +package policies + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id uuid.UUID) predicate.Policies { + return predicate.Policies(sql.FieldLTE(FieldID, id)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.Policies { + return predicate.Policies(sql.FieldEQ(FieldName, v)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.Policies { + return predicate.Policies(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.Policies { + return predicate.Policies(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.Policies { + return predicate.Policies(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.Policies { + return predicate.Policies(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.Policies { + return predicate.Policies(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.Policies { + return predicate.Policies(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.Policies { + return predicate.Policies(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.Policies { + return predicate.Policies(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.Policies { + return predicate.Policies(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.Policies { + return predicate.Policies(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.Policies { + return predicate.Policies(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.Policies { + return predicate.Policies(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.Policies { + return predicate.Policies(sql.FieldContainsFold(FieldName, v)) +} + +// LabelsIsNil applies the IsNil predicate on the "labels" field. +func LabelsIsNil() predicate.Policies { + return predicate.Policies(sql.FieldIsNull(FieldLabels)) +} + +// LabelsNotNil applies the NotNil predicate on the "labels" field. +func LabelsNotNil() predicate.Policies { + return predicate.Policies(sql.FieldNotNull(FieldLabels)) +} + +// TriggerIsNil applies the IsNil predicate on the "trigger" field. +func TriggerIsNil() predicate.Policies { + return predicate.Policies(sql.FieldIsNull(FieldTrigger)) +} + +// TriggerNotNil applies the NotNil predicate on the "trigger" field. +func TriggerNotNil() predicate.Policies { + return predicate.Policies(sql.FieldNotNull(FieldTrigger)) +} + +// CheckIsNil applies the IsNil predicate on the "check" field. +func CheckIsNil() predicate.Policies { + return predicate.Policies(sql.FieldIsNull(FieldCheck)) +} + +// CheckNotNil applies the NotNil predicate on the "check" field. +func CheckNotNil() predicate.Policies { + return predicate.Policies(sql.FieldNotNull(FieldCheck)) +} + +// HasPolicyLabels applies the HasEdge predicate on the "policy_labels" edge. +func HasPolicyLabels() predicate.Policies { + return predicate.Policies(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, PolicyLabelsTable, PolicyLabelsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasPolicyLabelsWith applies the HasEdge predicate on the "policy_labels" edge with a given conditions (other predicates). +func HasPolicyLabelsWith(preds ...predicate.PolicyLabels) predicate.Policies { + return predicate.Policies(func(s *sql.Selector) { + step := newPolicyLabelsStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Policies) predicate.Policies { + return predicate.Policies(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Policies) predicate.Policies { + return predicate.Policies(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Policies) predicate.Policies { + return predicate.Policies(sql.NotPredicates(p)) +} diff --git a/ent/policies_create.go b/ent/policies_create.go new file mode 100644 index 0000000..ffcb004 --- /dev/null +++ b/ent/policies_create.go @@ -0,0 +1,310 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/shinobistack/gokakashi/ent/schema" +) + +// PoliciesCreate is the builder for creating a Policies entity. +type PoliciesCreate struct { + config + mutation *PoliciesMutation + hooks []Hook +} + +// SetName sets the "name" field. +func (pc *PoliciesCreate) SetName(s string) *PoliciesCreate { + pc.mutation.SetName(s) + return pc +} + +// SetImage sets the "image" field. +func (pc *PoliciesCreate) SetImage(s schema.Image) *PoliciesCreate { + pc.mutation.SetImage(s) + return pc +} + +// SetLabels sets the "labels" field. +func (pc *PoliciesCreate) SetLabels(sl schema.PolicyLabels) *PoliciesCreate { + pc.mutation.SetLabels(sl) + return pc +} + +// SetNillableLabels sets the "labels" field if the given value is not nil. +func (pc *PoliciesCreate) SetNillableLabels(sl *schema.PolicyLabels) *PoliciesCreate { + if sl != nil { + pc.SetLabels(*sl) + } + return pc +} + +// SetTrigger sets the "trigger" field. +func (pc *PoliciesCreate) SetTrigger(m map[string]interface{}) *PoliciesCreate { + pc.mutation.SetTrigger(m) + return pc +} + +// SetCheck sets the "check" field. +func (pc *PoliciesCreate) SetCheck(s schema.Check) *PoliciesCreate { + pc.mutation.SetCheck(s) + return pc +} + +// SetNillableCheck sets the "check" field if the given value is not nil. +func (pc *PoliciesCreate) SetNillableCheck(s *schema.Check) *PoliciesCreate { + if s != nil { + pc.SetCheck(*s) + } + return pc +} + +// SetID sets the "id" field. +func (pc *PoliciesCreate) SetID(u uuid.UUID) *PoliciesCreate { + pc.mutation.SetID(u) + return pc +} + +// SetNillableID sets the "id" field if the given value is not nil. +func (pc *PoliciesCreate) SetNillableID(u *uuid.UUID) *PoliciesCreate { + if u != nil { + pc.SetID(*u) + } + return pc +} + +// AddPolicyLabelIDs adds the "policy_labels" edge to the PolicyLabels entity by IDs. +func (pc *PoliciesCreate) AddPolicyLabelIDs(ids ...int) *PoliciesCreate { + pc.mutation.AddPolicyLabelIDs(ids...) + return pc +} + +// AddPolicyLabels adds the "policy_labels" edges to the PolicyLabels entity. +func (pc *PoliciesCreate) AddPolicyLabels(p ...*PolicyLabels) *PoliciesCreate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return pc.AddPolicyLabelIDs(ids...) +} + +// Mutation returns the PoliciesMutation object of the builder. +func (pc *PoliciesCreate) Mutation() *PoliciesMutation { + return pc.mutation +} + +// Save creates the Policies in the database. +func (pc *PoliciesCreate) Save(ctx context.Context) (*Policies, error) { + pc.defaults() + return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (pc *PoliciesCreate) SaveX(ctx context.Context) *Policies { + v, err := pc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pc *PoliciesCreate) Exec(ctx context.Context) error { + _, err := pc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pc *PoliciesCreate) ExecX(ctx context.Context) { + if err := pc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (pc *PoliciesCreate) defaults() { + if _, ok := pc.mutation.ID(); !ok { + v := policies.DefaultID() + pc.mutation.SetID(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (pc *PoliciesCreate) check() error { + if _, ok := pc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Policies.name"`)} + } + if v, ok := pc.mutation.Name(); ok { + if err := policies.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Policies.name": %w`, err)} + } + } + if _, ok := pc.mutation.Image(); !ok { + return &ValidationError{Name: "image", err: errors.New(`ent: missing required field "Policies.image"`)} + } + return nil +} + +func (pc *PoliciesCreate) sqlSave(ctx context.Context) (*Policies, error) { + if err := pc.check(); err != nil { + return nil, err + } + _node, _spec := pc.createSpec() + if err := sqlgraph.CreateNode(ctx, pc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != nil { + if id, ok := _spec.ID.Value.(*uuid.UUID); ok { + _node.ID = *id + } else if err := _node.ID.Scan(_spec.ID.Value); err != nil { + return nil, err + } + } + pc.mutation.id = &_node.ID + pc.mutation.done = true + return _node, nil +} + +func (pc *PoliciesCreate) createSpec() (*Policies, *sqlgraph.CreateSpec) { + var ( + _node = &Policies{config: pc.config} + _spec = sqlgraph.NewCreateSpec(policies.Table, sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID)) + ) + if id, ok := pc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = &id + } + if value, ok := pc.mutation.Name(); ok { + _spec.SetField(policies.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := pc.mutation.Image(); ok { + _spec.SetField(policies.FieldImage, field.TypeJSON, value) + _node.Image = value + } + if value, ok := pc.mutation.Labels(); ok { + _spec.SetField(policies.FieldLabels, field.TypeJSON, value) + _node.Labels = value + } + if value, ok := pc.mutation.Trigger(); ok { + _spec.SetField(policies.FieldTrigger, field.TypeJSON, value) + _node.Trigger = value + } + if value, ok := pc.mutation.Check(); ok { + _spec.SetField(policies.FieldCheck, field.TypeJSON, value) + _node.Check = value + } + if nodes := pc.mutation.PolicyLabelsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// PoliciesCreateBulk is the builder for creating many Policies entities in bulk. +type PoliciesCreateBulk struct { + config + err error + builders []*PoliciesCreate +} + +// Save creates the Policies entities in the database. +func (pcb *PoliciesCreateBulk) Save(ctx context.Context) ([]*Policies, error) { + if pcb.err != nil { + return nil, pcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(pcb.builders)) + nodes := make([]*Policies, len(pcb.builders)) + mutators := make([]Mutator, len(pcb.builders)) + for i := range pcb.builders { + func(i int, root context.Context) { + builder := pcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*PoliciesMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, pcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, pcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, pcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (pcb *PoliciesCreateBulk) SaveX(ctx context.Context) []*Policies { + v, err := pcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pcb *PoliciesCreateBulk) Exec(ctx context.Context) error { + _, err := pcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pcb *PoliciesCreateBulk) ExecX(ctx context.Context) { + if err := pcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/policies_delete.go b/ent/policies_delete.go new file mode 100644 index 0000000..9ad7821 --- /dev/null +++ b/ent/policies_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// PoliciesDelete is the builder for deleting a Policies entity. +type PoliciesDelete struct { + config + hooks []Hook + mutation *PoliciesMutation +} + +// Where appends a list predicates to the PoliciesDelete builder. +func (pd *PoliciesDelete) Where(ps ...predicate.Policies) *PoliciesDelete { + pd.mutation.Where(ps...) + return pd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (pd *PoliciesDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, pd.sqlExec, pd.mutation, pd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (pd *PoliciesDelete) ExecX(ctx context.Context) int { + n, err := pd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (pd *PoliciesDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(policies.Table, sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID)) + if ps := pd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, pd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + pd.mutation.done = true + return affected, err +} + +// PoliciesDeleteOne is the builder for deleting a single Policies entity. +type PoliciesDeleteOne struct { + pd *PoliciesDelete +} + +// Where appends a list predicates to the PoliciesDelete builder. +func (pdo *PoliciesDeleteOne) Where(ps ...predicate.Policies) *PoliciesDeleteOne { + pdo.pd.mutation.Where(ps...) + return pdo +} + +// Exec executes the deletion query. +func (pdo *PoliciesDeleteOne) Exec(ctx context.Context) error { + n, err := pdo.pd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{policies.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (pdo *PoliciesDeleteOne) ExecX(ctx context.Context) { + if err := pdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/policies_query.go b/ent/policies_query.go new file mode 100644 index 0000000..057121b --- /dev/null +++ b/ent/policies_query.go @@ -0,0 +1,607 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// PoliciesQuery is the builder for querying Policies entities. +type PoliciesQuery struct { + config + ctx *QueryContext + order []policies.OrderOption + inters []Interceptor + predicates []predicate.Policies + withPolicyLabels *PolicyLabelsQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the PoliciesQuery builder. +func (pq *PoliciesQuery) Where(ps ...predicate.Policies) *PoliciesQuery { + pq.predicates = append(pq.predicates, ps...) + return pq +} + +// Limit the number of records to be returned by this query. +func (pq *PoliciesQuery) Limit(limit int) *PoliciesQuery { + pq.ctx.Limit = &limit + return pq +} + +// Offset to start from. +func (pq *PoliciesQuery) Offset(offset int) *PoliciesQuery { + pq.ctx.Offset = &offset + return pq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (pq *PoliciesQuery) Unique(unique bool) *PoliciesQuery { + pq.ctx.Unique = &unique + return pq +} + +// Order specifies how the records should be ordered. +func (pq *PoliciesQuery) Order(o ...policies.OrderOption) *PoliciesQuery { + pq.order = append(pq.order, o...) + return pq +} + +// QueryPolicyLabels chains the current query on the "policy_labels" edge. +func (pq *PoliciesQuery) QueryPolicyLabels() *PolicyLabelsQuery { + query := (&PolicyLabelsClient{config: pq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := pq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(policies.Table, policies.FieldID, selector), + sqlgraph.To(policylabels.Table, policylabels.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, policies.PolicyLabelsTable, policies.PolicyLabelsColumn), + ) + fromU = sqlgraph.SetNeighbors(pq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Policies entity from the query. +// Returns a *NotFoundError when no Policies was found. +func (pq *PoliciesQuery) First(ctx context.Context) (*Policies, error) { + nodes, err := pq.Limit(1).All(setContextOp(ctx, pq.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{policies.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (pq *PoliciesQuery) FirstX(ctx context.Context) *Policies { + node, err := pq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Policies ID from the query. +// Returns a *NotFoundError when no Policies ID was found. +func (pq *PoliciesQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) { + var ids []uuid.UUID + if ids, err = pq.Limit(1).IDs(setContextOp(ctx, pq.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{policies.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (pq *PoliciesQuery) FirstIDX(ctx context.Context) uuid.UUID { + id, err := pq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Policies entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Policies entity is found. +// Returns a *NotFoundError when no Policies entities are found. +func (pq *PoliciesQuery) Only(ctx context.Context) (*Policies, error) { + nodes, err := pq.Limit(2).All(setContextOp(ctx, pq.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{policies.Label} + default: + return nil, &NotSingularError{policies.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (pq *PoliciesQuery) OnlyX(ctx context.Context) *Policies { + node, err := pq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Policies ID in the query. +// Returns a *NotSingularError when more than one Policies ID is found. +// Returns a *NotFoundError when no entities are found. +func (pq *PoliciesQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) { + var ids []uuid.UUID + if ids, err = pq.Limit(2).IDs(setContextOp(ctx, pq.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{policies.Label} + default: + err = &NotSingularError{policies.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (pq *PoliciesQuery) OnlyIDX(ctx context.Context) uuid.UUID { + id, err := pq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of PoliciesSlice. +func (pq *PoliciesQuery) All(ctx context.Context) ([]*Policies, error) { + ctx = setContextOp(ctx, pq.ctx, ent.OpQueryAll) + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Policies, *PoliciesQuery]() + return withInterceptors[[]*Policies](ctx, pq, qr, pq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (pq *PoliciesQuery) AllX(ctx context.Context) []*Policies { + nodes, err := pq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Policies IDs. +func (pq *PoliciesQuery) IDs(ctx context.Context) (ids []uuid.UUID, err error) { + if pq.ctx.Unique == nil && pq.path != nil { + pq.Unique(true) + } + ctx = setContextOp(ctx, pq.ctx, ent.OpQueryIDs) + if err = pq.Select(policies.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (pq *PoliciesQuery) IDsX(ctx context.Context) []uuid.UUID { + ids, err := pq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (pq *PoliciesQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, pq.ctx, ent.OpQueryCount) + if err := pq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, pq, querierCount[*PoliciesQuery](), pq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (pq *PoliciesQuery) CountX(ctx context.Context) int { + count, err := pq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (pq *PoliciesQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, pq.ctx, ent.OpQueryExist) + switch _, err := pq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (pq *PoliciesQuery) ExistX(ctx context.Context) bool { + exist, err := pq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the PoliciesQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (pq *PoliciesQuery) Clone() *PoliciesQuery { + if pq == nil { + return nil + } + return &PoliciesQuery{ + config: pq.config, + ctx: pq.ctx.Clone(), + order: append([]policies.OrderOption{}, pq.order...), + inters: append([]Interceptor{}, pq.inters...), + predicates: append([]predicate.Policies{}, pq.predicates...), + withPolicyLabels: pq.withPolicyLabels.Clone(), + // clone intermediate query. + sql: pq.sql.Clone(), + path: pq.path, + } +} + +// WithPolicyLabels tells the query-builder to eager-load the nodes that are connected to +// the "policy_labels" edge. The optional arguments are used to configure the query builder of the edge. +func (pq *PoliciesQuery) WithPolicyLabels(opts ...func(*PolicyLabelsQuery)) *PoliciesQuery { + query := (&PolicyLabelsClient{config: pq.config}).Query() + for _, opt := range opts { + opt(query) + } + pq.withPolicyLabels = query + return pq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Policies.Query(). +// GroupBy(policies.FieldName). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (pq *PoliciesQuery) GroupBy(field string, fields ...string) *PoliciesGroupBy { + pq.ctx.Fields = append([]string{field}, fields...) + grbuild := &PoliciesGroupBy{build: pq} + grbuild.flds = &pq.ctx.Fields + grbuild.label = policies.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// } +// +// client.Policies.Query(). +// Select(policies.FieldName). +// Scan(ctx, &v) +func (pq *PoliciesQuery) Select(fields ...string) *PoliciesSelect { + pq.ctx.Fields = append(pq.ctx.Fields, fields...) + sbuild := &PoliciesSelect{PoliciesQuery: pq} + sbuild.label = policies.Label + sbuild.flds, sbuild.scan = &pq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a PoliciesSelect configured with the given aggregations. +func (pq *PoliciesQuery) Aggregate(fns ...AggregateFunc) *PoliciesSelect { + return pq.Select().Aggregate(fns...) +} + +func (pq *PoliciesQuery) prepareQuery(ctx context.Context) error { + for _, inter := range pq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, pq); err != nil { + return err + } + } + } + for _, f := range pq.ctx.Fields { + if !policies.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if pq.path != nil { + prev, err := pq.path(ctx) + if err != nil { + return err + } + pq.sql = prev + } + return nil +} + +func (pq *PoliciesQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Policies, error) { + var ( + nodes = []*Policies{} + _spec = pq.querySpec() + loadedTypes = [1]bool{ + pq.withPolicyLabels != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Policies).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Policies{config: pq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, pq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := pq.withPolicyLabels; query != nil { + if err := pq.loadPolicyLabels(ctx, query, nodes, + func(n *Policies) { n.Edges.PolicyLabels = []*PolicyLabels{} }, + func(n *Policies, e *PolicyLabels) { n.Edges.PolicyLabels = append(n.Edges.PolicyLabels, e) }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (pq *PoliciesQuery) loadPolicyLabels(ctx context.Context, query *PolicyLabelsQuery, nodes []*Policies, init func(*Policies), assign func(*Policies, *PolicyLabels)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[uuid.UUID]*Policies) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(policylabels.FieldPolicyID) + } + query.Where(predicate.PolicyLabels(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(policies.PolicyLabelsColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.PolicyID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "policy_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} + +func (pq *PoliciesQuery) sqlCount(ctx context.Context) (int, error) { + _spec := pq.querySpec() + _spec.Node.Columns = pq.ctx.Fields + if len(pq.ctx.Fields) > 0 { + _spec.Unique = pq.ctx.Unique != nil && *pq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, pq.driver, _spec) +} + +func (pq *PoliciesQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(policies.Table, policies.Columns, sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID)) + _spec.From = pq.sql + if unique := pq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if pq.path != nil { + _spec.Unique = true + } + if fields := pq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, policies.FieldID) + for i := range fields { + if fields[i] != policies.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := pq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := pq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := pq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := pq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (pq *PoliciesQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(pq.driver.Dialect()) + t1 := builder.Table(policies.Table) + columns := pq.ctx.Fields + if len(columns) == 0 { + columns = policies.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if pq.sql != nil { + selector = pq.sql + selector.Select(selector.Columns(columns...)...) + } + if pq.ctx.Unique != nil && *pq.ctx.Unique { + selector.Distinct() + } + for _, p := range pq.predicates { + p(selector) + } + for _, p := range pq.order { + p(selector) + } + if offset := pq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := pq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// PoliciesGroupBy is the group-by builder for Policies entities. +type PoliciesGroupBy struct { + selector + build *PoliciesQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (pgb *PoliciesGroupBy) Aggregate(fns ...AggregateFunc) *PoliciesGroupBy { + pgb.fns = append(pgb.fns, fns...) + return pgb +} + +// Scan applies the selector query and scans the result into the given value. +func (pgb *PoliciesGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, pgb.build.ctx, ent.OpQueryGroupBy) + if err := pgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*PoliciesQuery, *PoliciesGroupBy](ctx, pgb.build, pgb, pgb.build.inters, v) +} + +func (pgb *PoliciesGroupBy) sqlScan(ctx context.Context, root *PoliciesQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(pgb.fns)) + for _, fn := range pgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*pgb.flds)+len(pgb.fns)) + for _, f := range *pgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*pgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := pgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// PoliciesSelect is the builder for selecting fields of Policies entities. +type PoliciesSelect struct { + *PoliciesQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ps *PoliciesSelect) Aggregate(fns ...AggregateFunc) *PoliciesSelect { + ps.fns = append(ps.fns, fns...) + return ps +} + +// Scan applies the selector query and scans the result into the given value. +func (ps *PoliciesSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ps.ctx, ent.OpQuerySelect) + if err := ps.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*PoliciesQuery, *PoliciesSelect](ctx, ps.PoliciesQuery, ps, ps.inters, v) +} + +func (ps *PoliciesSelect) sqlScan(ctx context.Context, root *PoliciesQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ps.fns)) + for _, fn := range ps.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ps.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ps.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/policies_update.go b/ent/policies_update.go new file mode 100644 index 0000000..96e3e26 --- /dev/null +++ b/ent/policies_update.go @@ -0,0 +1,573 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/shinobistack/gokakashi/ent/predicate" + "github.com/shinobistack/gokakashi/ent/schema" +) + +// PoliciesUpdate is the builder for updating Policies entities. +type PoliciesUpdate struct { + config + hooks []Hook + mutation *PoliciesMutation +} + +// Where appends a list predicates to the PoliciesUpdate builder. +func (pu *PoliciesUpdate) Where(ps ...predicate.Policies) *PoliciesUpdate { + pu.mutation.Where(ps...) + return pu +} + +// SetName sets the "name" field. +func (pu *PoliciesUpdate) SetName(s string) *PoliciesUpdate { + pu.mutation.SetName(s) + return pu +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (pu *PoliciesUpdate) SetNillableName(s *string) *PoliciesUpdate { + if s != nil { + pu.SetName(*s) + } + return pu +} + +// SetImage sets the "image" field. +func (pu *PoliciesUpdate) SetImage(s schema.Image) *PoliciesUpdate { + pu.mutation.SetImage(s) + return pu +} + +// SetNillableImage sets the "image" field if the given value is not nil. +func (pu *PoliciesUpdate) SetNillableImage(s *schema.Image) *PoliciesUpdate { + if s != nil { + pu.SetImage(*s) + } + return pu +} + +// SetLabels sets the "labels" field. +func (pu *PoliciesUpdate) SetLabels(sl schema.PolicyLabels) *PoliciesUpdate { + pu.mutation.SetLabels(sl) + return pu +} + +// SetNillableLabels sets the "labels" field if the given value is not nil. +func (pu *PoliciesUpdate) SetNillableLabels(sl *schema.PolicyLabels) *PoliciesUpdate { + if sl != nil { + pu.SetLabels(*sl) + } + return pu +} + +// ClearLabels clears the value of the "labels" field. +func (pu *PoliciesUpdate) ClearLabels() *PoliciesUpdate { + pu.mutation.ClearLabels() + return pu +} + +// SetTrigger sets the "trigger" field. +func (pu *PoliciesUpdate) SetTrigger(m map[string]interface{}) *PoliciesUpdate { + pu.mutation.SetTrigger(m) + return pu +} + +// ClearTrigger clears the value of the "trigger" field. +func (pu *PoliciesUpdate) ClearTrigger() *PoliciesUpdate { + pu.mutation.ClearTrigger() + return pu +} + +// SetCheck sets the "check" field. +func (pu *PoliciesUpdate) SetCheck(s schema.Check) *PoliciesUpdate { + pu.mutation.SetCheck(s) + return pu +} + +// SetNillableCheck sets the "check" field if the given value is not nil. +func (pu *PoliciesUpdate) SetNillableCheck(s *schema.Check) *PoliciesUpdate { + if s != nil { + pu.SetCheck(*s) + } + return pu +} + +// ClearCheck clears the value of the "check" field. +func (pu *PoliciesUpdate) ClearCheck() *PoliciesUpdate { + pu.mutation.ClearCheck() + return pu +} + +// AddPolicyLabelIDs adds the "policy_labels" edge to the PolicyLabels entity by IDs. +func (pu *PoliciesUpdate) AddPolicyLabelIDs(ids ...int) *PoliciesUpdate { + pu.mutation.AddPolicyLabelIDs(ids...) + return pu +} + +// AddPolicyLabels adds the "policy_labels" edges to the PolicyLabels entity. +func (pu *PoliciesUpdate) AddPolicyLabels(p ...*PolicyLabels) *PoliciesUpdate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return pu.AddPolicyLabelIDs(ids...) +} + +// Mutation returns the PoliciesMutation object of the builder. +func (pu *PoliciesUpdate) Mutation() *PoliciesMutation { + return pu.mutation +} + +// ClearPolicyLabels clears all "policy_labels" edges to the PolicyLabels entity. +func (pu *PoliciesUpdate) ClearPolicyLabels() *PoliciesUpdate { + pu.mutation.ClearPolicyLabels() + return pu +} + +// RemovePolicyLabelIDs removes the "policy_labels" edge to PolicyLabels entities by IDs. +func (pu *PoliciesUpdate) RemovePolicyLabelIDs(ids ...int) *PoliciesUpdate { + pu.mutation.RemovePolicyLabelIDs(ids...) + return pu +} + +// RemovePolicyLabels removes "policy_labels" edges to PolicyLabels entities. +func (pu *PoliciesUpdate) RemovePolicyLabels(p ...*PolicyLabels) *PoliciesUpdate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return pu.RemovePolicyLabelIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (pu *PoliciesUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, pu.sqlSave, pu.mutation, pu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (pu *PoliciesUpdate) SaveX(ctx context.Context) int { + affected, err := pu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (pu *PoliciesUpdate) Exec(ctx context.Context) error { + _, err := pu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pu *PoliciesUpdate) ExecX(ctx context.Context) { + if err := pu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (pu *PoliciesUpdate) check() error { + if v, ok := pu.mutation.Name(); ok { + if err := policies.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Policies.name": %w`, err)} + } + } + return nil +} + +func (pu *PoliciesUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := pu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(policies.Table, policies.Columns, sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID)) + if ps := pu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := pu.mutation.Name(); ok { + _spec.SetField(policies.FieldName, field.TypeString, value) + } + if value, ok := pu.mutation.Image(); ok { + _spec.SetField(policies.FieldImage, field.TypeJSON, value) + } + if value, ok := pu.mutation.Labels(); ok { + _spec.SetField(policies.FieldLabels, field.TypeJSON, value) + } + if pu.mutation.LabelsCleared() { + _spec.ClearField(policies.FieldLabels, field.TypeJSON) + } + if value, ok := pu.mutation.Trigger(); ok { + _spec.SetField(policies.FieldTrigger, field.TypeJSON, value) + } + if pu.mutation.TriggerCleared() { + _spec.ClearField(policies.FieldTrigger, field.TypeJSON) + } + if value, ok := pu.mutation.Check(); ok { + _spec.SetField(policies.FieldCheck, field.TypeJSON, value) + } + if pu.mutation.CheckCleared() { + _spec.ClearField(policies.FieldCheck, field.TypeJSON) + } + if pu.mutation.PolicyLabelsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := pu.mutation.RemovedPolicyLabelsIDs(); len(nodes) > 0 && !pu.mutation.PolicyLabelsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := pu.mutation.PolicyLabelsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{policies.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + pu.mutation.done = true + return n, nil +} + +// PoliciesUpdateOne is the builder for updating a single Policies entity. +type PoliciesUpdateOne struct { + config + fields []string + hooks []Hook + mutation *PoliciesMutation +} + +// SetName sets the "name" field. +func (puo *PoliciesUpdateOne) SetName(s string) *PoliciesUpdateOne { + puo.mutation.SetName(s) + return puo +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (puo *PoliciesUpdateOne) SetNillableName(s *string) *PoliciesUpdateOne { + if s != nil { + puo.SetName(*s) + } + return puo +} + +// SetImage sets the "image" field. +func (puo *PoliciesUpdateOne) SetImage(s schema.Image) *PoliciesUpdateOne { + puo.mutation.SetImage(s) + return puo +} + +// SetNillableImage sets the "image" field if the given value is not nil. +func (puo *PoliciesUpdateOne) SetNillableImage(s *schema.Image) *PoliciesUpdateOne { + if s != nil { + puo.SetImage(*s) + } + return puo +} + +// SetLabels sets the "labels" field. +func (puo *PoliciesUpdateOne) SetLabels(sl schema.PolicyLabels) *PoliciesUpdateOne { + puo.mutation.SetLabels(sl) + return puo +} + +// SetNillableLabels sets the "labels" field if the given value is not nil. +func (puo *PoliciesUpdateOne) SetNillableLabels(sl *schema.PolicyLabels) *PoliciesUpdateOne { + if sl != nil { + puo.SetLabels(*sl) + } + return puo +} + +// ClearLabels clears the value of the "labels" field. +func (puo *PoliciesUpdateOne) ClearLabels() *PoliciesUpdateOne { + puo.mutation.ClearLabels() + return puo +} + +// SetTrigger sets the "trigger" field. +func (puo *PoliciesUpdateOne) SetTrigger(m map[string]interface{}) *PoliciesUpdateOne { + puo.mutation.SetTrigger(m) + return puo +} + +// ClearTrigger clears the value of the "trigger" field. +func (puo *PoliciesUpdateOne) ClearTrigger() *PoliciesUpdateOne { + puo.mutation.ClearTrigger() + return puo +} + +// SetCheck sets the "check" field. +func (puo *PoliciesUpdateOne) SetCheck(s schema.Check) *PoliciesUpdateOne { + puo.mutation.SetCheck(s) + return puo +} + +// SetNillableCheck sets the "check" field if the given value is not nil. +func (puo *PoliciesUpdateOne) SetNillableCheck(s *schema.Check) *PoliciesUpdateOne { + if s != nil { + puo.SetCheck(*s) + } + return puo +} + +// ClearCheck clears the value of the "check" field. +func (puo *PoliciesUpdateOne) ClearCheck() *PoliciesUpdateOne { + puo.mutation.ClearCheck() + return puo +} + +// AddPolicyLabelIDs adds the "policy_labels" edge to the PolicyLabels entity by IDs. +func (puo *PoliciesUpdateOne) AddPolicyLabelIDs(ids ...int) *PoliciesUpdateOne { + puo.mutation.AddPolicyLabelIDs(ids...) + return puo +} + +// AddPolicyLabels adds the "policy_labels" edges to the PolicyLabels entity. +func (puo *PoliciesUpdateOne) AddPolicyLabels(p ...*PolicyLabels) *PoliciesUpdateOne { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return puo.AddPolicyLabelIDs(ids...) +} + +// Mutation returns the PoliciesMutation object of the builder. +func (puo *PoliciesUpdateOne) Mutation() *PoliciesMutation { + return puo.mutation +} + +// ClearPolicyLabels clears all "policy_labels" edges to the PolicyLabels entity. +func (puo *PoliciesUpdateOne) ClearPolicyLabels() *PoliciesUpdateOne { + puo.mutation.ClearPolicyLabels() + return puo +} + +// RemovePolicyLabelIDs removes the "policy_labels" edge to PolicyLabels entities by IDs. +func (puo *PoliciesUpdateOne) RemovePolicyLabelIDs(ids ...int) *PoliciesUpdateOne { + puo.mutation.RemovePolicyLabelIDs(ids...) + return puo +} + +// RemovePolicyLabels removes "policy_labels" edges to PolicyLabels entities. +func (puo *PoliciesUpdateOne) RemovePolicyLabels(p ...*PolicyLabels) *PoliciesUpdateOne { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return puo.RemovePolicyLabelIDs(ids...) +} + +// Where appends a list predicates to the PoliciesUpdate builder. +func (puo *PoliciesUpdateOne) Where(ps ...predicate.Policies) *PoliciesUpdateOne { + puo.mutation.Where(ps...) + return puo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (puo *PoliciesUpdateOne) Select(field string, fields ...string) *PoliciesUpdateOne { + puo.fields = append([]string{field}, fields...) + return puo +} + +// Save executes the query and returns the updated Policies entity. +func (puo *PoliciesUpdateOne) Save(ctx context.Context) (*Policies, error) { + return withHooks(ctx, puo.sqlSave, puo.mutation, puo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (puo *PoliciesUpdateOne) SaveX(ctx context.Context) *Policies { + node, err := puo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (puo *PoliciesUpdateOne) Exec(ctx context.Context) error { + _, err := puo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (puo *PoliciesUpdateOne) ExecX(ctx context.Context) { + if err := puo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (puo *PoliciesUpdateOne) check() error { + if v, ok := puo.mutation.Name(); ok { + if err := policies.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Policies.name": %w`, err)} + } + } + return nil +} + +func (puo *PoliciesUpdateOne) sqlSave(ctx context.Context) (_node *Policies, err error) { + if err := puo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(policies.Table, policies.Columns, sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID)) + id, ok := puo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Policies.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := puo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, policies.FieldID) + for _, f := range fields { + if !policies.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != policies.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := puo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := puo.mutation.Name(); ok { + _spec.SetField(policies.FieldName, field.TypeString, value) + } + if value, ok := puo.mutation.Image(); ok { + _spec.SetField(policies.FieldImage, field.TypeJSON, value) + } + if value, ok := puo.mutation.Labels(); ok { + _spec.SetField(policies.FieldLabels, field.TypeJSON, value) + } + if puo.mutation.LabelsCleared() { + _spec.ClearField(policies.FieldLabels, field.TypeJSON) + } + if value, ok := puo.mutation.Trigger(); ok { + _spec.SetField(policies.FieldTrigger, field.TypeJSON, value) + } + if puo.mutation.TriggerCleared() { + _spec.ClearField(policies.FieldTrigger, field.TypeJSON) + } + if value, ok := puo.mutation.Check(); ok { + _spec.SetField(policies.FieldCheck, field.TypeJSON, value) + } + if puo.mutation.CheckCleared() { + _spec.ClearField(policies.FieldCheck, field.TypeJSON) + } + if puo.mutation.PolicyLabelsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := puo.mutation.RemovedPolicyLabelsIDs(); len(nodes) > 0 && !puo.mutation.PolicyLabelsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := puo.mutation.PolicyLabelsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: policies.PolicyLabelsTable, + Columns: []string{policies.PolicyLabelsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Policies{config: puo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, puo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{policies.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + puo.mutation.done = true + return _node, nil +} diff --git a/ent/policylabels.go b/ent/policylabels.go new file mode 100644 index 0000000..ba71389 --- /dev/null +++ b/ent/policylabels.go @@ -0,0 +1,157 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" +) + +// PolicyLabels is the model entity for the PolicyLabels schema. +type PolicyLabels struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Foreign key to policies + PolicyID uuid.UUID `json:"policy_id,omitempty"` + // Key holds the value of the "key" field. + Key string `json:"key,omitempty"` + // Value holds the value of the "value" field. + Value string `json:"value,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the PolicyLabelsQuery when eager-loading is set. + Edges PolicyLabelsEdges `json:"edges"` + selectValues sql.SelectValues +} + +// PolicyLabelsEdges holds the relations/edges for other nodes in the graph. +type PolicyLabelsEdges struct { + // Policy holds the value of the policy edge. + Policy *Policies `json:"policy,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// PolicyOrErr returns the Policy value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e PolicyLabelsEdges) PolicyOrErr() (*Policies, error) { + if e.Policy != nil { + return e.Policy, nil + } else if e.loadedTypes[0] { + return nil, &NotFoundError{label: policies.Label} + } + return nil, &NotLoadedError{edge: "policy"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*PolicyLabels) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case policylabels.FieldID: + values[i] = new(sql.NullInt64) + case policylabels.FieldKey, policylabels.FieldValue: + values[i] = new(sql.NullString) + case policylabels.FieldPolicyID: + values[i] = new(uuid.UUID) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the PolicyLabels fields. +func (pl *PolicyLabels) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case policylabels.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pl.ID = int(value.Int64) + case policylabels.FieldPolicyID: + if value, ok := values[i].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field policy_id", values[i]) + } else if value != nil { + pl.PolicyID = *value + } + case policylabels.FieldKey: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field key", values[i]) + } else if value.Valid { + pl.Key = value.String + } + case policylabels.FieldValue: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field value", values[i]) + } else if value.Valid { + pl.Value = value.String + } + default: + pl.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// GetValue returns the ent.Value that was dynamically selected and assigned to the PolicyLabels. +// This includes values selected through modifiers, order, etc. +func (pl *PolicyLabels) GetValue(name string) (ent.Value, error) { + return pl.selectValues.Get(name) +} + +// QueryPolicy queries the "policy" edge of the PolicyLabels entity. +func (pl *PolicyLabels) QueryPolicy() *PoliciesQuery { + return NewPolicyLabelsClient(pl.config).QueryPolicy(pl) +} + +// Update returns a builder for updating this PolicyLabels. +// Note that you need to call PolicyLabels.Unwrap() before calling this method if this PolicyLabels +// was returned from a transaction, and the transaction was committed or rolled back. +func (pl *PolicyLabels) Update() *PolicyLabelsUpdateOne { + return NewPolicyLabelsClient(pl.config).UpdateOne(pl) +} + +// Unwrap unwraps the PolicyLabels entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (pl *PolicyLabels) Unwrap() *PolicyLabels { + _tx, ok := pl.config.driver.(*txDriver) + if !ok { + panic("ent: PolicyLabels is not a transactional entity") + } + pl.config.driver = _tx.drv + return pl +} + +// String implements the fmt.Stringer. +func (pl *PolicyLabels) String() string { + var builder strings.Builder + builder.WriteString("PolicyLabels(") + builder.WriteString(fmt.Sprintf("id=%v, ", pl.ID)) + builder.WriteString("policy_id=") + builder.WriteString(fmt.Sprintf("%v", pl.PolicyID)) + builder.WriteString(", ") + builder.WriteString("key=") + builder.WriteString(pl.Key) + builder.WriteString(", ") + builder.WriteString("value=") + builder.WriteString(pl.Value) + builder.WriteByte(')') + return builder.String() +} + +// PolicyLabelsSlice is a parsable slice of PolicyLabels. +type PolicyLabelsSlice []*PolicyLabels diff --git a/ent/policylabels/policylabels.go b/ent/policylabels/policylabels.go new file mode 100644 index 0000000..e329615 --- /dev/null +++ b/ent/policylabels/policylabels.go @@ -0,0 +1,94 @@ +// Code generated by ent, DO NOT EDIT. + +package policylabels + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the policylabels type in the database. + Label = "policy_labels" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldPolicyID holds the string denoting the policy_id field in the database. + FieldPolicyID = "policy_id" + // FieldKey holds the string denoting the key field in the database. + FieldKey = "key" + // FieldValue holds the string denoting the value field in the database. + FieldValue = "value" + // EdgePolicy holds the string denoting the policy edge name in mutations. + EdgePolicy = "policy" + // Table holds the table name of the policylabels in the database. + Table = "policy_labels" + // PolicyTable is the table that holds the policy relation/edge. + PolicyTable = "policy_labels" + // PolicyInverseTable is the table name for the Policies entity. + // It exists in this package in order to avoid circular dependency with the "policies" package. + PolicyInverseTable = "policies" + // PolicyColumn is the table column denoting the policy relation/edge. + PolicyColumn = "policy_id" +) + +// Columns holds all SQL columns for policylabels fields. +var Columns = []string{ + FieldID, + FieldPolicyID, + FieldKey, + FieldValue, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // KeyValidator is a validator for the "key" field. It is called by the builders before save. + KeyValidator func(string) error + // ValueValidator is a validator for the "value" field. It is called by the builders before save. + ValueValidator func(string) error +) + +// OrderOption defines the ordering options for the PolicyLabels queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByPolicyID orders the results by the policy_id field. +func ByPolicyID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPolicyID, opts...).ToFunc() +} + +// ByKey orders the results by the key field. +func ByKey(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldKey, opts...).ToFunc() +} + +// ByValue orders the results by the value field. +func ByValue(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldValue, opts...).ToFunc() +} + +// ByPolicyField orders the results by policy field. +func ByPolicyField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newPolicyStep(), sql.OrderByField(field, opts...)) + } +} +func newPolicyStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(PolicyInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, PolicyTable, PolicyColumn), + ) +} diff --git a/ent/policylabels/where.go b/ent/policylabels/where.go new file mode 100644 index 0000000..d32fefa --- /dev/null +++ b/ent/policylabels/where.go @@ -0,0 +1,258 @@ +// Code generated by ent, DO NOT EDIT. + +package policylabels + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldLTE(FieldID, id)) +} + +// PolicyID applies equality check predicate on the "policy_id" field. It's identical to PolicyIDEQ. +func PolicyID(v uuid.UUID) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldPolicyID, v)) +} + +// Key applies equality check predicate on the "key" field. It's identical to KeyEQ. +func Key(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldKey, v)) +} + +// Value applies equality check predicate on the "value" field. It's identical to ValueEQ. +func Value(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldValue, v)) +} + +// PolicyIDEQ applies the EQ predicate on the "policy_id" field. +func PolicyIDEQ(v uuid.UUID) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldPolicyID, v)) +} + +// PolicyIDNEQ applies the NEQ predicate on the "policy_id" field. +func PolicyIDNEQ(v uuid.UUID) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNEQ(FieldPolicyID, v)) +} + +// PolicyIDIn applies the In predicate on the "policy_id" field. +func PolicyIDIn(vs ...uuid.UUID) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldIn(FieldPolicyID, vs...)) +} + +// PolicyIDNotIn applies the NotIn predicate on the "policy_id" field. +func PolicyIDNotIn(vs ...uuid.UUID) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNotIn(FieldPolicyID, vs...)) +} + +// KeyEQ applies the EQ predicate on the "key" field. +func KeyEQ(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldKey, v)) +} + +// KeyNEQ applies the NEQ predicate on the "key" field. +func KeyNEQ(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNEQ(FieldKey, v)) +} + +// KeyIn applies the In predicate on the "key" field. +func KeyIn(vs ...string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldIn(FieldKey, vs...)) +} + +// KeyNotIn applies the NotIn predicate on the "key" field. +func KeyNotIn(vs ...string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNotIn(FieldKey, vs...)) +} + +// KeyGT applies the GT predicate on the "key" field. +func KeyGT(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldGT(FieldKey, v)) +} + +// KeyGTE applies the GTE predicate on the "key" field. +func KeyGTE(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldGTE(FieldKey, v)) +} + +// KeyLT applies the LT predicate on the "key" field. +func KeyLT(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldLT(FieldKey, v)) +} + +// KeyLTE applies the LTE predicate on the "key" field. +func KeyLTE(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldLTE(FieldKey, v)) +} + +// KeyContains applies the Contains predicate on the "key" field. +func KeyContains(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldContains(FieldKey, v)) +} + +// KeyHasPrefix applies the HasPrefix predicate on the "key" field. +func KeyHasPrefix(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldHasPrefix(FieldKey, v)) +} + +// KeyHasSuffix applies the HasSuffix predicate on the "key" field. +func KeyHasSuffix(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldHasSuffix(FieldKey, v)) +} + +// KeyEqualFold applies the EqualFold predicate on the "key" field. +func KeyEqualFold(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEqualFold(FieldKey, v)) +} + +// KeyContainsFold applies the ContainsFold predicate on the "key" field. +func KeyContainsFold(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldContainsFold(FieldKey, v)) +} + +// ValueEQ applies the EQ predicate on the "value" field. +func ValueEQ(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEQ(FieldValue, v)) +} + +// ValueNEQ applies the NEQ predicate on the "value" field. +func ValueNEQ(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNEQ(FieldValue, v)) +} + +// ValueIn applies the In predicate on the "value" field. +func ValueIn(vs ...string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldIn(FieldValue, vs...)) +} + +// ValueNotIn applies the NotIn predicate on the "value" field. +func ValueNotIn(vs ...string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldNotIn(FieldValue, vs...)) +} + +// ValueGT applies the GT predicate on the "value" field. +func ValueGT(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldGT(FieldValue, v)) +} + +// ValueGTE applies the GTE predicate on the "value" field. +func ValueGTE(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldGTE(FieldValue, v)) +} + +// ValueLT applies the LT predicate on the "value" field. +func ValueLT(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldLT(FieldValue, v)) +} + +// ValueLTE applies the LTE predicate on the "value" field. +func ValueLTE(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldLTE(FieldValue, v)) +} + +// ValueContains applies the Contains predicate on the "value" field. +func ValueContains(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldContains(FieldValue, v)) +} + +// ValueHasPrefix applies the HasPrefix predicate on the "value" field. +func ValueHasPrefix(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldHasPrefix(FieldValue, v)) +} + +// ValueHasSuffix applies the HasSuffix predicate on the "value" field. +func ValueHasSuffix(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldHasSuffix(FieldValue, v)) +} + +// ValueEqualFold applies the EqualFold predicate on the "value" field. +func ValueEqualFold(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldEqualFold(FieldValue, v)) +} + +// ValueContainsFold applies the ContainsFold predicate on the "value" field. +func ValueContainsFold(v string) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.FieldContainsFold(FieldValue, v)) +} + +// HasPolicy applies the HasEdge predicate on the "policy" edge. +func HasPolicy() predicate.PolicyLabels { + return predicate.PolicyLabels(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, PolicyTable, PolicyColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasPolicyWith applies the HasEdge predicate on the "policy" edge with a given conditions (other predicates). +func HasPolicyWith(preds ...predicate.Policies) predicate.PolicyLabels { + return predicate.PolicyLabels(func(s *sql.Selector) { + step := newPolicyStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.PolicyLabels) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.PolicyLabels) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.PolicyLabels) predicate.PolicyLabels { + return predicate.PolicyLabels(sql.NotPredicates(p)) +} diff --git a/ent/policylabels_create.go b/ent/policylabels_create.go new file mode 100644 index 0000000..6912616 --- /dev/null +++ b/ent/policylabels_create.go @@ -0,0 +1,242 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" +) + +// PolicyLabelsCreate is the builder for creating a PolicyLabels entity. +type PolicyLabelsCreate struct { + config + mutation *PolicyLabelsMutation + hooks []Hook +} + +// SetPolicyID sets the "policy_id" field. +func (plc *PolicyLabelsCreate) SetPolicyID(u uuid.UUID) *PolicyLabelsCreate { + plc.mutation.SetPolicyID(u) + return plc +} + +// SetKey sets the "key" field. +func (plc *PolicyLabelsCreate) SetKey(s string) *PolicyLabelsCreate { + plc.mutation.SetKey(s) + return plc +} + +// SetValue sets the "value" field. +func (plc *PolicyLabelsCreate) SetValue(s string) *PolicyLabelsCreate { + plc.mutation.SetValue(s) + return plc +} + +// SetPolicy sets the "policy" edge to the Policies entity. +func (plc *PolicyLabelsCreate) SetPolicy(p *Policies) *PolicyLabelsCreate { + return plc.SetPolicyID(p.ID) +} + +// Mutation returns the PolicyLabelsMutation object of the builder. +func (plc *PolicyLabelsCreate) Mutation() *PolicyLabelsMutation { + return plc.mutation +} + +// Save creates the PolicyLabels in the database. +func (plc *PolicyLabelsCreate) Save(ctx context.Context) (*PolicyLabels, error) { + return withHooks(ctx, plc.sqlSave, plc.mutation, plc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (plc *PolicyLabelsCreate) SaveX(ctx context.Context) *PolicyLabels { + v, err := plc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (plc *PolicyLabelsCreate) Exec(ctx context.Context) error { + _, err := plc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (plc *PolicyLabelsCreate) ExecX(ctx context.Context) { + if err := plc.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (plc *PolicyLabelsCreate) check() error { + if _, ok := plc.mutation.PolicyID(); !ok { + return &ValidationError{Name: "policy_id", err: errors.New(`ent: missing required field "PolicyLabels.policy_id"`)} + } + if _, ok := plc.mutation.Key(); !ok { + return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "PolicyLabels.key"`)} + } + if v, ok := plc.mutation.Key(); ok { + if err := policylabels.KeyValidator(v); err != nil { + return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "PolicyLabels.key": %w`, err)} + } + } + if _, ok := plc.mutation.Value(); !ok { + return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "PolicyLabels.value"`)} + } + if v, ok := plc.mutation.Value(); ok { + if err := policylabels.ValueValidator(v); err != nil { + return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "PolicyLabels.value": %w`, err)} + } + } + if len(plc.mutation.PolicyIDs()) == 0 { + return &ValidationError{Name: "policy", err: errors.New(`ent: missing required edge "PolicyLabels.policy"`)} + } + return nil +} + +func (plc *PolicyLabelsCreate) sqlSave(ctx context.Context) (*PolicyLabels, error) { + if err := plc.check(); err != nil { + return nil, err + } + _node, _spec := plc.createSpec() + if err := sqlgraph.CreateNode(ctx, plc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + plc.mutation.id = &_node.ID + plc.mutation.done = true + return _node, nil +} + +func (plc *PolicyLabelsCreate) createSpec() (*PolicyLabels, *sqlgraph.CreateSpec) { + var ( + _node = &PolicyLabels{config: plc.config} + _spec = sqlgraph.NewCreateSpec(policylabels.Table, sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt)) + ) + if value, ok := plc.mutation.Key(); ok { + _spec.SetField(policylabels.FieldKey, field.TypeString, value) + _node.Key = value + } + if value, ok := plc.mutation.Value(); ok { + _spec.SetField(policylabels.FieldValue, field.TypeString, value) + _node.Value = value + } + if nodes := plc.mutation.PolicyIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: policylabels.PolicyTable, + Columns: []string{policylabels.PolicyColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.PolicyID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// PolicyLabelsCreateBulk is the builder for creating many PolicyLabels entities in bulk. +type PolicyLabelsCreateBulk struct { + config + err error + builders []*PolicyLabelsCreate +} + +// Save creates the PolicyLabels entities in the database. +func (plcb *PolicyLabelsCreateBulk) Save(ctx context.Context) ([]*PolicyLabels, error) { + if plcb.err != nil { + return nil, plcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(plcb.builders)) + nodes := make([]*PolicyLabels, len(plcb.builders)) + mutators := make([]Mutator, len(plcb.builders)) + for i := range plcb.builders { + func(i int, root context.Context) { + builder := plcb.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*PolicyLabelsMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, plcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, plcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, plcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (plcb *PolicyLabelsCreateBulk) SaveX(ctx context.Context) []*PolicyLabels { + v, err := plcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (plcb *PolicyLabelsCreateBulk) Exec(ctx context.Context) error { + _, err := plcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (plcb *PolicyLabelsCreateBulk) ExecX(ctx context.Context) { + if err := plcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/policylabels_delete.go b/ent/policylabels_delete.go new file mode 100644 index 0000000..46c4c76 --- /dev/null +++ b/ent/policylabels_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// PolicyLabelsDelete is the builder for deleting a PolicyLabels entity. +type PolicyLabelsDelete struct { + config + hooks []Hook + mutation *PolicyLabelsMutation +} + +// Where appends a list predicates to the PolicyLabelsDelete builder. +func (pld *PolicyLabelsDelete) Where(ps ...predicate.PolicyLabels) *PolicyLabelsDelete { + pld.mutation.Where(ps...) + return pld +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (pld *PolicyLabelsDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, pld.sqlExec, pld.mutation, pld.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (pld *PolicyLabelsDelete) ExecX(ctx context.Context) int { + n, err := pld.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (pld *PolicyLabelsDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(policylabels.Table, sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt)) + if ps := pld.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, pld.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + pld.mutation.done = true + return affected, err +} + +// PolicyLabelsDeleteOne is the builder for deleting a single PolicyLabels entity. +type PolicyLabelsDeleteOne struct { + pld *PolicyLabelsDelete +} + +// Where appends a list predicates to the PolicyLabelsDelete builder. +func (pldo *PolicyLabelsDeleteOne) Where(ps ...predicate.PolicyLabels) *PolicyLabelsDeleteOne { + pldo.pld.mutation.Where(ps...) + return pldo +} + +// Exec executes the deletion query. +func (pldo *PolicyLabelsDeleteOne) Exec(ctx context.Context) error { + n, err := pldo.pld.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{policylabels.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (pldo *PolicyLabelsDeleteOne) ExecX(ctx context.Context) { + if err := pldo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/policylabels_query.go b/ent/policylabels_query.go new file mode 100644 index 0000000..018323e --- /dev/null +++ b/ent/policylabels_query.go @@ -0,0 +1,607 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// PolicyLabelsQuery is the builder for querying PolicyLabels entities. +type PolicyLabelsQuery struct { + config + ctx *QueryContext + order []policylabels.OrderOption + inters []Interceptor + predicates []predicate.PolicyLabels + withPolicy *PoliciesQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the PolicyLabelsQuery builder. +func (plq *PolicyLabelsQuery) Where(ps ...predicate.PolicyLabels) *PolicyLabelsQuery { + plq.predicates = append(plq.predicates, ps...) + return plq +} + +// Limit the number of records to be returned by this query. +func (plq *PolicyLabelsQuery) Limit(limit int) *PolicyLabelsQuery { + plq.ctx.Limit = &limit + return plq +} + +// Offset to start from. +func (plq *PolicyLabelsQuery) Offset(offset int) *PolicyLabelsQuery { + plq.ctx.Offset = &offset + return plq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (plq *PolicyLabelsQuery) Unique(unique bool) *PolicyLabelsQuery { + plq.ctx.Unique = &unique + return plq +} + +// Order specifies how the records should be ordered. +func (plq *PolicyLabelsQuery) Order(o ...policylabels.OrderOption) *PolicyLabelsQuery { + plq.order = append(plq.order, o...) + return plq +} + +// QueryPolicy chains the current query on the "policy" edge. +func (plq *PolicyLabelsQuery) QueryPolicy() *PoliciesQuery { + query := (&PoliciesClient{config: plq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := plq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := plq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(policylabels.Table, policylabels.FieldID, selector), + sqlgraph.To(policies.Table, policies.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, policylabels.PolicyTable, policylabels.PolicyColumn), + ) + fromU = sqlgraph.SetNeighbors(plq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first PolicyLabels entity from the query. +// Returns a *NotFoundError when no PolicyLabels was found. +func (plq *PolicyLabelsQuery) First(ctx context.Context) (*PolicyLabels, error) { + nodes, err := plq.Limit(1).All(setContextOp(ctx, plq.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{policylabels.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (plq *PolicyLabelsQuery) FirstX(ctx context.Context) *PolicyLabels { + node, err := plq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first PolicyLabels ID from the query. +// Returns a *NotFoundError when no PolicyLabels ID was found. +func (plq *PolicyLabelsQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = plq.Limit(1).IDs(setContextOp(ctx, plq.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{policylabels.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (plq *PolicyLabelsQuery) FirstIDX(ctx context.Context) int { + id, err := plq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single PolicyLabels entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one PolicyLabels entity is found. +// Returns a *NotFoundError when no PolicyLabels entities are found. +func (plq *PolicyLabelsQuery) Only(ctx context.Context) (*PolicyLabels, error) { + nodes, err := plq.Limit(2).All(setContextOp(ctx, plq.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{policylabels.Label} + default: + return nil, &NotSingularError{policylabels.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (plq *PolicyLabelsQuery) OnlyX(ctx context.Context) *PolicyLabels { + node, err := plq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only PolicyLabels ID in the query. +// Returns a *NotSingularError when more than one PolicyLabels ID is found. +// Returns a *NotFoundError when no entities are found. +func (plq *PolicyLabelsQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = plq.Limit(2).IDs(setContextOp(ctx, plq.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{policylabels.Label} + default: + err = &NotSingularError{policylabels.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (plq *PolicyLabelsQuery) OnlyIDX(ctx context.Context) int { + id, err := plq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of PolicyLabelsSlice. +func (plq *PolicyLabelsQuery) All(ctx context.Context) ([]*PolicyLabels, error) { + ctx = setContextOp(ctx, plq.ctx, ent.OpQueryAll) + if err := plq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*PolicyLabels, *PolicyLabelsQuery]() + return withInterceptors[[]*PolicyLabels](ctx, plq, qr, plq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (plq *PolicyLabelsQuery) AllX(ctx context.Context) []*PolicyLabels { + nodes, err := plq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of PolicyLabels IDs. +func (plq *PolicyLabelsQuery) IDs(ctx context.Context) (ids []int, err error) { + if plq.ctx.Unique == nil && plq.path != nil { + plq.Unique(true) + } + ctx = setContextOp(ctx, plq.ctx, ent.OpQueryIDs) + if err = plq.Select(policylabels.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (plq *PolicyLabelsQuery) IDsX(ctx context.Context) []int { + ids, err := plq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (plq *PolicyLabelsQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, plq.ctx, ent.OpQueryCount) + if err := plq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, plq, querierCount[*PolicyLabelsQuery](), plq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (plq *PolicyLabelsQuery) CountX(ctx context.Context) int { + count, err := plq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (plq *PolicyLabelsQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, plq.ctx, ent.OpQueryExist) + switch _, err := plq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (plq *PolicyLabelsQuery) ExistX(ctx context.Context) bool { + exist, err := plq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the PolicyLabelsQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (plq *PolicyLabelsQuery) Clone() *PolicyLabelsQuery { + if plq == nil { + return nil + } + return &PolicyLabelsQuery{ + config: plq.config, + ctx: plq.ctx.Clone(), + order: append([]policylabels.OrderOption{}, plq.order...), + inters: append([]Interceptor{}, plq.inters...), + predicates: append([]predicate.PolicyLabels{}, plq.predicates...), + withPolicy: plq.withPolicy.Clone(), + // clone intermediate query. + sql: plq.sql.Clone(), + path: plq.path, + } +} + +// WithPolicy tells the query-builder to eager-load the nodes that are connected to +// the "policy" edge. The optional arguments are used to configure the query builder of the edge. +func (plq *PolicyLabelsQuery) WithPolicy(opts ...func(*PoliciesQuery)) *PolicyLabelsQuery { + query := (&PoliciesClient{config: plq.config}).Query() + for _, opt := range opts { + opt(query) + } + plq.withPolicy = query + return plq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// PolicyID uuid.UUID `json:"policy_id,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.PolicyLabels.Query(). +// GroupBy(policylabels.FieldPolicyID). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (plq *PolicyLabelsQuery) GroupBy(field string, fields ...string) *PolicyLabelsGroupBy { + plq.ctx.Fields = append([]string{field}, fields...) + grbuild := &PolicyLabelsGroupBy{build: plq} + grbuild.flds = &plq.ctx.Fields + grbuild.label = policylabels.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// PolicyID uuid.UUID `json:"policy_id,omitempty"` +// } +// +// client.PolicyLabels.Query(). +// Select(policylabels.FieldPolicyID). +// Scan(ctx, &v) +func (plq *PolicyLabelsQuery) Select(fields ...string) *PolicyLabelsSelect { + plq.ctx.Fields = append(plq.ctx.Fields, fields...) + sbuild := &PolicyLabelsSelect{PolicyLabelsQuery: plq} + sbuild.label = policylabels.Label + sbuild.flds, sbuild.scan = &plq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a PolicyLabelsSelect configured with the given aggregations. +func (plq *PolicyLabelsQuery) Aggregate(fns ...AggregateFunc) *PolicyLabelsSelect { + return plq.Select().Aggregate(fns...) +} + +func (plq *PolicyLabelsQuery) prepareQuery(ctx context.Context) error { + for _, inter := range plq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, plq); err != nil { + return err + } + } + } + for _, f := range plq.ctx.Fields { + if !policylabels.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if plq.path != nil { + prev, err := plq.path(ctx) + if err != nil { + return err + } + plq.sql = prev + } + return nil +} + +func (plq *PolicyLabelsQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*PolicyLabels, error) { + var ( + nodes = []*PolicyLabels{} + _spec = plq.querySpec() + loadedTypes = [1]bool{ + plq.withPolicy != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*PolicyLabels).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &PolicyLabels{config: plq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, plq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := plq.withPolicy; query != nil { + if err := plq.loadPolicy(ctx, query, nodes, nil, + func(n *PolicyLabels, e *Policies) { n.Edges.Policy = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (plq *PolicyLabelsQuery) loadPolicy(ctx context.Context, query *PoliciesQuery, nodes []*PolicyLabels, init func(*PolicyLabels), assign func(*PolicyLabels, *Policies)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*PolicyLabels) + for i := range nodes { + fk := nodes[i].PolicyID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(policies.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "policy_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (plq *PolicyLabelsQuery) sqlCount(ctx context.Context) (int, error) { + _spec := plq.querySpec() + _spec.Node.Columns = plq.ctx.Fields + if len(plq.ctx.Fields) > 0 { + _spec.Unique = plq.ctx.Unique != nil && *plq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, plq.driver, _spec) +} + +func (plq *PolicyLabelsQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(policylabels.Table, policylabels.Columns, sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt)) + _spec.From = plq.sql + if unique := plq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if plq.path != nil { + _spec.Unique = true + } + if fields := plq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, policylabels.FieldID) + for i := range fields { + if fields[i] != policylabels.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if plq.withPolicy != nil { + _spec.Node.AddColumnOnce(policylabels.FieldPolicyID) + } + } + if ps := plq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := plq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := plq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := plq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (plq *PolicyLabelsQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(plq.driver.Dialect()) + t1 := builder.Table(policylabels.Table) + columns := plq.ctx.Fields + if len(columns) == 0 { + columns = policylabels.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if plq.sql != nil { + selector = plq.sql + selector.Select(selector.Columns(columns...)...) + } + if plq.ctx.Unique != nil && *plq.ctx.Unique { + selector.Distinct() + } + for _, p := range plq.predicates { + p(selector) + } + for _, p := range plq.order { + p(selector) + } + if offset := plq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := plq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// PolicyLabelsGroupBy is the group-by builder for PolicyLabels entities. +type PolicyLabelsGroupBy struct { + selector + build *PolicyLabelsQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (plgb *PolicyLabelsGroupBy) Aggregate(fns ...AggregateFunc) *PolicyLabelsGroupBy { + plgb.fns = append(plgb.fns, fns...) + return plgb +} + +// Scan applies the selector query and scans the result into the given value. +func (plgb *PolicyLabelsGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, plgb.build.ctx, ent.OpQueryGroupBy) + if err := plgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*PolicyLabelsQuery, *PolicyLabelsGroupBy](ctx, plgb.build, plgb, plgb.build.inters, v) +} + +func (plgb *PolicyLabelsGroupBy) sqlScan(ctx context.Context, root *PolicyLabelsQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(plgb.fns)) + for _, fn := range plgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*plgb.flds)+len(plgb.fns)) + for _, f := range *plgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*plgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := plgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// PolicyLabelsSelect is the builder for selecting fields of PolicyLabels entities. +type PolicyLabelsSelect struct { + *PolicyLabelsQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (pls *PolicyLabelsSelect) Aggregate(fns ...AggregateFunc) *PolicyLabelsSelect { + pls.fns = append(pls.fns, fns...) + return pls +} + +// Scan applies the selector query and scans the result into the given value. +func (pls *PolicyLabelsSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, pls.ctx, ent.OpQuerySelect) + if err := pls.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*PolicyLabelsQuery, *PolicyLabelsSelect](ctx, pls.PolicyLabelsQuery, pls, pls.inters, v) +} + +func (pls *PolicyLabelsSelect) sqlScan(ctx context.Context, root *PolicyLabelsQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(pls.fns)) + for _, fn := range pls.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*pls.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := pls.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/policylabels_update.go b/ent/policylabels_update.go new file mode 100644 index 0000000..e237fbe --- /dev/null +++ b/ent/policylabels_update.go @@ -0,0 +1,395 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/shinobistack/gokakashi/ent/predicate" +) + +// PolicyLabelsUpdate is the builder for updating PolicyLabels entities. +type PolicyLabelsUpdate struct { + config + hooks []Hook + mutation *PolicyLabelsMutation +} + +// Where appends a list predicates to the PolicyLabelsUpdate builder. +func (plu *PolicyLabelsUpdate) Where(ps ...predicate.PolicyLabels) *PolicyLabelsUpdate { + plu.mutation.Where(ps...) + return plu +} + +// SetPolicyID sets the "policy_id" field. +func (plu *PolicyLabelsUpdate) SetPolicyID(u uuid.UUID) *PolicyLabelsUpdate { + plu.mutation.SetPolicyID(u) + return plu +} + +// SetNillablePolicyID sets the "policy_id" field if the given value is not nil. +func (plu *PolicyLabelsUpdate) SetNillablePolicyID(u *uuid.UUID) *PolicyLabelsUpdate { + if u != nil { + plu.SetPolicyID(*u) + } + return plu +} + +// SetKey sets the "key" field. +func (plu *PolicyLabelsUpdate) SetKey(s string) *PolicyLabelsUpdate { + plu.mutation.SetKey(s) + return plu +} + +// SetNillableKey sets the "key" field if the given value is not nil. +func (plu *PolicyLabelsUpdate) SetNillableKey(s *string) *PolicyLabelsUpdate { + if s != nil { + plu.SetKey(*s) + } + return plu +} + +// SetValue sets the "value" field. +func (plu *PolicyLabelsUpdate) SetValue(s string) *PolicyLabelsUpdate { + plu.mutation.SetValue(s) + return plu +} + +// SetNillableValue sets the "value" field if the given value is not nil. +func (plu *PolicyLabelsUpdate) SetNillableValue(s *string) *PolicyLabelsUpdate { + if s != nil { + plu.SetValue(*s) + } + return plu +} + +// SetPolicy sets the "policy" edge to the Policies entity. +func (plu *PolicyLabelsUpdate) SetPolicy(p *Policies) *PolicyLabelsUpdate { + return plu.SetPolicyID(p.ID) +} + +// Mutation returns the PolicyLabelsMutation object of the builder. +func (plu *PolicyLabelsUpdate) Mutation() *PolicyLabelsMutation { + return plu.mutation +} + +// ClearPolicy clears the "policy" edge to the Policies entity. +func (plu *PolicyLabelsUpdate) ClearPolicy() *PolicyLabelsUpdate { + plu.mutation.ClearPolicy() + return plu +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (plu *PolicyLabelsUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, plu.sqlSave, plu.mutation, plu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (plu *PolicyLabelsUpdate) SaveX(ctx context.Context) int { + affected, err := plu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (plu *PolicyLabelsUpdate) Exec(ctx context.Context) error { + _, err := plu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (plu *PolicyLabelsUpdate) ExecX(ctx context.Context) { + if err := plu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (plu *PolicyLabelsUpdate) check() error { + if v, ok := plu.mutation.Key(); ok { + if err := policylabels.KeyValidator(v); err != nil { + return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "PolicyLabels.key": %w`, err)} + } + } + if v, ok := plu.mutation.Value(); ok { + if err := policylabels.ValueValidator(v); err != nil { + return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "PolicyLabels.value": %w`, err)} + } + } + if plu.mutation.PolicyCleared() && len(plu.mutation.PolicyIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "PolicyLabels.policy"`) + } + return nil +} + +func (plu *PolicyLabelsUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := plu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(policylabels.Table, policylabels.Columns, sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt)) + if ps := plu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := plu.mutation.Key(); ok { + _spec.SetField(policylabels.FieldKey, field.TypeString, value) + } + if value, ok := plu.mutation.Value(); ok { + _spec.SetField(policylabels.FieldValue, field.TypeString, value) + } + if plu.mutation.PolicyCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: policylabels.PolicyTable, + Columns: []string{policylabels.PolicyColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := plu.mutation.PolicyIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: policylabels.PolicyTable, + Columns: []string{policylabels.PolicyColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, plu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{policylabels.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + plu.mutation.done = true + return n, nil +} + +// PolicyLabelsUpdateOne is the builder for updating a single PolicyLabels entity. +type PolicyLabelsUpdateOne struct { + config + fields []string + hooks []Hook + mutation *PolicyLabelsMutation +} + +// SetPolicyID sets the "policy_id" field. +func (pluo *PolicyLabelsUpdateOne) SetPolicyID(u uuid.UUID) *PolicyLabelsUpdateOne { + pluo.mutation.SetPolicyID(u) + return pluo +} + +// SetNillablePolicyID sets the "policy_id" field if the given value is not nil. +func (pluo *PolicyLabelsUpdateOne) SetNillablePolicyID(u *uuid.UUID) *PolicyLabelsUpdateOne { + if u != nil { + pluo.SetPolicyID(*u) + } + return pluo +} + +// SetKey sets the "key" field. +func (pluo *PolicyLabelsUpdateOne) SetKey(s string) *PolicyLabelsUpdateOne { + pluo.mutation.SetKey(s) + return pluo +} + +// SetNillableKey sets the "key" field if the given value is not nil. +func (pluo *PolicyLabelsUpdateOne) SetNillableKey(s *string) *PolicyLabelsUpdateOne { + if s != nil { + pluo.SetKey(*s) + } + return pluo +} + +// SetValue sets the "value" field. +func (pluo *PolicyLabelsUpdateOne) SetValue(s string) *PolicyLabelsUpdateOne { + pluo.mutation.SetValue(s) + return pluo +} + +// SetNillableValue sets the "value" field if the given value is not nil. +func (pluo *PolicyLabelsUpdateOne) SetNillableValue(s *string) *PolicyLabelsUpdateOne { + if s != nil { + pluo.SetValue(*s) + } + return pluo +} + +// SetPolicy sets the "policy" edge to the Policies entity. +func (pluo *PolicyLabelsUpdateOne) SetPolicy(p *Policies) *PolicyLabelsUpdateOne { + return pluo.SetPolicyID(p.ID) +} + +// Mutation returns the PolicyLabelsMutation object of the builder. +func (pluo *PolicyLabelsUpdateOne) Mutation() *PolicyLabelsMutation { + return pluo.mutation +} + +// ClearPolicy clears the "policy" edge to the Policies entity. +func (pluo *PolicyLabelsUpdateOne) ClearPolicy() *PolicyLabelsUpdateOne { + pluo.mutation.ClearPolicy() + return pluo +} + +// Where appends a list predicates to the PolicyLabelsUpdate builder. +func (pluo *PolicyLabelsUpdateOne) Where(ps ...predicate.PolicyLabels) *PolicyLabelsUpdateOne { + pluo.mutation.Where(ps...) + return pluo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (pluo *PolicyLabelsUpdateOne) Select(field string, fields ...string) *PolicyLabelsUpdateOne { + pluo.fields = append([]string{field}, fields...) + return pluo +} + +// Save executes the query and returns the updated PolicyLabels entity. +func (pluo *PolicyLabelsUpdateOne) Save(ctx context.Context) (*PolicyLabels, error) { + return withHooks(ctx, pluo.sqlSave, pluo.mutation, pluo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (pluo *PolicyLabelsUpdateOne) SaveX(ctx context.Context) *PolicyLabels { + node, err := pluo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (pluo *PolicyLabelsUpdateOne) Exec(ctx context.Context) error { + _, err := pluo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pluo *PolicyLabelsUpdateOne) ExecX(ctx context.Context) { + if err := pluo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (pluo *PolicyLabelsUpdateOne) check() error { + if v, ok := pluo.mutation.Key(); ok { + if err := policylabels.KeyValidator(v); err != nil { + return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "PolicyLabels.key": %w`, err)} + } + } + if v, ok := pluo.mutation.Value(); ok { + if err := policylabels.ValueValidator(v); err != nil { + return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "PolicyLabels.value": %w`, err)} + } + } + if pluo.mutation.PolicyCleared() && len(pluo.mutation.PolicyIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "PolicyLabels.policy"`) + } + return nil +} + +func (pluo *PolicyLabelsUpdateOne) sqlSave(ctx context.Context) (_node *PolicyLabels, err error) { + if err := pluo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(policylabels.Table, policylabels.Columns, sqlgraph.NewFieldSpec(policylabels.FieldID, field.TypeInt)) + id, ok := pluo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "PolicyLabels.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := pluo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, policylabels.FieldID) + for _, f := range fields { + if !policylabels.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != policylabels.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := pluo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := pluo.mutation.Key(); ok { + _spec.SetField(policylabels.FieldKey, field.TypeString, value) + } + if value, ok := pluo.mutation.Value(); ok { + _spec.SetField(policylabels.FieldValue, field.TypeString, value) + } + if pluo.mutation.PolicyCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: policylabels.PolicyTable, + Columns: []string{policylabels.PolicyColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := pluo.mutation.PolicyIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: policylabels.PolicyTable, + Columns: []string{policylabels.PolicyColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(policies.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &PolicyLabels{config: pluo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, pluo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{policylabels.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + pluo.mutation.done = true + return _node, nil +} diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index 8d7e3a7..ca231c0 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -11,3 +11,9 @@ type IntegrationType func(*sql.Selector) // Integrations is the predicate function for integrations builders. type Integrations func(*sql.Selector) + +// Policies is the predicate function for policies builders. +type Policies func(*sql.Selector) + +// PolicyLabels is the predicate function for policylabels builders. +type PolicyLabels func(*sql.Selector) diff --git a/ent/runtime.go b/ent/runtime.go index 1e85412..70a10b5 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -6,6 +6,8 @@ import ( "github.com/google/uuid" "github.com/shinobistack/gokakashi/ent/integrations" "github.com/shinobistack/gokakashi/ent/integrationtype" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" "github.com/shinobistack/gokakashi/ent/schema" ) @@ -33,4 +35,38 @@ func init() { integrationsDescID := integrationsFields[0].Descriptor() // integrations.DefaultID holds the default value on creation for the id field. integrations.DefaultID = integrationsDescID.Default.(func() uuid.UUID) + policiesFields := schema.Policies{}.Fields() + _ = policiesFields + // policiesDescName is the schema descriptor for name field. + policiesDescName := policiesFields[1].Descriptor() + // policies.NameValidator is a validator for the "name" field. It is called by the builders before save. + policies.NameValidator = func() func(string) error { + validators := policiesDescName.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(name string) error { + for _, fn := range fns { + if err := fn(name); err != nil { + return err + } + } + return nil + } + }() + // policiesDescID is the schema descriptor for id field. + policiesDescID := policiesFields[0].Descriptor() + // policies.DefaultID holds the default value on creation for the id field. + policies.DefaultID = policiesDescID.Default.(func() uuid.UUID) + policylabelsFields := schema.PolicyLabels{}.Fields() + _ = policylabelsFields + // policylabelsDescKey is the schema descriptor for key field. + policylabelsDescKey := policylabelsFields[1].Descriptor() + // policylabels.KeyValidator is a validator for the "key" field. It is called by the builders before save. + policylabels.KeyValidator = policylabelsDescKey.Validators[0].(func(string) error) + // policylabelsDescValue is the schema descriptor for value field. + policylabelsDescValue := policylabelsFields[2].Descriptor() + // policylabels.ValueValidator is a validator for the "value" field. It is called by the builders before save. + policylabels.ValueValidator = policylabelsDescValue.Validators[0].(func(string) error) } diff --git a/ent/schema/integrations.go b/ent/schema/integrations.go index 2970f0c..4ad9fa6 100644 --- a/ent/schema/integrations.go +++ b/ent/schema/integrations.go @@ -15,9 +15,16 @@ type Integrations struct { // Fields of the Integrations. func (Integrations) Fields() []ent.Field { return []ent.Field{ - field.UUID("id", uuid.UUID{}).Default(uuid.New).Unique().Immutable().Comment("UUID for unique identification"), - field.String("name").NotEmpty().Unique().Comment("Integration name"), - field.String("type").NotEmpty().Comment("Foreign key to IntegrationType.id"), + field.UUID("id", uuid.UUID{}). + Default(uuid.New).Unique(). + Immutable(). + Comment("UUID for unique identification"), + field.String("name"). + NotEmpty().Unique(). + Comment("Integration name"), + field.String("type"). + NotEmpty(). + Comment("Foreign key to IntegrationType.id"), field.JSON("config", map[string]interface{}{}).Comment("Integrations Configurations stored as JSONB"), } } @@ -25,7 +32,7 @@ func (Integrations) Fields() []ent.Field { // Edges of the Integrations. func (Integrations) Edges() []ent.Edge { // Many to one - edge.From("id", Integrations.Type). + edge.From("integrations_type", Integrations.Type). // Reference the "integrations" edge in IntegrationType Ref("integrations"). // Use as foreign key diff --git a/ent/schema/integrationtype.go b/ent/schema/integrationtype.go index f2a374a..9b6d9f4 100644 --- a/ent/schema/integrationtype.go +++ b/ent/schema/integrationtype.go @@ -15,7 +15,7 @@ type IntegrationType struct { func (IntegrationType) Fields() []ent.Field { return []ent.Field{ field.String("id").Unique().Immutable(), - field.String("display_name").NotEmpty().Unique().Comment("Types of Integration e.g., linear,jira"), + field.String("display_name").NotEmpty().Unique().Comment("Human-readable name for the integration type"), } } diff --git a/ent/schema/policies.go b/ent/schema/policies.go new file mode 100644 index 0000000..f0a5c1f --- /dev/null +++ b/ent/schema/policies.go @@ -0,0 +1,63 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// Policies holds the schema definition for the Policies entity. +type Policies struct { + ent.Schema +} + +type PolicyLabel struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type Image struct { + Registry string `json:"registry"` + Name string `json:"name"` + Tags []string `json:"tags"` +} + +type Check struct { + Condition string `json:"condition"` + Notify []string `json:"notify"` +} + +// Fields of the Policies. +func (Policies) Fields() []ent.Field { + return []ent.Field{ + field.UUID("id", uuid.UUID{}). + Default(uuid.New). + Unique(). + Comment("Primary key, unique identifier."), + field.String("name"). + NotEmpty(). + Unique(). + NotEmpty(). + Comment("Policy name."), + field.JSON("image", Image{}). + Comment("Stores image details like registry, tags."), + field.JSON("labels", PolicyLabels{}). + Optional(). + Comment("Policies labels key:value"), + // Todo: Trigger is optional + field.JSON("trigger", map[string]interface{}{}). + Optional(). + Comment("Stores trigger details (e.g., cron schedule)."), + field.JSON("check", Check{}).Optional(). + Comment("Stores conditions for evaluation."), + } +} + +// Edges of the Policies. +func (Policies) Edges() []ent.Edge { + // a one-to-many relationship with PolicyLabels. + return []ent.Edge{ + edge.To("policy_labels", PolicyLabels.Type), + } +} diff --git a/ent/schema/policylabels.go b/ent/schema/policylabels.go new file mode 100644 index 0000000..3cb9ca0 --- /dev/null +++ b/ent/schema/policylabels.go @@ -0,0 +1,36 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// PolicyLabels holds the schema definition for the PolicyLabels entity. +type PolicyLabels struct { + ent.Schema +} + +// Fields of the PolicyLabels. +func (PolicyLabels) Fields() []ent.Field { + return []ent.Field{ + field.UUID("policy_id", uuid.UUID{}). + Comment("Foreign key to policies"), + field.String("key"). + NotEmpty(), + field.String("value"). + NotEmpty(), + } +} + +// Edges of the PolicyLabels. +func (PolicyLabels) Edges() []ent.Edge { + // many-to-one relationship back to policies. + return []ent.Edge{ + edge.From("policy", Policies.Type). + Ref("policy_labels"). + Field("policy_id"). + Unique().Required(), + } +} diff --git a/ent/tx.go b/ent/tx.go index fb328f2..24551cd 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -16,6 +16,10 @@ type Tx struct { IntegrationType *IntegrationTypeClient // Integrations is the client for interacting with the Integrations builders. Integrations *IntegrationsClient + // Policies is the client for interacting with the Policies builders. + Policies *PoliciesClient + // PolicyLabels is the client for interacting with the PolicyLabels builders. + PolicyLabels *PolicyLabelsClient // lazily loaded. client *Client @@ -149,6 +153,8 @@ func (tx *Tx) Client() *Client { func (tx *Tx) init() { tx.IntegrationType = NewIntegrationTypeClient(tx.config) tx.Integrations = NewIntegrationsClient(tx.config) + tx.Policies = NewPoliciesClient(tx.config) + tx.PolicyLabels = NewPolicyLabelsClient(tx.config) } // txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation. diff --git a/go.sum b/go.sum index 3341a90..1d11ce7 100644 --- a/go.sum +++ b/go.sum @@ -57,10 +57,14 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -117,6 +121,8 @@ golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -124,6 +130,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/restapi/v1/integrations/get.go b/internal/restapi/v1/integrations/get.go index c5280bd..5f9c274 100644 --- a/internal/restapi/v1/integrations/get.go +++ b/internal/restapi/v1/integrations/get.go @@ -10,11 +10,11 @@ import ( ) type GetIntegrationRequests struct { - ID string `path:"id"` + ID uuid.UUID `path:"id"` } type GetIntegrationResponse struct { - ID string `json:"id"` + ID uuid.UUID `json:"id"` Name string `json:"name"` Type string `json:"type"` Config map[string]interface{} `json:"config"` @@ -26,14 +26,13 @@ type ListIntegrationResponse struct { func GetIntegration(client *ent.Client) func(ctx context.Context, req GetIntegrationRequests, res *GetIntegrationResponse) error { return func(ctx context.Context, req GetIntegrationRequests, res *GetIntegrationResponse) error { - // Convert string to uuid.UUID - uid, err := uuid.Parse(req.ID) - if err != nil { - return status.Wrap(errors.New("invalid UUID format"), status.InvalidArgument) + // Validate ID + if req.ID == uuid.Nil { + return status.Wrap(errors.New("invalid UUID: cannot be nil"), status.InvalidArgument) } // Fetch integration by ID - integration, err := client.Integrations.Get(ctx, uid) + integration, err := client.Integrations.Get(ctx, req.ID) if err != nil { if ent.IsNotFound(err) { return status.Wrap(errors.New("integration not found"), status.NotFound) @@ -41,7 +40,7 @@ func GetIntegration(client *ent.Client) func(ctx context.Context, req GetIntegra return status.Wrap(fmt.Errorf("unexpected error: %v", err), status.Internal) } - res.ID = integration.ID.String() + res.ID = integration.ID res.Name = integration.Name res.Type = integration.Type res.Config = integration.Config @@ -61,7 +60,7 @@ func ListIntegrations(client *ent.Client) func(ctx context.Context, req struct{} *res = make([]GetIntegrationResponse, len(integrations)) for i, integration := range integrations { (*res)[i] = GetIntegrationResponse{ - ID: integration.ID.String(), + ID: integration.ID, Name: integration.Name, Type: integration.Type, Config: integration.Config, diff --git a/internal/restapi/v1/integrations/get_test.go b/internal/restapi/v1/integrations/get_test.go index 99ce4f7..ca2ff37 100644 --- a/internal/restapi/v1/integrations/get_test.go +++ b/internal/restapi/v1/integrations/get_test.go @@ -29,7 +29,7 @@ func TestGetIntegration(t *testing.T) { assert.NoError(t, err) // Test case: Valid ID - req := integrations.GetIntegrationRequests{ID: id.String()} + req := integrations.GetIntegrationRequests{ID: id} res := &integrations.GetIntegrationResponse{} handler := integrations.GetIntegration(client) err = handler(context.Background(), req, res) @@ -39,12 +39,13 @@ func TestGetIntegration(t *testing.T) { assert.Equal(t, "linear", res.Type) // Test case: Invalid UUID - req = integrations.GetIntegrationRequests{ID: "invalid-uuid"} + parsedUUID, _ := uuid.Parse("c60c700e-3dd9-4059-8372-f772358c") + req = integrations.GetIntegrationRequests{parsedUUID} err = handler(context.Background(), req, res) assert.Error(t, err) // Test case: Non-existent ID - req = integrations.GetIntegrationRequests{ID: uuid.New().String()} + req = integrations.GetIntegrationRequests{ID: uuid.New()} err = handler(context.Background(), req, res) assert.Error(t, err) diff --git a/internal/restapi/v1/integrations/post.go b/internal/restapi/v1/integrations/post.go index fb17d66..2480aa6 100644 --- a/internal/restapi/v1/integrations/post.go +++ b/internal/restapi/v1/integrations/post.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/google/uuid" "github.com/shinobistack/gokakashi/ent" "github.com/shinobistack/gokakashi/ent/integrations" "github.com/swaggest/usecase/status" @@ -16,8 +17,8 @@ type CreateIntegrationRequest struct { } type CreateIntegrationResponse struct { - ID string `json:"id"` - Status string `json:"status"` + ID uuid.UUID `json:"id"` + Status string `json:"status"` } func CreateIntegration(client *ent.Client) func(ctx context.Context, req CreateIntegrationRequest, res *CreateIntegrationResponse) error { @@ -47,7 +48,7 @@ func CreateIntegration(client *ent.Client) func(ctx context.Context, req CreateI return status.Wrap(fmt.Errorf("failed to create integration: %v", err), status.Internal) } - res.ID = integration.ID.String() + res.ID = integration.ID res.Status = "created" return nil diff --git a/internal/restapi/v1/integrations/post_test.go b/internal/restapi/v1/integrations/post_test.go index 3df0b77..96f6c9b 100644 --- a/internal/restapi/v1/integrations/post_test.go +++ b/internal/restapi/v1/integrations/post_test.go @@ -2,7 +2,6 @@ package integrations_test import ( "context" - "github.com/google/uuid" "github.com/shinobistack/gokakashi/internal/restapi/v1/integrations" "testing" @@ -29,9 +28,7 @@ func TestCreateIntegration_ValidInput(t *testing.T) { assert.Equal(t, "created", res.Status) // Verify database - integrationID, err := uuid.Parse(res.ID) - assert.NoError(t, err) - integration, err := client.Integrations.Get(context.Background(), integrationID) + integration, err := client.Integrations.Get(context.Background(), res.ID) assert.NoError(t, err) assert.Equal(t, "Valid Integration", integration.Name) assert.Equal(t, "linear", integration.Type) @@ -112,9 +109,7 @@ func TestCreateIntegration_EmptyConfig(t *testing.T) { assert.NotEmpty(t, res.ID) // Verify database - integrationID, err := uuid.Parse(res.ID) - assert.NoError(t, err) - integration, err := client.Integrations.Get(context.Background(), integrationID) + integration, err := client.Integrations.Get(context.Background(), res.ID) assert.NoError(t, err) assert.Equal(t, 0, len(integration.Config)) } diff --git a/internal/restapi/v1/integrations/put.go b/internal/restapi/v1/integrations/put.go index 277694f..2f20ebe 100644 --- a/internal/restapi/v1/integrations/put.go +++ b/internal/restapi/v1/integrations/put.go @@ -6,39 +6,38 @@ import ( "fmt" "github.com/google/uuid" "github.com/shinobistack/gokakashi/ent" - "github.com/shinobistack/gokakashi/ent/integrations" "github.com/swaggest/usecase/status" ) type UpdateIntegrationRequest struct { - ID string `path:"id"` + ID uuid.UUID `path:"id"` Name *string `json:"name"` Type *string `json:"type"` Config *map[string]interface{} `json:"config"` } type UpdateIntegrationResponse struct { - ID string `json:"id"` - Status string `json:"status"` + ID uuid.UUID `json:"id"` + Status string `json:"status"` } func UpdateIntegration(client *ent.Client) func(ctx context.Context, req UpdateIntegrationRequest, res *GetIntegrationResponse) error { return func(ctx context.Context, req UpdateIntegrationRequest, res *GetIntegrationResponse) error { - uid, err := uuid.Parse(req.ID) - if err != nil { - return status.Wrap(fmt.Errorf("invalid UUID format: %v", err), status.InvalidArgument) + // Validate ID + if req.ID == uuid.Nil { + return status.Wrap(errors.New("invalid UUID: cannot be nil"), status.InvalidArgument) } // Check if integration exists - exists, err := client.Integrations.Query().Where(integrations.ID(uid)).Exist(ctx) + integrationID, err := client.Integrations.Get(ctx, req.ID) if err != nil { - return status.Wrap(fmt.Errorf("unexpected database error: %v", err), status.Internal) - } - if !exists { - return status.Wrap(errors.New("integration not found"), status.NotFound) + if ent.IsNotFound(err) { + return status.Wrap(errors.New("policy not found"), status.NotFound) + } + return status.Wrap(fmt.Errorf("unexpected error: %v", err), status.Internal) } - update := client.Integrations.UpdateOneID(uid) + update := client.Integrations.UpdateOne(integrationID) if req.Name != nil { update = update.SetName(*req.Name) } @@ -51,7 +50,7 @@ func UpdateIntegration(client *ent.Client) func(ctx context.Context, req UpdateI return status.Wrap(fmt.Errorf("failed to update integration: %v", err), status.Internal) } - res.ID = integration.ID.String() + res.ID = integration.ID res.Name = integration.Name res.Type = integration.Type res.Config = integration.Config diff --git a/internal/restapi/v1/integrations/put_test.go b/internal/restapi/v1/integrations/put_test.go index c56e325..0cbe904 100644 --- a/internal/restapi/v1/integrations/put_test.go +++ b/internal/restapi/v1/integrations/put_test.go @@ -2,6 +2,7 @@ package integrations_test import ( "context" + "fmt" "github.com/shinobistack/gokakashi/internal/restapi/v1/integrations" "testing" @@ -26,7 +27,7 @@ func TestUpdateIntegration(t *testing.T) { // Test case: Valid update req := integrations.UpdateIntegrationRequest{ - ID: id.String(), + ID: id, Name: stringPointer("Updated Integration"), } var res integrations.GetIntegrationResponse @@ -48,16 +49,17 @@ func TestUpdateIntegration(t *testing.T) { func TestUpdateIntegration_InvalidUUID(t *testing.T) { client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") defer client.Close() + parsedUUID, _ := uuid.Parse("c60c700e-3dd9-4059-8372-f77235") req := integrations.UpdateIntegrationRequest{ - ID: "invalid-uuid", + ID: parsedUUID, Name: stringPointer("Invalid Update"), } var res integrations.GetIntegrationResponse handler := integrations.UpdateIntegration(client) err := handler(context.Background(), req, &res) - + fmt.Println(err) assert.Error(t, err) } @@ -66,7 +68,7 @@ func TestUpdateIntegration_NonExistentID(t *testing.T) { defer client.Close() req := integrations.UpdateIntegrationRequest{ - ID: uuid.New().String(), + ID: uuid.New(), Name: stringPointer("Non-existent ID"), } var res integrations.GetIntegrationResponse @@ -93,7 +95,7 @@ func TestUpdateIntegration_NoChanges(t *testing.T) { // Test case: No changes req := integrations.UpdateIntegrationRequest{ - ID: id.String(), + ID: id, } var res integrations.GetIntegrationResponse diff --git a/internal/restapi/v1/integrationtype/get.go b/internal/restapi/v1/integrationtype/get.go new file mode 100644 index 0000000..69371d1 --- /dev/null +++ b/internal/restapi/v1/integrationtype/get.go @@ -0,0 +1,53 @@ +package integrationtype + +import ( + "context" + "errors" + "github.com/shinobistack/gokakashi/ent" + "github.com/swaggest/usecase/status" +) + +type GetIntegrationTypeRequests struct { + ID string `path:"id"` +} + +type GetIntegrationTypeResponse struct { + ID string `json:"id"` + DisplayName string `json:"display_name"` +} + +func GetIntegrationType(client *ent.Client) func(ctx context.Context, req GetIntegrationTypeRequests, res *GetIntegrationTypeResponse) error { + return func(ctx context.Context, req GetIntegrationTypeRequests, res *GetIntegrationTypeResponse) error { + it, err := client.IntegrationType.Get(ctx, req.ID) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("integration type not found"), status.NotFound) + } + return status.Wrap(err, status.Internal) + } + + res.ID = it.ID + res.DisplayName = it.DisplayName + return nil + + } + +} + +func ListIntegrationType(client *ent.Client) func(ctx context.Context, req struct{}, res *[]GetIntegrationTypeResponse) error { + return func(ctx context.Context, req struct{}, res *[]GetIntegrationTypeResponse) error { + its, err := client.IntegrationType.Query().All(ctx) + if err != nil { + return status.Wrap(errors.New("failed to fetch integration types"), status.Internal) + } + + *res = make([]GetIntegrationTypeResponse, len(its)) + for i, it := range its { + (*res)[i] = GetIntegrationTypeResponse{ + ID: it.ID, + DisplayName: it.DisplayName, + } + } + return nil + } +} diff --git a/internal/restapi/v1/integrationtype/get_test.go b/internal/restapi/v1/integrationtype/get_test.go new file mode 100644 index 0000000..83d6c56 --- /dev/null +++ b/internal/restapi/v1/integrationtype/get_test.go @@ -0,0 +1,99 @@ +package integrationtype_test + +import ( + "context" + _ "github.com/mattn/go-sqlite3" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/internal/restapi/v1/integrationtype" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetIntegrationType_ValidID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Seed data + _, _ = client.IntegrationType.Create(). + SetID("linear"). + SetDisplayName("Linear Integration"). + Save(context.Background()) + + // Test case: Valid ID + req := integrationtype.GetIntegrationTypeRequests{ID: "linear"} + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.GetIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, "linear", res.ID) + assert.Equal(t, "Linear Integration", res.DisplayName) +} + +func TestGetIntegrationType_NonExistentID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.GetIntegrationTypeRequests{ID: "nonexistent"} + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.GetIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "integration type not found") +} + +func TestGetIntegrationType_InvalidIDFormat(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.GetIntegrationTypeRequests{ID: "Invalid ID!"} + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.GetIntegrationType(client) + err := handler(context.Background(), req, res) + assert.Error(t, err) + + req = integrationtype.GetIntegrationTypeRequests{ID: "Inv*ID"} + handler = integrationtype.GetIntegrationType(client) + err = handler(context.Background(), req, res) + assert.Error(t, err) +} + +func TestListIntegrationTypes_ValidRequest(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Seed data + _, _ = client.IntegrationType.Create(). + SetID("linear"). + SetDisplayName("Linear Integration"). + Save(context.Background()) + _, _ = client.IntegrationType.Create(). + SetID("jira"). + SetDisplayName("Jira Integration"). + Save(context.Background()) + + req := struct{}{} + var res []integrationtype.GetIntegrationTypeResponse + handler := integrationtype.ListIntegrationType(client) + err := handler(context.Background(), req, &res) + + assert.NoError(t, err) + assert.Len(t, res, 2) +} + +func TestListIntegrations_EmptyDB(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Prepare response + var res []integrationtype.GetIntegrationTypeResponse + + // Execute ListIntegrations handler + handler := integrationtype.ListIntegrationType(client) + err := handler(context.Background(), struct{}{}, &res) + + // Validate response + assert.NoError(t, err) + assert.Len(t, res, 0) +} diff --git a/internal/restapi/v1/integrationtype/post.go b/internal/restapi/v1/integrationtype/post.go new file mode 100644 index 0000000..c556c4c --- /dev/null +++ b/internal/restapi/v1/integrationtype/post.go @@ -0,0 +1,56 @@ +package integrationtype + +import ( + "context" + "errors" + "fmt" + "github.com/shinobistack/gokakashi/ent" + "github.com/swaggest/usecase/status" + "regexp" + "strings" +) + +type CreateIntegrationTypeRequest struct { + ID string `json:"id"` + DisplayName string `json:"display_name"` +} + +func CreateIntegrationType(client *ent.Client) func(ctx context.Context, req CreateIntegrationTypeRequest, res *GetIntegrationTypeResponse) error { + return func(ctx context.Context, req CreateIntegrationTypeRequest, res *GetIntegrationTypeResponse) error { + // Validate fields + if req.ID == "" || req.DisplayName == "" { + return status.Wrap(errors.New("missing required fields: id and/or display_name"), status.InvalidArgument) + } + + if !isValidID(req.ID) { + return status.Wrap(errors.New("invalid id format; must be lowercase, alphanumeric, or dashes"), status.InvalidArgument) // 400 Bad Request + } + + // Create integration type + it, err := client.IntegrationType.Create(). + SetID(req.ID). + SetDisplayName(req.DisplayName). + Save(ctx) + if err != nil { + if ent.IsConstraintError(err) { + return status.Wrap(errors.New("integration type already exists"), status.AlreadyExists) + } + return status.Wrap(fmt.Errorf("failed to create integration type: %v", err), status.Internal) + } + + res.ID = it.ID + res.DisplayName = it.DisplayName + return nil + } +} + +// isValidID validates the ID format: +// - All lowercase letters. +// - Multiple words separated by dashes (`-`). +// - No spaces at the beginning or end. +// - No special characters other than hyphen. +func isValidID(id string) bool { + id = strings.TrimSpace(id) + regex := regexp.MustCompile(`^[a-z]+(-[a-z]+)*$`) + return regex.MatchString(id) +} diff --git a/internal/restapi/v1/integrationtype/post_test.go b/internal/restapi/v1/integrationtype/post_test.go new file mode 100644 index 0000000..3dd6b65 --- /dev/null +++ b/internal/restapi/v1/integrationtype/post_test.go @@ -0,0 +1,84 @@ +package integrationtype_test + +import ( + "context" + "github.com/shinobistack/gokakashi/internal/restapi/v1/integrationtype" + "testing" + + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/stretchr/testify/assert" +) + +func TestCreateIntegrationType_ValidInput(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.CreateIntegrationTypeRequest{ + ID: "linear", + DisplayName: "Linear Integration", + } + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.CreateIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, "linear", res.ID) + assert.Equal(t, "Linear Integration", res.DisplayName) +} + +func TestCreateIntegrationType_MissingFields(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.CreateIntegrationTypeRequest{} + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.CreateIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "missing required fields") +} + +func TestCreateIntegrationType_InvalidIDFormat(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.CreateIntegrationTypeRequest{ + ID: "Invalid ID!", + DisplayName: "Valid Format ", + } + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.CreateIntegrationType(client) + err := handler(context.Background(), req, res) + assert.Error(t, err) + + req = integrationtype.CreateIntegrationTypeRequest{ + ID: "invalid*#", + DisplayName: "Valid Format ", + } + handler = integrationtype.CreateIntegrationType(client) + err = handler(context.Background(), req, res) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid id format") +} + +func TestCreateIntegrationType_DuplicateID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + _, _ = client.IntegrationType.Create(). + SetID("linear"). + SetDisplayName("Linear Integration"). + Save(context.Background()) + + req := integrationtype.CreateIntegrationTypeRequest{ + ID: "linear", + DisplayName: "Linear Integration", + } + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.CreateIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "integration type already exists") +} diff --git a/internal/restapi/v1/integrationtype/put.go b/internal/restapi/v1/integrationtype/put.go new file mode 100644 index 0000000..588beeb --- /dev/null +++ b/internal/restapi/v1/integrationtype/put.go @@ -0,0 +1,39 @@ +package integrationtype + +import ( + "context" + "errors" + "fmt" + "github.com/shinobistack/gokakashi/ent" + "github.com/swaggest/usecase/status" +) + +type UpdateIntegrationTypeRequest struct { + ID string `path:"id"` + DisplayName *string `json:"display_name"` +} + +func UpdateIntegrationType(client *ent.Client) func(ctx context.Context, req UpdateIntegrationTypeRequest, res *GetIntegrationTypeResponse) error { + return func(ctx context.Context, req UpdateIntegrationTypeRequest, res *GetIntegrationTypeResponse) error { + if !isValidID(req.ID) { + return status.Wrap(errors.New("invalid id format"), status.InvalidArgument) // 400 Bad Request + } + + update := client.IntegrationType.UpdateOneID(req.ID) + if req.DisplayName != nil { + update = update.SetDisplayName(*req.DisplayName) + } + + it, err := update.Save(ctx) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("integration type not found"), status.NotFound) + } + return status.Wrap(fmt.Errorf("failed to update integration type: %v", err), status.Internal) + } + + res.ID = it.ID + res.DisplayName = it.DisplayName + return nil + } +} diff --git a/internal/restapi/v1/integrationtype/put_test.go b/internal/restapi/v1/integrationtype/put_test.go new file mode 100644 index 0000000..c497974 --- /dev/null +++ b/internal/restapi/v1/integrationtype/put_test.go @@ -0,0 +1,83 @@ +package integrationtype_test + +import ( + "context" + "github.com/shinobistack/gokakashi/internal/restapi/v1/integrationtype" + "testing" + + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/stretchr/testify/assert" +) + +func TestUpdateIntegrationType_ValidUpdate(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + _, _ = client.IntegrationType.Create(). + SetID("linear"). + SetDisplayName("Linear Integration"). + Save(context.Background()) + + req := integrationtype.UpdateIntegrationTypeRequest{ + ID: "linear", + DisplayName: ptr("Updated Linear Integration"), + } + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.UpdateIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, "linear", res.ID) + assert.Equal(t, "Updated Linear Integration", res.DisplayName) +} + +func TestUpdateIntegrationType_InvalidIDFormat(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.UpdateIntegrationTypeRequest{ + ID: "Invalid ID!", + DisplayName: ptr("Invalid Format"), + } + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.UpdateIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid id format") +} + +func TestUpdateIntegrationType_NonExistentID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.UpdateIntegrationTypeRequest{ + ID: "nonexistent", + DisplayName: ptr("Non-existent Integration"), + } + res := &integrationtype.GetIntegrationTypeResponse{} + handler := integrationtype.UpdateIntegrationType(client) + err := handler(context.Background(), req, res) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "integration type not found") +} + +func TestUpdateIntegrationType_NoFieldsToUpdate(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := integrationtype.UpdateIntegrationTypeRequest{ + ID: "linear", + DisplayName: nil, + } + var res integrationtype.GetIntegrationTypeResponse + handler := integrationtype.UpdateIntegrationType(client) + err := handler(context.Background(), req, &res) + + assert.Error(t, err) +} + +func ptr(value string) *string { + return &value +} diff --git a/internal/restapi/v1/policies/delete.go b/internal/restapi/v1/policies/delete.go new file mode 100644 index 0000000..c23b95b --- /dev/null +++ b/internal/restapi/v1/policies/delete.go @@ -0,0 +1,81 @@ +package policies + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/swaggest/usecase/status" +) + +type DeletePolicyRequest struct { + ID uuid.UUID `path:"id"` +} + +type DeletePolicyResponse struct { + ID uuid.UUID `json:"id"` + Status string `json:"status"` +} + +func DeletePolicy(client *ent.Client) func(ctx context.Context, req DeletePolicyRequest, res *DeletePolicyResponse) error { + return func(ctx context.Context, req DeletePolicyRequest, res *DeletePolicyResponse) error { + // Validate ID + if req.ID == uuid.Nil { + return status.Wrap(errors.New("invalid UUID: cannot be nil"), status.InvalidArgument) + } + + // Start a transaction + tx, err := client.Tx(ctx) + if err != nil { + return status.Wrap(fmt.Errorf("failed to start transaction: %v", err), status.Internal) + } + + // Check if the policy exists + exists, err := tx.Policies.Query().Where(policies.ID(req.ID)).Exist(ctx) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(fmt.Errorf("failed to query policy: %v", err), status.Internal) + } + if !exists { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(errors.New("policy not found"), status.NotFound) + } + + // Delete associated labels + _, err = tx.PolicyLabels.Delete(). + Where(policylabels.PolicyID(req.ID)). + Exec(ctx) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(fmt.Errorf("failed to delete policy labels: %v", err), status.Internal) + } + + // Delete the policy + err = tx.Policies.DeleteOneID(req.ID).Exec(ctx) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(fmt.Errorf("failed to delete policy: %v", err), status.Internal) + } + + // Commit the transaction + if err := tx.Commit(); err != nil { + return status.Wrap(fmt.Errorf("failed to commit transaction: %v", err), status.Internal) + } + + // Build the response + res.ID = req.ID + res.Status = "deleted" + return nil + } +} diff --git a/internal/restapi/v1/policies/delete_test.go b/internal/restapi/v1/policies/delete_test.go new file mode 100644 index 0000000..ba9e73d --- /dev/null +++ b/internal/restapi/v1/policies/delete_test.go @@ -0,0 +1,58 @@ +package policies_test + +import ( + "context" + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "github.com/shinobistack/gokakashi/ent/enttest" + policyent "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policies" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestDeletePolicy_ValidDeletion(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Create a policy + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + req := policies.DeletePolicyRequest{ID: policy.ID} + res := &policies.DeletePolicyResponse{} + err := policies.DeletePolicy(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, policy.ID, res.ID) + + // Verify deletion + exists := client.Policies.Query().Where(policyent.ID(policy.ID)).ExistX(context.Background()) + assert.False(t, exists) +} + +func TestDeletePolicy_InvalidUUID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.DeletePolicyRequest{ID: uuid.Nil} + res := &policies.DeletePolicyResponse{} + err := policies.DeletePolicy(client)(context.Background(), req, res) + + assert.Error(t, err) +} + +func TestDeletePolicy_NonExistentID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.DeletePolicyRequest{ID: uuid.New()} + res := &policies.DeletePolicyResponse{} + err := policies.DeletePolicy(client)(context.Background(), req, res) + + assert.Error(t, err) +} + +// ToDo: TestDeletePolicy_WithDependentRecords diff --git a/internal/restapi/v1/policies/get.go b/internal/restapi/v1/policies/get.go new file mode 100644 index 0000000..f7872d2 --- /dev/null +++ b/internal/restapi/v1/policies/get.go @@ -0,0 +1,105 @@ +package policies + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/swaggest/usecase/status" +) + +type GetPolicyRequests struct { + // ToDO: Fix it to UUID + ID uuid.UUID `path:"id"` +} + +type GetPolicyResponse struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Image schema.Image `json:"image"` + Labels []schema.PolicyLabel `json:"labels"` + Trigger map[string]interface{} `json:"trigger,omitempty"` + Check *schema.Check `json:"check,omitempty"` +} + +type ListPoliciesRequest struct{} + +type ListPoliciesResponse struct { + Policies []GetPolicyResponse `json:"policies"` +} + +func ListPolicies(client *ent.Client) func(ctx context.Context, req ListPoliciesRequest, res *[]GetPolicyResponse) error { + return func(ctx context.Context, req ListPoliciesRequest, res *[]GetPolicyResponse) error { + // Query all policies with their labels + policies, err := client.Policies.Query(). + WithPolicyLabels(). + All(ctx) + if err != nil { + return status.Wrap(errors.New("failed to fetch policies"), status.Internal) + } + + // Build the response + *res = make([]GetPolicyResponse, len(policies)) + for i, policy := range policies { + labels := make([]schema.PolicyLabel, len(policy.Edges.PolicyLabels)) + for j, label := range policy.Edges.PolicyLabels { + labels[j] = schema.PolicyLabel{Key: label.Key, Value: label.Value} + } + + (*res)[i] = GetPolicyResponse{ + ID: policy.ID, + Name: policy.Name, + Image: policy.Image, + Labels: labels, + Trigger: policy.Trigger, + Check: convertToPointer(policy.Check), + } + } + return nil + } +} + +func GetPolicy(client *ent.Client) func(ctx context.Context, req GetPolicyRequests, res *GetPolicyResponse) error { + return func(ctx context.Context, req GetPolicyRequests, res *GetPolicyResponse) error { + // Validate ID should not be nil and should be correct UUID + if req.ID == uuid.Nil { + return status.Wrap(errors.New("invalid UUID: cannot be nil"), status.InvalidArgument) + } + + // Fetch the policy by ID with its labels + policy, err := client.Policies.Query(). + Where(policies.ID(req.ID)). + WithPolicyLabels(). // Include related policy labels + Only(ctx) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("policy not found"), status.NotFound) + } + return status.Wrap(fmt.Errorf("unexpected error: %v", err), status.Internal) + } + + // Map the labels + labels := make([]schema.PolicyLabel, len(policy.Edges.PolicyLabels)) + for i, label := range policy.Edges.PolicyLabels { + labels[i] = schema.PolicyLabel{Key: label.Key, Value: label.Value} + } + + // Build the response + res.ID = policy.ID + res.Name = policy.Name + res.Image = policy.Image + res.Labels = labels + res.Trigger = policy.Trigger + res.Check = convertToPointer(policy.Check) + + return nil + } +} + +// Utility function to convert nullable fields to pointers +func convertToPointer(data schema.Check) *schema.Check { + return &data +} diff --git a/internal/restapi/v1/policies/get_test.go b/internal/restapi/v1/policies/get_test.go new file mode 100644 index 0000000..e2b7e65 --- /dev/null +++ b/internal/restapi/v1/policies/get_test.go @@ -0,0 +1,88 @@ +package policies_test + +import ( + "context" + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policies" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestListPolicies_EmptyDatabase(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.ListPoliciesRequest{} + res := &[]policies.GetPolicyResponse{} + err := policies.ListPolicies(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, 0, len(*res)) +} + +func TestListPolicies(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Create test data + _, err := client.Policies.Create(). + SetName("test-policy1"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + Save(context.Background()) + assert.NoError(t, err) + _, err = client.Policies.Create(). + SetName("test-policy2"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + Save(context.Background()) + assert.NoError(t, err) + + req := policies.ListPoliciesRequest{} + res := &[]policies.GetPolicyResponse{} + err = policies.ListPolicies(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, 2, len(*res)) +} + +func TestGetPolicy_ValidID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Create a policy + policy := client.Policies.Create(). + SetName("test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + req := policies.GetPolicyRequests{ID: policy.ID} + res := &policies.GetPolicyResponse{} + err := policies.GetPolicy(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, policy.Name, res.Name) +} + +func TestGetPolicy_InvalidUUID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.GetPolicyRequests{ID: uuid.Nil} + res := &policies.GetPolicyResponse{} + err := policies.GetPolicy(client)(context.Background(), req, res) + + assert.Error(t, err) +} + +func TestGetPolicy_NonExistentID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.GetPolicyRequests{ID: uuid.New()} + res := &policies.GetPolicyResponse{} + err := policies.GetPolicy(client)(context.Background(), req, res) + + assert.Error(t, err) +} diff --git a/internal/restapi/v1/policies/post.go b/internal/restapi/v1/policies/post.go new file mode 100644 index 0000000..b3d8851 --- /dev/null +++ b/internal/restapi/v1/policies/post.go @@ -0,0 +1,120 @@ +package policies + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policies" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/swaggest/usecase/status" + "regexp" + "strings" +) + +type CreatePolicyRequest struct { + Name string `json:"name"` + Image schema.Image `json:"image"` + Labels []schema.PolicyLabel `json:"labels"` + // Todo: Implement the logic of Type:cron etc + Trigger map[string]interface{} `json:"trigger"` + Check *schema.Check `json:"check"` +} + +type CreatePolicyResponse struct { + ID uuid.UUID `json:"id"` + Status string `json:"status"` +} + +func CreatePolicy(client *ent.Client) func(ctx context.Context, req CreatePolicyRequest, res *CreatePolicyResponse) error { + return func(ctx context.Context, req CreatePolicyRequest, res *CreatePolicyResponse) error { + // Validate image fields + if req.Image.Registry == "" || req.Image.Name == "" || len(req.Image.Tags) == 0 { + return status.Wrap(errors.New("invalid image: missing required fields"), status.InvalidArgument) + } + + if !isValidID(req.Name) { + return status.Wrap(errors.New("invalid id format; must be lowercase, alphanumeric, or dashes"), status.InvalidArgument) + } + + // Check for duplicate name + exists, err := client.Policies.Query(). + Where(policies.Name(req.Name)). + Exist(ctx) + if err != nil { + return status.Wrap(fmt.Errorf("failed to check for duplicate policies name: %v", err), status.Internal) + } + if exists { + return status.Wrap(errors.New("policy with the same name already exists"), status.AlreadyExists) + } + + // Validate trigger + // ToDo: Valid cron for type: cron + + // Validate check fields + // ToDo: Discuss, if check is mentioned then validate the check and accordingly publish the report by default or publish complete report. + // ToDo: Discuss, if check is present then post satisfying the condition execute Notify accordingly + // ToDO: Discuss the report server + // ToDo: check.condition format for evaluation + if req.Check.Condition == "" || len(req.Check.Notify) == 0 { + return status.Wrap(errors.New("invalid check: missing required fields"), status.InvalidArgument) + } + + tx, err := client.Tx(ctx) + if err != nil { + return status.Wrap(err, status.Internal) + } + + // Save the policy + policy, err := tx.Policies.Create(). + SetName(req.Name). + SetImage(req.Image). + SetTrigger(req.Trigger). + SetNillableCheck(req.Check). + Save(ctx) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(err, status.Internal) + } + + // Save policy labels + if len(req.Labels) > 0 { + bulk := make([]*ent.PolicyLabelsCreate, len(req.Labels)) + for i, label := range req.Labels { + bulk[i] = tx.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey(label.Key). + SetValue(label.Value) + } + + if _, err := tx.PolicyLabels.CreateBulk(bulk...).Save(ctx); err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(err, status.Internal) + } + } + + if err := tx.Commit(); err != nil { + return status.Wrap(err, status.Internal) + } + + res.ID = policy.ID + res.Status = "created" + return nil + } +} + +// isValidID validates the ID format: +// - All lowercase letters. +// - Multiple words separated by dashes (`-`). +// - No spaces at the beginning or end. +// - No special characters other than hyphen. +func isValidID(id string) bool { + id = strings.TrimSpace(id) + regex := regexp.MustCompile(`^[a-z]+(-[a-z]+)*$`) + return regex.MatchString(id) +} diff --git a/internal/restapi/v1/policies/post_test.go b/internal/restapi/v1/policies/post_test.go new file mode 100644 index 0000000..5bab017 --- /dev/null +++ b/internal/restapi/v1/policies/post_test.go @@ -0,0 +1,124 @@ +package policies_test + +import ( + "context" + _ "github.com/mattn/go-sqlite3" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policies" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCreatepolicy_InvalidPolicyNameFormat(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.CreatePolicyRequest{ + Name: "tTest-policy", + Image: schema.Image{ + Registry: "example-registry", + Name: "example-name", + Tags: []string{"v1.0"}, + }, + Trigger: map[string]interface{}{"type": "cron", "schedule": "0 0 * * *"}, + Check: &schema.Check{ + Condition: "sev.high > 0", + Notify: []string{"team-slack"}, + }, + } + res := &policies.CreatePolicyResponse{} + err := policies.CreatePolicy(client)(context.Background(), req, res) + assert.Error(t, err) + + req = policies.CreatePolicyRequest{ + Name: "#test policy", + Image: schema.Image{ + Registry: "example-registry", + Name: "example-name", + Tags: []string{"v1.0"}, + }, + Trigger: map[string]interface{}{"type": "cron", "schedule": "0 0 * * *"}, + Check: &schema.Check{ + Condition: "sev.high > 0", + Notify: []string{"team-slack"}, + }, + } + err = policies.CreatePolicy(client)(context.Background(), req, res) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid id format") +} + +func TestCreatePolicy_ValidInput(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.CreatePolicyRequest{ + Name: "test-policy", + Image: schema.Image{ + Registry: "example-registry", + Name: "example-name", + Tags: []string{"v1.0"}, + }, + Trigger: map[string]interface{}{"type": "cron", "schedule": "0 0 * * *"}, + Check: &schema.Check{ + Condition: "sev.high > 0", + Notify: []string{"team-slack"}, + }, + } + res := &policies.CreatePolicyResponse{} + err := policies.CreatePolicy(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.NotNil(t, res.ID) + assert.Equal(t, "created", res.Status) +} + +func TestCreatePolicy_MissingFields(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.CreatePolicyRequest{ + Name: "incomplete-policy", + Image: schema.Image{ + Registry: "", + Name: "example-name", + Tags: []string{}, + }, + Trigger: nil, + Check: nil, + } + res := &policies.CreatePolicyResponse{} + err := policies.CreatePolicy(client)(context.Background(), req, res) + + assert.Error(t, err) +} + +func TestCreatePolicy_DuplicateName(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Seed database + req := policies.CreatePolicyRequest{ + Name: "duplicate-policy", + Image: schema.Image{ + Registry: "example-registry", + Name: "example-name", + Tags: []string{"v1.0"}, + }, + Trigger: map[string]interface{}{"type": "cron", "schedule": "0 0 * * *"}, + Check: &schema.Check{ + Condition: "sev.high > 0", + Notify: []string{"team-slack"}, + }, + } + res := &policies.CreatePolicyResponse{} + handler := policies.CreatePolicy(client) + err := handler(context.Background(), req, res) + assert.NoError(t, err) + + // Test case: Duplicate name + err = handler(context.Background(), req, res) + assert.Error(t, err) + assert.Contains(t, err.Error(), "policy with the same name already exists") +} diff --git a/internal/restapi/v1/policies/put.go b/internal/restapi/v1/policies/put.go new file mode 100644 index 0000000..fb309e7 --- /dev/null +++ b/internal/restapi/v1/policies/put.go @@ -0,0 +1,75 @@ +package policies + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/swaggest/usecase/status" +) + +type UpdatePolicyRequest struct { + ID uuid.UUID `path:"id"` + Name *string `json:"name"` + Image *schema.Image `json:"image"` + Trigger *map[string]interface{} `json:"trigger"` + Check *schema.Check `json:"check"` +} + +type UpdatePolicyResponse struct { + ID uuid.UUID `json:"id"` + Status string `json:"status"` +} + +func UpdatePolicy(client *ent.Client) func(ctx context.Context, req UpdatePolicyRequest, res *GetPolicyResponse) error { + return func(ctx context.Context, req UpdatePolicyRequest, res *GetPolicyResponse) error { + // Validate ID + if req.ID == uuid.Nil { + return status.Wrap(errors.New("invalid UUID: cannot be nil"), status.InvalidArgument) + } + + // Fetch the policy + policy, err := client.Policies.Get(ctx, req.ID) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("policy not found"), status.NotFound) + } + return status.Wrap(fmt.Errorf("unexpected error: %v", err), status.Internal) + } + + // Start updating fields if provided + // ToDo: Allows to update the objects same as present in db. Not required, see whats efficient. + update := client.Policies.UpdateOne(policy) + + if req.Name != nil { + update.SetName(*req.Name) + } + + if req.Image != nil { + update.SetImage(*req.Image) + } + + if req.Trigger != nil { + update.SetTrigger(*req.Trigger) + } + + if req.Check != nil { + update.SetCheck(*req.Check) + } + + // Save updates + updatedPolicy, err := update.Save(ctx) + if err != nil { + return status.Wrap(fmt.Errorf("failed to update policy: %v", err), status.Internal) + } + + res.ID = updatedPolicy.ID + res.Name = policy.Name + res.Image = policy.Image + res.Trigger = policy.Trigger + res.Check = convertToPointer(policy.Check) + return nil + } +} diff --git a/internal/restapi/v1/policies/put_test.go b/internal/restapi/v1/policies/put_test.go new file mode 100644 index 0000000..36e40bd --- /dev/null +++ b/internal/restapi/v1/policies/put_test.go @@ -0,0 +1,88 @@ +package policies_test + +import ( + "context" + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policies" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestUpdatePolicy_ValidUpdate(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + // Create a policy + policy := client.Policies.Create(). + SetName("test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + req := policies.UpdatePolicyRequest{ + ID: policy.ID, + Name: strPtr("updated-test-policy"), + } + var res policies.GetPolicyResponse + err := policies.UpdatePolicy(client)(context.Background(), req, &res) + + assert.NoError(t, err) + assert.Equal(t, policy.ID, res.ID) + + // Verify update + updatedPolicy := client.Policies.GetX(context.Background(), policy.ID) + assert.Equal(t, "updated-test-policy", updatedPolicy.Name) +} + +func TestUpdatePolicy_InvalidUUID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.UpdatePolicyRequest{ + ID: uuid.Nil, + } + var res policies.GetPolicyResponse + err := policies.UpdatePolicy(client)(context.Background(), req, &res) + + assert.Error(t, err) +} + +func TestUpdatePolicy_NonExistentID(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policies.UpdatePolicyRequest{ + ID: uuid.New(), + } + var res policies.GetPolicyResponse + err := policies.UpdatePolicy(client)(context.Background(), req, &res) + + assert.Error(t, err) +} + +// ToDo: implement no changes in policy when no to be changed objects are passed +//func TestUpdatePolicy_NoChanges(t *testing.T) { +// client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") +// defer client.Close() +// +// // Create a policy +// policy := client.Policies.Create(). +// SetName("test-policy"). +// SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). +// SaveX(context.Background()) +// +// req := policies.UpdatePolicyRequest{ +// ID: policy.ID, +// } +// var res policies.GetPolicyResponse +// err := policies.UpdatePolicy(client)(context.Background(), req, &res) +// +// assert.NoError(t, err) +// assert.Equal(t, "No Change Policy", client.Policies.GetX(context.Background(), policy.ID).Name) +//} + +func strPtr(s string) *string { + return &s +} diff --git a/internal/restapi/v1/policylabels/delete.go b/internal/restapi/v1/policylabels/delete.go new file mode 100644 index 0000000..edfedb1 --- /dev/null +++ b/internal/restapi/v1/policylabels/delete.go @@ -0,0 +1,68 @@ +package policylabels + +import ( + "context" + "errors" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/swaggest/usecase/status" +) + +type DeletePolicyLabelRequest struct { + PolicyID uuid.UUID `path:"policy_id"` + Key string `path:"key"` + Value string `query:"value"` +} + +type DeletePolicyLabelResponse struct { + Status string `json:"status"` +} + +func DeletePolicyLabel(client *ent.Client) func(ctx context.Context, req DeletePolicyLabelRequest, res *DeletePolicyLabelResponse) error { + return func(ctx context.Context, req DeletePolicyLabelRequest, res *DeletePolicyLabelResponse) error { + // Validate inputs + if req.PolicyID == uuid.Nil { + return status.Wrap(errors.New("invalid Policy ID: cannot be nil"), status.InvalidArgument) + } + if req.Key == "" { + return status.Wrap(errors.New("invalid Key: cannot be empty"), status.InvalidArgument) + } + if req.Value == "" { + return status.Wrap(errors.New("invalid Value: cannot be empty"), status.InvalidArgument) + } + + // Check if the label exists + exists, err := client.PolicyLabels.Query(). + Where( + policylabels.PolicyID(req.PolicyID), + policylabels.Key(req.Key), + policylabels.Value(req.Value), + ). + Exist(ctx) + + if err != nil { + return status.Wrap(err, status.Internal) + } + + if !exists { + return status.Wrap(errors.New("label not found"), status.NotFound) + } + + // Delete the label + _, err = client.PolicyLabels.Delete(). + Where( + policylabels.PolicyID(req.PolicyID), + policylabels.Key(req.Key), + policylabels.Value(req.Value), + ). + Exec(ctx) + + if err != nil { + return status.Wrap(err, status.Internal) + } + + res.Status = "deleted" + return nil + } +} diff --git a/internal/restapi/v1/policylabels/delete_test.go b/internal/restapi/v1/policylabels/delete_test.go new file mode 100644 index 0000000..07bc330 --- /dev/null +++ b/internal/restapi/v1/policylabels/delete_test.go @@ -0,0 +1,65 @@ +package policylabels_test + +import ( + "context" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policylabels" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestDeletePolicyLabel_Valid(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("team"). + SetValue("gokakashi"). + SaveX(context.Background()) + + req := policylabels.DeletePolicyLabelRequest{ + PolicyID: policy.ID, + Key: "team", + Value: "gokakashi", + } + res := &policylabels.DeletePolicyLabelResponse{} + + err := policylabels.DeletePolicyLabel(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, "deleted", res.Status) +} + +func TestDeletePolicyLabel_NonExistentLabel(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("team"). + SetValue("gokakashi"). + SaveX(context.Background()) + + req := policylabels.DeletePolicyLabelRequest{ + PolicyID: policy.ID, + Key: "dev", + Value: "role", + } + res := &policylabels.DeletePolicyLabelResponse{} + + err := policylabels.DeletePolicyLabel(client)(context.Background(), req, res) + + assert.Error(t, err) +} diff --git a/internal/restapi/v1/policylabels/get.go b/internal/restapi/v1/policylabels/get.go new file mode 100644 index 0000000..10a0e7f --- /dev/null +++ b/internal/restapi/v1/policylabels/get.go @@ -0,0 +1,86 @@ +package policylabels + +import ( + "context" + "errors" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/swaggest/usecase/status" +) + +type ListPolicyLabelsRequest struct { + PolicyID uuid.UUID `path:"policy_id"` + Keys []string `query:"key"` +} + +type PolicyLabel struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type ListPolicyLabelsResponse struct { + Labels []PolicyLabel `json:"labels"` +} + +type GetPolicyLabelRequest struct { + PolicyID uuid.UUID `path:"policy_id"` + Key string `path:"key"` +} + +type GetPolicyLabelResponse struct { + Key string `json:"key"` + Value string `json:"value"` +} + +func ListPolicyLabels(client *ent.Client) func(ctx context.Context, req ListPolicyLabelsRequest, res *ListPolicyLabelsResponse) error { + return func(ctx context.Context, req ListPolicyLabelsRequest, res *ListPolicyLabelsResponse) error { + // Validate inputs + if req.PolicyID == uuid.Nil { + return status.Wrap(errors.New("invalid Policy ID"), status.InvalidArgument) + } + + query := client.PolicyLabels.Query().Where(policylabels.PolicyID(req.PolicyID)) + + // Filter by keys if provided + if len(req.Keys) > 0 { + query = query.Where(policylabels.KeyIn(req.Keys...)) + } + + labels, err := query.All(ctx) + if err != nil { + return status.Wrap(err, status.Internal) + } + + // Build the response + res.Labels = make([]PolicyLabel, len(labels)) + for i, label := range labels { + res.Labels[i] = PolicyLabel{Key: label.Key, Value: label.Value} + } + return nil + } +} + +func GetPolicyLabel(client *ent.Client) func(ctx context.Context, req GetPolicyLabelRequest, res *GetPolicyLabelResponse) error { + return func(ctx context.Context, req GetPolicyLabelRequest, res *GetPolicyLabelResponse) error { + // Validate inputs + if req.PolicyID == uuid.Nil || req.Key == "" { + return status.Wrap(errors.New("invalid Policy ID or Key"), status.InvalidArgument) + } + + // Query the label + label, err := client.PolicyLabels.Query(). + Where(policylabels.PolicyID(req.PolicyID), policylabels.Key(req.Key)). + Only(ctx) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("label not found"), status.NotFound) + } + return status.Wrap(err, status.Internal) + } + + res.Key = label.Key + res.Value = label.Value + return nil + } +} diff --git a/internal/restapi/v1/policylabels/get_test.go b/internal/restapi/v1/policylabels/get_test.go new file mode 100644 index 0000000..9ce90f5 --- /dev/null +++ b/internal/restapi/v1/policylabels/get_test.go @@ -0,0 +1,106 @@ +package policylabels_test + +import ( + "context" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policylabels" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestListPolicyLabels_Valid(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("env"). + SetValue("prod"). + SaveX(context.Background()) + + req := policylabels.ListPolicyLabelsRequest{PolicyID: policy.ID} + res := &policylabels.ListPolicyLabelsResponse{} + + err := policylabels.ListPolicyLabels(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Len(t, res.Labels, 1) + assert.Equal(t, "env", res.Labels[0].Key) + assert.Equal(t, "prod", res.Labels[0].Value) +} + +func TestListPolicyLabels_NoLabels(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + req := policylabels.ListPolicyLabelsRequest{PolicyID: policy.ID} + res := &policylabels.ListPolicyLabelsResponse{} + + err := policylabels.ListPolicyLabels(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Empty(t, res.Labels) +} + +func TestGetPolicyLabel_SpecificLabel(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("env"). + SetValue("prod"). + SaveX(context.Background()) + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("team"). + SetValue("gokakashi"). + SaveX(context.Background()) + + req := policylabels.GetPolicyLabelRequest{PolicyID: policy.ID, Key: "team"} + res := &policylabels.GetPolicyLabelResponse{} + + err := policylabels.GetPolicyLabel(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, "team", res.Key) + assert.Equal(t, "gokakashi", res.Value) + +} + +func TestGetPolicyLabel_NonExistentLabel(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("team"). + SetValue("gokakashi"). + SaveX(context.Background()) + + req := policylabels.GetPolicyLabelRequest{PolicyID: policy.ID, Key: "env"} + res := &policylabels.GetPolicyLabelResponse{} + + err := policylabels.GetPolicyLabel(client)(context.Background(), req, res) + + assert.Error(t, err) +} diff --git a/internal/restapi/v1/policylabels/post.go b/internal/restapi/v1/policylabels/post.go new file mode 100644 index 0000000..4ee5954 --- /dev/null +++ b/internal/restapi/v1/policylabels/post.go @@ -0,0 +1,74 @@ +package policylabels + +import ( + "context" + "errors" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/swaggest/usecase/status" +) + +type CreatePolicyLabelRequest struct { + PolicyID uuid.UUID `path:"policy_id"` + Key string `json:"key"` + Value string `json:"value"` +} + +type CreatePolicyLabelResponse struct { + ID uuid.UUID `json:"policy_id"` + Labels []PolicyLabel `json:"labels"` +} + +// ToDO: When extra fields are passed? +func CreatePolicyLabel(client *ent.Client) func(ctx context.Context, req CreatePolicyLabelRequest, res *CreatePolicyLabelResponse) error { + return func(ctx context.Context, req CreatePolicyLabelRequest, res *CreatePolicyLabelResponse) error { + // Validate inputs + if req.PolicyID == uuid.Nil { + return status.Wrap(errors.New("invalid Policy ID"), status.InvalidArgument) + } + if req.Key == "" || req.Value == "" { + return status.Wrap(errors.New("key and value must not be empty"), status.InvalidArgument) + } + + // Ensure the policy exists + _, err := client.Policies.Get(ctx, req.PolicyID) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("policy not found"), status.NotFound) + } + return status.Wrap(err, status.Internal) + } + // Validate of if label exists + // Query the label + exists, _ := client.PolicyLabels.Query(). + Where(policylabels.PolicyID(req.PolicyID), policylabels.Key(req.Key)). + Exist(ctx) + if err != nil { + return status.Wrap(err, status.Internal) + } + if exists { + return status.Wrap(errors.New("label with the same key already exists"), status.AlreadyExists) + } + + // Create the policy label + // ToDo: append the key + label, err := client.PolicyLabels.Create(). + SetPolicyID(req.PolicyID). + SetKey(req.Key). + SetValue(req.Value). + Save(ctx) + if err != nil { + return status.Wrap(err, status.Internal) + } + + res.ID = label.PolicyID + res.Labels = []PolicyLabel{ + { + Key: label.Key, + Value: label.Value, + }, + } + return nil + } +} diff --git a/internal/restapi/v1/policylabels/post_test.go b/internal/restapi/v1/policylabels/post_test.go new file mode 100644 index 0000000..a296ea4 --- /dev/null +++ b/internal/restapi/v1/policylabels/post_test.go @@ -0,0 +1,76 @@ +package policylabels_test + +import ( + "context" + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policylabels" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCreatePolicyLabel_Valid(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + req := policylabels.CreatePolicyLabelRequest{ + PolicyID: policy.ID, + Key: "env", + Value: "prod", + } + res := &policylabels.CreatePolicyLabelResponse{} + + err := policylabels.CreatePolicyLabel(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, req.PolicyID, res.ID) + assert.Len(t, res.Labels, 1) + assert.Equal(t, req.Key, res.Labels[0].Key) + assert.Equal(t, req.Value, res.Labels[0].Value) + +} + +func TestCreatePolicyLabel_Invalid(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + req := policylabels.CreatePolicyLabelRequest{PolicyID: uuid.Nil, Key: "", Value: ""} + res := &policylabels.CreatePolicyLabelResponse{} + + err := policylabels.CreatePolicyLabel(client)(context.Background(), req, res) + + assert.Error(t, err) +} + +func TestCreatePolicyLabel_Duplicate(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("env"). + SetValue("prod"). + SaveX(context.Background()) + + req := policylabels.CreatePolicyLabelRequest{ + PolicyID: policy.ID, + Key: "env", + Value: "prod", + } + res := &policylabels.CreatePolicyLabelResponse{} + + err := policylabels.CreatePolicyLabel(client)(context.Background(), req, res) + + assert.Error(t, err) +} diff --git a/internal/restapi/v1/policylabels/put.go b/internal/restapi/v1/policylabels/put.go new file mode 100644 index 0000000..18c5c88 --- /dev/null +++ b/internal/restapi/v1/policylabels/put.go @@ -0,0 +1,117 @@ +package policylabels + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/shinobistack/gokakashi/ent" + "github.com/shinobistack/gokakashi/ent/policylabels" + "github.com/swaggest/usecase/status" +) + +type UpdatePolicyLabelsRequest struct { + PolicyID uuid.UUID `path:"policy_id"` + Labels []PolicyLabel `json:"labels"` + Key *string `json:"key"` + Value *string `json:"value"` +} + +type UpdatePolicyLabelsResponse struct { + Labels []PolicyLabel `json:"labels"` +} + +func UpdatePolicyLabels(client *ent.Client) func(ctx context.Context, req UpdatePolicyLabelsRequest, res *UpdatePolicyLabelsResponse) error { + return func(ctx context.Context, req UpdatePolicyLabelsRequest, res *UpdatePolicyLabelsResponse) error { + // Validate PolicyID + if req.PolicyID == uuid.Nil { + return status.Wrap(errors.New("invalid Policy ID"), status.InvalidArgument) + } + + if req.Key != nil && req.Value != nil { + // Update a specific label + _, err := client.PolicyLabels.Update(). + Where(policylabels.PolicyID(req.PolicyID), policylabels.Key(*req.Key)). + SetValue(*req.Value). + Save(ctx) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("label not found"), status.NotFound) + } + return status.Wrap(err, status.Internal) + } + + updatedLabel, err := client.PolicyLabels.Query(). + Where(policylabels.PolicyID(req.PolicyID), policylabels.Key(*req.Key)). + Only(ctx) + if err != nil { + if ent.IsNotFound(err) { + return status.Wrap(errors.New("label not found after update"), status.NotFound) + } + return status.Wrap(err, status.Internal) + } + + // Return the updated label + res.Labels = []PolicyLabel{ + { + Key: updatedLabel.Key, + Value: updatedLabel.Value, + }, + } + return nil + } + + if req.Labels != nil { + // Replace all labels + tx, err := client.Tx(ctx) + if err != nil { + return status.Wrap(err, status.Internal) + } + + // Delete existing labels + _, err = tx.PolicyLabels.Delete(). + Where(policylabels.PolicyID(req.PolicyID)). + Exec(ctx) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(err, status.Internal) + } + + // Add new labels + bulk := make([]*ent.PolicyLabelsCreate, len(req.Labels)) + for i, label := range req.Labels { + bulk[i] = tx.PolicyLabels.Create(). + SetPolicyID(req.PolicyID). + SetKey(label.Key). + SetValue(label.Value) + } + + createdLabels, err := tx.PolicyLabels.CreateBulk(bulk...).Save(ctx) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + fmt.Printf("rollback failed: %v\n", rollbackErr) + } + return status.Wrap(err, status.Internal) + } + + err = tx.Commit() + if err != nil { + return status.Wrap(err, status.Internal) + } + + // Build the response + res.Labels = make([]PolicyLabel, len(createdLabels)) + for i, label := range createdLabels { + res.Labels[i] = PolicyLabel{ + Key: label.Key, + Value: label.Value, + } + } + return nil + } + + return status.Wrap(errors.New("invalid request: either key-value or labels must be provided"), status.InvalidArgument) + } +} diff --git a/internal/restapi/v1/policylabels/put_test.go b/internal/restapi/v1/policylabels/put_test.go new file mode 100644 index 0000000..3517c40 --- /dev/null +++ b/internal/restapi/v1/policylabels/put_test.go @@ -0,0 +1,82 @@ +package policylabels_test + +import ( + "context" + "github.com/shinobistack/gokakashi/ent/enttest" + "github.com/shinobistack/gokakashi/ent/schema" + "github.com/shinobistack/gokakashi/internal/restapi/v1/policylabels" + "github.com/stretchr/testify/assert" + "testing" +) + +// Todo: Certainly can better this logic to check for single label update +func TestUpdatePolicyLabel_SingleLabel(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("team"). + SetValue("gokakashi"). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("env"). + SetValue("prod"). + SaveX(context.Background()) + + req := policylabels.UpdatePolicyLabelsRequest{ + PolicyID: policy.ID, + Key: StringPointer("env"), + Value: StringPointer("dev"), + } + res := &policylabels.UpdatePolicyLabelsResponse{} + + err := policylabels.UpdatePolicyLabels(client)(context.Background(), req, res) + assert.NoError(t, err) + assert.Equal(t, "dev", res.Labels[0].Value) +} + +func TestUpdatePolicyLabel_AllLabels(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + policy := client.Policies.Create(). + SetName("to-be-deleted-test-policy"). + SetImage(schema.Image{Registry: "example-registry", Name: "example-name", Tags: []string{"v1.0"}}). + SaveX(context.Background()) + + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("env"). + SetValue("prod"). + SaveX(context.Background()) + client.PolicyLabels.Create(). + SetPolicyID(policy.ID). + SetKey("team"). + SetValue("gokakashi"). + SaveX(context.Background()) + + req := policylabels.UpdatePolicyLabelsRequest{ + PolicyID: policy.ID, + Labels: []policylabels.PolicyLabel{ + {Key: "updated", Value: "all"}, + }, + } + res := &policylabels.UpdatePolicyLabelsResponse{} + + err := policylabels.UpdatePolicyLabels(client)(context.Background(), req, res) + + assert.NoError(t, err) + assert.Equal(t, "all", res.Labels[0].Value) +} + +func StringPointer(s string) *string { + return &s +} diff --git a/internal/restapi/v1/server.go b/internal/restapi/v1/server.go index a66c862..4e5f2a3 100644 --- a/internal/restapi/v1/server.go +++ b/internal/restapi/v1/server.go @@ -9,6 +9,9 @@ import ( "github.com/shinobistack/gokakashi/ent" "github.com/shinobistack/gokakashi/internal/restapi/server/middleware" integrations1 "github.com/shinobistack/gokakashi/internal/restapi/v1/integrations" + integrationtype1 "github.com/shinobistack/gokakashi/internal/restapi/v1/integrationtype" + policies1 "github.com/shinobistack/gokakashi/internal/restapi/v1/policies" + policylabels1 "github.com/shinobistack/gokakashi/internal/restapi/v1/policylabels" "github.com/swaggest/openapi-go/openapi31" "github.com/swaggest/rest/web" swg "github.com/swaggest/swgui" @@ -49,6 +52,23 @@ func (srv *Server) Service() *web.Service { apiV1.Post("/integrations", usecase.NewInteractor(integrations1.CreateIntegration(srv.DB))) apiV1.Put("/integrations/{id}", usecase.NewInteractor(integrations1.UpdateIntegration(srv.DB))) + apiV1.Get("/integrationtypes", usecase.NewInteractor(integrationtype1.ListIntegrationType(srv.DB))) + apiV1.Get("/integrationtypes/{id}", usecase.NewInteractor(integrationtype1.GetIntegrationType(srv.DB))) + apiV1.Post("/integrationtypes", usecase.NewInteractor(integrationtype1.CreateIntegrationType(srv.DB))) + apiV1.Put("/integrationtypes/{id}", usecase.NewInteractor(integrationtype1.UpdateIntegrationType(srv.DB))) + + apiV1.Post("/policies", usecase.NewInteractor(policies1.CreatePolicy(srv.DB))) + apiV1.Get("/policies", usecase.NewInteractor(policies1.ListPolicies(srv.DB))) + apiV1.Get("/policies/{id}", usecase.NewInteractor(policies1.GetPolicy(srv.DB))) + apiV1.Put("/policies/{id}", usecase.NewInteractor(policies1.UpdatePolicy(srv.DB))) + apiV1.Delete("/policies/{id}", usecase.NewInteractor(policies1.DeletePolicy(srv.DB))) + + apiV1.Post("/policies/{policy_id}/labels", usecase.NewInteractor(policylabels1.CreatePolicyLabel(srv.DB))) + apiV1.Get("/policies/{policy_id}/labels", usecase.NewInteractor(policylabels1.ListPolicyLabels(srv.DB))) + apiV1.Get("/policies/{policy_id}/labels/{key}", usecase.NewInteractor(policylabels1.GetPolicyLabel(srv.DB))) + apiV1.Put("/policies/{policy_id}/labels", usecase.NewInteractor(policylabels1.UpdatePolicyLabels(srv.DB))) + apiV1.Delete("/policies/{policy_id}/labels/{key}", usecase.NewInteractor(policylabels1.DeletePolicyLabel(srv.DB))) + s.Mount("/api/v1/openapi.json", specHandler(apiV1.OpenAPICollector.SpecSchema().(*openapi31.Spec))) s.Mount("/api/v1", apiV1)