mirror of
https://github.com/harness/drone.git
synced 2025-05-05 23:42:57 +00:00
feat: [CDE-718]: Adding support for cde-gateways. (#3696)
* feat: [CDE-718]: Adding existence checks in cde-gateway related migration scripts. * feat: [CDE-718]: Updating the report stats service. * feat: [CDE-718]: Adding cde-gateway related tables and services.
This commit is contained in:
parent
952a6d852f
commit
7c42a497e5
@ -29,6 +29,7 @@ func NewService(
|
||||
templateStore store.InfraProviderTemplateStore,
|
||||
factory infraprovider.Factory,
|
||||
spaceFinder refcache.SpaceFinder,
|
||||
gatewayStore store.CDEGatewayStore,
|
||||
) *Service {
|
||||
return &Service{
|
||||
tx: tx,
|
||||
@ -38,6 +39,7 @@ func NewService(
|
||||
infraProviderFactory: factory,
|
||||
spaceFinder: spaceFinder,
|
||||
gitspaceConfigStore: gitspaceConfigStore,
|
||||
gatewayStore: gatewayStore,
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,4 +51,5 @@ type Service struct {
|
||||
infraProviderTemplateStore store.InfraProviderTemplateStore
|
||||
infraProviderFactory infraprovider.Factory
|
||||
spaceFinder refcache.SpaceFinder
|
||||
gatewayStore store.CDEGatewayStore
|
||||
}
|
||||
|
70
app/services/infraprovider/list_gateways.go
Normal file
70
app/services/infraprovider/list_gateways.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) ListGateways(ctx context.Context, filter *types.CDEGatewayFilter) ([]*types.CDEGateway, error) {
|
||||
if filter == nil || len(filter.InfraProviderConfigIDs) == 0 {
|
||||
return nil, fmt.Errorf("cde-gateway filter is required")
|
||||
}
|
||||
|
||||
if filter.HealthReportValidityInMins == 0 {
|
||||
filter.HealthReportValidityInMins = 5
|
||||
}
|
||||
|
||||
gateways, err := c.gatewayStore.List(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list gateways: %w", err)
|
||||
}
|
||||
|
||||
infraProviderConfigMap := make(map[int64]string)
|
||||
for _, gateway := range gateways {
|
||||
if _, ok := infraProviderConfigMap[gateway.InfraProviderConfigID]; !ok {
|
||||
infraProviderConfig, err := c.infraProviderConfigStore.Find(ctx, gateway.InfraProviderConfigID, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infra provider config %d while listing gateways: %w",
|
||||
gateway.InfraProviderConfigID, err)
|
||||
}
|
||||
infraProviderConfigMap[gateway.InfraProviderConfigID] = infraProviderConfig.Identifier
|
||||
}
|
||||
gateway.InfraProviderConfigIdentifier = infraProviderConfigMap[gateway.InfraProviderConfigID]
|
||||
|
||||
spaceCore, err := c.spaceFinder.FindByID(ctx, gateway.SpaceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find space %d while listing gateways: %w", gateway.SpaceID, err)
|
||||
}
|
||||
|
||||
gateway.SpacePath = spaceCore.Path
|
||||
|
||||
if gateway.Updated < time.Now().Add(-time.Duration(filter.HealthReportValidityInMins)*time.Minute).UnixMilli() {
|
||||
gateway.Health = types.GatewayHealthUnhealthy
|
||||
}
|
||||
|
||||
if gateway.Health != types.GatewayHealthHealthy || gateway.EnvoyHealth != types.GatewayHealthHealthy {
|
||||
gateway.OverallHealth = types.GatewayHealthUnhealthy
|
||||
} else {
|
||||
gateway.OverallHealth = types.GatewayHealthHealthy
|
||||
}
|
||||
}
|
||||
|
||||
return gateways, nil
|
||||
}
|
47
app/services/infraprovider/report_stats.go
Normal file
47
app/services/infraprovider/report_stats.go
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) ReportStats(
|
||||
ctx context.Context,
|
||||
spaceCore *types.SpaceCore,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
in *types.CDEGatewayStats,
|
||||
) error {
|
||||
gateway := types.CDEGateway{
|
||||
InfraProviderConfigID: infraProviderConfig.ID,
|
||||
InfraProviderConfigIdentifier: infraProviderConfig.Identifier,
|
||||
SpaceID: spaceCore.ID,
|
||||
SpacePath: spaceCore.Path,
|
||||
}
|
||||
gateway.Name = in.Name
|
||||
gateway.GroupName = in.GroupName
|
||||
gateway.Region = in.Region
|
||||
gateway.Zone = in.Zone
|
||||
gateway.Version = in.Version
|
||||
gateway.Health = in.Health
|
||||
gateway.EnvoyHealth = in.EnvoyHealth
|
||||
gateway.Created = time.Now().UnixMilli()
|
||||
gateway.Updated = gateway.Created
|
||||
|
||||
return c.gatewayStore.Upsert(ctx, &gateway)
|
||||
}
|
@ -35,7 +35,8 @@ func ProvideInfraProvider(
|
||||
templateStore store.InfraProviderTemplateStore,
|
||||
infraProviderFactory infraprovider.Factory,
|
||||
spaceFinder refcache.SpaceFinder,
|
||||
gatewayStore store.CDEGatewayStore,
|
||||
) *Service {
|
||||
return NewService(tx, gitspaceConfigStore, resourceStore, configStore, templateStore, infraProviderFactory,
|
||||
spaceFinder)
|
||||
spaceFinder, gatewayStore)
|
||||
}
|
||||
|
@ -1352,4 +1352,9 @@ type (
|
||||
end int64,
|
||||
) ([]types.UsageMetric, error)
|
||||
}
|
||||
|
||||
CDEGatewayStore interface {
|
||||
Upsert(ctx context.Context, in *types.CDEGateway) error
|
||||
List(ctx context.Context, filter *types.CDEGatewayFilter) ([]*types.CDEGateway, error)
|
||||
}
|
||||
)
|
||||
|
179
app/store/database/cde_gateway.go
Normal file
179
app/store/database/cde_gateway.go
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/store/database"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var _ store.CDEGatewayStore = (*CDEGatewayStore)(nil)
|
||||
|
||||
const (
|
||||
cdeGatewayIDColumn = `cgate_id`
|
||||
cdeGatewayInsertColumns = `
|
||||
cgate_name,
|
||||
cgate_group_name,
|
||||
cgate_space_id,
|
||||
cgate_infra_provider_config_id,
|
||||
cgate_region,
|
||||
cgate_zone,
|
||||
cgate_version,
|
||||
cgate_health,
|
||||
cgate_envoy_health,
|
||||
cgate_created,
|
||||
cgate_updated
|
||||
`
|
||||
cdeGatewaySelectColumns = cdeGatewayIDColumn + "," + cdeGatewayInsertColumns
|
||||
cdeGatewayTable = `cde_gateways`
|
||||
)
|
||||
|
||||
// NewCDEGatewayStore returns a new CDEGatewayStore.
|
||||
func NewCDEGatewayStore(db *sqlx.DB) *CDEGatewayStore {
|
||||
return &CDEGatewayStore{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// CDEGatewayStore implements store.CDEGatewayStore backed by a relational database.
|
||||
type CDEGatewayStore struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func (c *CDEGatewayStore) Upsert(ctx context.Context, in *types.CDEGateway) error {
|
||||
stmt := database.Builder.
|
||||
Insert(cdeGatewayTable).
|
||||
Columns(cdeGatewayInsertColumns).
|
||||
Values(
|
||||
in.Name,
|
||||
in.GroupName,
|
||||
in.SpaceID,
|
||||
in.InfraProviderConfigID,
|
||||
in.Region,
|
||||
in.Zone,
|
||||
in.Version,
|
||||
in.Health,
|
||||
in.EnvoyHealth,
|
||||
in.Created,
|
||||
in.Updated).
|
||||
Suffix(`
|
||||
ON CONFLICT (cgate_space_id, cgate_infra_provider_config_id, cgate_region, cgate_group_name, cgate_name)
|
||||
DO UPDATE
|
||||
SET
|
||||
cgate_health = EXCLUDED.cgate_health,
|
||||
cgate_envoy_health = EXCLUDED.cgate_envoy_health,
|
||||
cgate_updated = EXCLUDED.cgate_updated,
|
||||
cgate_zone = EXCLUDED.cgate_zone,
|
||||
cgate_version = EXCLUDED.cgate_version`)
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
|
||||
}
|
||||
db := dbtx.GetAccessor(ctx, c.db)
|
||||
if _, err = db.ExecContext(ctx, sql, args...); err != nil {
|
||||
return database.ProcessSQLErrorf(
|
||||
ctx, err, "cde gateway upsert create query failed for %s", in.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CDEGatewayStore) List(ctx context.Context, filter *types.CDEGatewayFilter) ([]*types.CDEGateway, error) {
|
||||
stmt := database.Builder.
|
||||
Select(cdeGatewaySelectColumns).
|
||||
From(cdeGatewayTable)
|
||||
|
||||
if filter != nil && len(filter.InfraProviderConfigIDs) > 0 {
|
||||
stmt = stmt.Where(squirrel.Eq{"cgate_infra_provider_config_id": filter.InfraProviderConfigIDs})
|
||||
}
|
||||
|
||||
if filter != nil && filter.Health == types.GatewayHealthHealthy {
|
||||
stmt = stmt.Where(squirrel.Eq{"cgate_health": filter.Health}).
|
||||
Where(squirrel.Eq{"cgate_envoy_health": filter.Health}).
|
||||
Where(squirrel.Gt{"cgate_updated": time.Now().Add(
|
||||
-time.Duration(filter.HealthReportValidityInMins) * time.Minute).UnixMilli()})
|
||||
}
|
||||
|
||||
if filter != nil && filter.Health == types.GatewayHealthUnhealthy {
|
||||
stmt = stmt.Where(
|
||||
squirrel.Or{
|
||||
squirrel.LtOrEq{"cgate_updated": time.Now().Add(
|
||||
time.Minute * -time.Duration(filter.HealthReportValidityInMins)).UnixMilli()},
|
||||
squirrel.Eq{"cgate_envoy_health": filter.Health},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
|
||||
}
|
||||
|
||||
db := dbtx.GetAccessor(ctx, c.db)
|
||||
dst := new([]*cdeGateway)
|
||||
if err := db.SelectContext(ctx, dst, sql, args...); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to list cde gatways")
|
||||
}
|
||||
|
||||
return entitiesToDTOs(*dst), nil
|
||||
}
|
||||
|
||||
type cdeGateway struct {
|
||||
ID int64 `db:"cgate_id"`
|
||||
Name string `db:"cgate_name"`
|
||||
GroupName string `db:"cgate_group_name"`
|
||||
SpaceID int64 `db:"cgate_space_id"`
|
||||
InfraProviderConfigID int64 `db:"cgate_infra_provider_config_id"`
|
||||
Region string `db:"cgate_region"`
|
||||
Zone string `db:"cgate_zone"`
|
||||
Version string `db:"cgate_version"`
|
||||
Health string `db:"cgate_health"`
|
||||
EnvoyHealth string `db:"cgate_envoy_health"`
|
||||
Created int64 `db:"cgate_created"`
|
||||
Updated int64 `db:"cgate_updated"`
|
||||
}
|
||||
|
||||
func entitiesToDTOs(entities []*cdeGateway) []*types.CDEGateway {
|
||||
var dtos []*types.CDEGateway
|
||||
for _, entity := range entities {
|
||||
dtos = append(dtos, entityToDTO(*entity))
|
||||
}
|
||||
return dtos
|
||||
}
|
||||
|
||||
func entityToDTO(entity cdeGateway) *types.CDEGateway {
|
||||
dto := &types.CDEGateway{}
|
||||
dto.Name = entity.Name
|
||||
dto.GroupName = entity.GroupName
|
||||
dto.SpaceID = entity.SpaceID
|
||||
dto.InfraProviderConfigID = entity.InfraProviderConfigID
|
||||
dto.Region = entity.Region
|
||||
dto.Zone = entity.Zone
|
||||
dto.Version = entity.Version
|
||||
dto.Health = entity.Health
|
||||
dto.EnvoyHealth = entity.EnvoyHealth
|
||||
dto.Created = entity.Created
|
||||
dto.Updated = entity.Updated
|
||||
return dto
|
||||
}
|
@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS cde_gateways;
|
@ -0,0 +1,26 @@
|
||||
CREATE TABLE IF NOT EXISTS cde_gateways
|
||||
(
|
||||
cgate_id BIGSERIAL PRIMARY KEY,
|
||||
cgate_name TEXT NOT NULL,
|
||||
cgate_group_name TEXT NOT NULL,
|
||||
cgate_region TEXT NOT NULL,
|
||||
cgate_zone TEXT NOT NULL,
|
||||
cgate_version TEXT NOT NULL,
|
||||
cgate_health TEXT NOT NULL,
|
||||
cgate_space_id BIGINT NOT NULL,
|
||||
cgate_infra_provider_config_id BIGINT NOT NULL,
|
||||
cgate_envoy_health TEXT NOT NULL,
|
||||
cgate_created BIGINT NOT NULL,
|
||||
cgate_updated BIGINT NOT NULL,
|
||||
CONSTRAINT fk_cgate_space_id FOREIGN KEY (cgate_space_id)
|
||||
REFERENCES spaces (space_id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION,
|
||||
CONSTRAINT fk_cgate_infra_provider_config_id FOREIGN KEY (cgate_infra_provider_config_id)
|
||||
REFERENCES infra_provider_configs (ipconf_id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS cde_gateways_space_id_infra_config_id_region_group_name_name
|
||||
ON cde_gateways (cgate_space_id, cgate_infra_provider_config_id, cgate_region, cgate_group_name, cgate_name);
|
@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS cde_gateways;
|
@ -0,0 +1,26 @@
|
||||
CREATE TABLE IF NOT EXISTS cde_gateways
|
||||
(
|
||||
cgate_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
cgate_name TEXT NOT NULL,
|
||||
cgate_group_name TEXT NOT NULL,
|
||||
cgate_region TEXT NOT NULL,
|
||||
cgate_zone TEXT NOT NULL,
|
||||
cgate_version TEXT NOT NULL,
|
||||
cgate_health TEXT NOT NULL,
|
||||
cgate_space_id BIGINT NOT NULL,
|
||||
cgate_infra_provider_config_id BIGINT NOT NULL,
|
||||
cgate_envoy_health TEXT NOT NULL,
|
||||
cgate_created BIGINT NOT NULL,
|
||||
cgate_updated BIGINT NOT NULL,
|
||||
CONSTRAINT fk_cgate_space_id FOREIGN KEY (cgate_space_id)
|
||||
REFERENCES spaces (space_id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION,
|
||||
CONSTRAINT fk_cgate_infra_provider_config_id FOREIGN KEY (cgate_infra_provider_config_id)
|
||||
REFERENCES infra_provider_configs (ipconf_id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS cde_gateways_space_id_infra_config_id_region_group_name_name
|
||||
ON cde_gateways (cgate_space_id, cgate_infra_provider_config_id, cgate_region, cgate_group_name, cgate_name);
|
@ -74,6 +74,7 @@ var WireSet = wire.NewSet(
|
||||
ProvideInfraProviderTemplateStore,
|
||||
ProvideInfraProvisionedStore,
|
||||
ProvideUsageMetricStore,
|
||||
ProvideCDEGatewayStore,
|
||||
)
|
||||
|
||||
// migrator is helper function to set up the database by performing automated
|
||||
@ -355,3 +356,7 @@ func ProvideInfraProvisionedStore(db *sqlx.DB) store.InfraProvisionedStore {
|
||||
func ProvideUsageMetricStore(db *sqlx.DB) store.UsageMetricStore {
|
||||
return NewUsageMetricsStore(db)
|
||||
}
|
||||
|
||||
func ProvideCDEGatewayStore(db *sqlx.DB) store.CDEGatewayStore {
|
||||
return NewCDEGatewayStore(db)
|
||||
}
|
||||
|
@ -347,7 +347,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
||||
}
|
||||
dockerProvider := infraprovider.ProvideDockerProvider(dockerConfig, dockerClientFactory, reporter4)
|
||||
factory := infraprovider.ProvideFactory(dockerProvider)
|
||||
infraproviderService := infraprovider2.ProvideInfraProvider(transactor, gitspaceConfigStore, infraProviderResourceStore, infraProviderConfigStore, infraProviderTemplateStore, factory, spaceFinder)
|
||||
cdeGatewayStore := database.ProvideCDEGatewayStore(db)
|
||||
infraproviderService := infraprovider2.ProvideInfraProvider(transactor, gitspaceConfigStore, infraProviderResourceStore, infraProviderConfigStore, infraProviderTemplateStore, factory, spaceFinder, cdeGatewayStore)
|
||||
gitnessSCM := scm.ProvideGitnessSCM(repoStore, repoFinder, gitInterface, tokenStore, principalStore, provider)
|
||||
genericSCM := scm.ProvideGenericSCM()
|
||||
scmFactory := scm.ProvideFactory(gitnessSCM, genericSCM)
|
||||
|
45
types/cde_gateway.go
Normal file
45
types/cde_gateway.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
const GatewayHealthHealthy = "healthy"
|
||||
const GatewayHealthUnhealthy = "unhealthy"
|
||||
|
||||
type CDEGatewayStats struct {
|
||||
Name string `json:"name"`
|
||||
GroupName string `json:"group_name"`
|
||||
Region string `json:"region"`
|
||||
Zone string `json:"zone"`
|
||||
Health string `json:"health"`
|
||||
EnvoyHealth string `json:"envoy_health"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type CDEGateway struct {
|
||||
CDEGatewayStats
|
||||
SpaceID int64 `json:"space_id,omitempty"`
|
||||
SpacePath string `json:"space_path"`
|
||||
InfraProviderConfigID int64 `json:"infra_provider_config_id,omitempty"`
|
||||
InfraProviderConfigIdentifier string `json:"infra_provider_config_identifier"`
|
||||
OverallHealth string `json:"overall_health,omitempty"`
|
||||
Created int64 `json:"created"`
|
||||
Updated int64 `json:"updated"`
|
||||
}
|
||||
|
||||
type CDEGatewayFilter struct {
|
||||
Health string `json:"health,omitempty"`
|
||||
HealthReportValidityInMins int `json:"health_report_validity_in_mins,omitempty"`
|
||||
InfraProviderConfigIDs []int64 `json:"infra_provider_config_ids,omitempty"`
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user