From 9b3982b532a148d44079c986563a19676b70ee3d Mon Sep 17 00:00:00 2001 From: Stefan Benz Date: Tue, 2 Feb 2021 13:06:48 +0100 Subject: [PATCH 1/8] feat(cloudflare): add functionality to include loadbalancers on cloudflare --- .../kinds/networking/legacycf/adapt.go | 2 + .../kinds/networking/legacycf/app/app.go | 70 +++++- .../networking/legacycf/app/dnsrecords.go | 14 +- .../networking/legacycf/app/loadbalancers.go | 213 ++++++++++++++++++ .../kinds/networking/legacycf/app/pools.go | 123 ++++++++++ .../legacycf/cloudflare/cloudflare.go | 1 + .../legacycf/cloudflare/loadbalancer.go | 156 +++++++++++++ .../networking/legacycf/cloudflare/pool.go | 137 +++++++++++ .../networking/legacycf/config/external.go | 47 +++- .../networking/legacycf/config/internal.go | 13 +- .../networking/legacycf/legacyadapter.go | 14 +- .../networking/kinds/networking/networking.go | 3 +- .../operator/networking/kinds/orb/adapt.go | 4 +- internal/secret/operators/operators.go | 2 +- internal/start/networking.go | 2 +- 15 files changed, 770 insertions(+), 31 deletions(-) create mode 100644 internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go create mode 100644 internal/operator/networking/kinds/networking/legacycf/app/pools.go create mode 100644 internal/operator/networking/kinds/networking/legacycf/cloudflare/loadbalancer.go create mode 100644 internal/operator/networking/kinds/networking/legacycf/cloudflare/pool.go diff --git a/internal/operator/networking/kinds/networking/legacycf/adapt.go b/internal/operator/networking/kinds/networking/legacycf/adapt.go index 3c2c063a4..0611ae47c 100644 --- a/internal/operator/networking/kinds/networking/legacycf/adapt.go +++ b/internal/operator/networking/kinds/networking/legacycf/adapt.go @@ -14,6 +14,7 @@ import ( func AdaptFunc( namespace string, + ID string, operatorLabels *labels.Operator, ) opcore.AdaptFunc { return func( @@ -34,6 +35,7 @@ func AdaptFunc( return nil, nil, nil, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind + desiredKind.Spec.ID = ID if !monitor.IsVerbose() && desiredKind.Spec.Verbose { internalMonitor.Verbose() diff --git a/internal/operator/networking/kinds/networking/legacycf/app/app.go b/internal/operator/networking/kinds/networking/legacycf/app/app.go index 59e1ecadc..034f74045 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/app.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/app.go @@ -38,10 +38,76 @@ func (a *App) AddInternalPrefix(desc string) string { return strings.Join([]string{a.internalPrefix, desc}, " ") } -func (a *App) Ensure(k8sClient kubernetes.ClientInt, namespace string, domain string, subdomains []*config.Subdomain, rules []*config.Rule, originCALabels *labels.Name) error { +func (a *App) Ensure( + id string, + k8sClient kubernetes.ClientInt, + namespace string, + domain string, + subdomains []*config.Subdomain, + rules []*config.Rule, + originCALabels *labels.Name, + clusterID string, + region string, + lbs bool, + floatingIP string, +) error { firewallRulesInt := make([]*cloudflare.FirewallRule, 0) filtersInt := make([]*cloudflare.Filter, 0) recordsInt := make([]*cloudflare.DNSRecord, 0) + poolsInt := make([]*cloudflare.LoadBalancerPool, 0) + lbsInt := make([]*cloudflare.LoadBalancer, 0) + + if lbs { + originsInt := []*cloudflare.LoadBalancerOrigin{{ + Name: getPoolName(domain, region, clusterID), + Address: floatingIP, + Enabled: true, + }} + + poolsInt = append(poolsInt, &cloudflare.LoadBalancerPool{ + Name: getPoolName(domain, region, clusterID), + Description: id, + Enabled: lbs, + Origins: originsInt, + }) + } + + destroyPools, err := a.EnsureLoadBalancerPools(id, poolsInt) + if err != nil { + return err + } + + if lbs { + //ids get filled in the EnsureLoadBalancerPools-function + poolNames := []string{} + if poolsInt != nil { + for _, poolInt := range poolsInt { + poolNames = append(poolNames, poolInt.ID) + } + } + + enabled := true + lbsInt = append(lbsInt, &cloudflare.LoadBalancer{ + Name: config.GetLBName(domain), + DefaultPools: poolNames, + //the first pool is fallback pool for now + FallbackPool: poolNames[0], + Enabled: &enabled, + Proxied: true, + SteeringPolicy: "Random", + }) + } + + if err := a.EnsureLoadBalancers(id, clusterID, region, domain, lbsInt); err != nil { + return err + } + + //pools have to be deleted after the reference in the lbs is deleted + if destroyPools() != nil { + if err := destroyPools(); err != nil { + return err + } + } for _, record := range subdomains { @@ -68,7 +134,7 @@ func (a *App) Ensure(k8sClient kubernetes.ClientInt, namespace string, domain st }) } - err := a.EnsureDNSRecords(domain, recordsInt) + err = a.EnsureDNSRecords(domain, recordsInt) if err != nil { return err } diff --git a/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go b/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go index 5cf8da47f..693661466 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go @@ -12,6 +12,13 @@ func (a *App) EnsureDNSRecords(domain string, records []*cloudflare.DNSRecord) e return err } + deleteRecords := getRecordsToDelete(currentRecords, records) + if deleteRecords != nil && len(deleteRecords) > 0 { + if err := a.cloudflare.DeleteDNSRecords(domain, deleteRecords); err != nil { + return err + } + } + createRecords, updateRecords := getRecordsToCreateAndUpdate(domain, currentRecords, records) if createRecords != nil && len(createRecords) > 0 { _, err := a.cloudflare.CreateDNSRecords(domain, createRecords) @@ -26,13 +33,6 @@ func (a *App) EnsureDNSRecords(domain string, records []*cloudflare.DNSRecord) e return err } } - - deleteRecords := getRecordsToDelete(currentRecords, records) - if deleteRecords != nil && len(deleteRecords) > 0 { - if err := a.cloudflare.DeleteDNSRecords(domain, deleteRecords); err != nil { - return err - } - } return nil } diff --git a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go new file mode 100644 index 000000000..d8d433de5 --- /dev/null +++ b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go @@ -0,0 +1,213 @@ +package app + +import ( + "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/cloudflare" + "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/config" +) + +func (a *App) EnsureLoadBalancers(id string, clusterID, region, domain string, lbs []*cloudflare.LoadBalancer) error { + currentLbs, err := a.cloudflare.ListLoadBalancers(domain) + if err != nil { + return err + } + + //only try to manage lbs which have pools in them managed by this operator + filteredCurrentLbs := make([]*cloudflare.LoadBalancer, 0) + for _, currentLb := range currentLbs { + filteredPool := filterSameID(a.cloudflare, currentLb.DefaultPools, id) + if filteredPool != nil && len(filteredPool) > 0 { + filteredCurrentLbs = append(filteredCurrentLbs, currentLb) + } + } + + deleteLbs, updateLbs := getLoadBalancerToDelete(a.cloudflare, id, filteredCurrentLbs, lbs) + if deleteLbs != nil && len(deleteLbs) > 0 { + for _, lb := range deleteLbs { + if err := a.cloudflare.DeleteLoadBalancer(domain, lb); err != nil { + return err + } + } + } + + createLbs := getLoadBalancerToCreate(currentLbs, lbs) + if createLbs != nil && len(createLbs) > 0 { + for _, lb := range createLbs { + _, err := a.cloudflare.CreateLoadBalancer(domain, lb) + if err != nil { + return err + } + } + } + + updateLbs = append(updateLbs, getLoadBalancerToUpdate(a.cloudflare, id, clusterID, region, domain, currentLbs, lbs)...) + if updateLbs != nil && len(updateLbs) > 0 { + for _, lb := range updateLbs { + _, err := a.cloudflare.UpdateLoadBalancer(domain, lb) + if err != nil { + return err + } + } + } + + return nil +} + +func getLoadBalancerToDelete( + cf *cloudflare.Cloudflare, + id string, + currentLbs []*cloudflare.LoadBalancer, + lbs []*cloudflare.LoadBalancer, +) ( + []string, + []*cloudflare.LoadBalancer, +) { + deleteLbs := make([]string, 0) + updateLbs := make([]*cloudflare.LoadBalancer, 0) + + for _, currentLb := range currentLbs { + found := false + if lbs != nil { + for _, lb := range lbs { + if currentLb.Name == lb.Name { + found = true + } + } + } + + hasPoolWithOtherID := hasPoolsWithOtherID(cf, id, currentLb) + //delete lbs with no pools managed by another operator + if !found && !hasPoolWithOtherID { + deleteLbs = append(deleteLbs, currentLb.ID) + //otherwise just delete the pool and let the lb stand + } else if !found && hasPoolWithOtherID { + updateLb := currentLb + updateLb.DefaultPools = filterNotSameID(cf, currentLb.DefaultPools, id) + updateLb.FallbackPool = updateLb.DefaultPools[0] + + updateLbs = append(updateLbs, updateLb) + } + } + + return deleteLbs, updateLbs +} + +func getLoadBalancerToCreate(currentLbs []*cloudflare.LoadBalancer, lbs []*cloudflare.LoadBalancer) []*cloudflare.LoadBalancer { + createLbs := make([]*cloudflare.LoadBalancer, 0) + + if lbs != nil { + for _, lb := range lbs { + found := false + for _, currentLb := range currentLbs { + if currentLb.Name == lb.Name { + found = true + break + } + } + if found == false { + createLbs = append(createLbs, lb) + } + } + } + + return createLbs +} + +func getLoadBalancerToUpdate( + cf *cloudflare.Cloudflare, + id, + clusterID, + region, + domain string, + currentLbs []*cloudflare.LoadBalancer, + lbs []*cloudflare.LoadBalancer, +) []*cloudflare.LoadBalancer { + updateLbs := make([]*cloudflare.LoadBalancer, 0) + + poolName := getPoolName(domain, region, clusterID) + + if lbs != nil { + for _, lb := range lbs { + for _, currentLb := range currentLbs { + if currentLb.Name == config.GetLBName(domain) { + containedRegion := false + containedDefault := false + for _, currentPool := range currentLb.DefaultPools { + if currentPool == poolName { + containedDefault = true + } + } + for currentRegion, currentPools := range currentLb.RegionPools { + if currentRegion == region { + for _, currentPool := range currentPools { + if currentPool == poolName { + containedRegion = true + } + } + } + } + + //only update the lb if a pool has to be added + if !containedDefault || !containedRegion { + lb.ID = currentLb.ID + // add already entered pools for update + //all pools which are maintained by operators with other ids + lb.DefaultPools = append(lb.DefaultPools, filterNotSameID(cf, currentLb.DefaultPools, id)...) + + // combine the defined region pools for update + for currentRegion, currentPools := range currentLb.RegionPools { + regionSlice, found := lb.RegionPools[currentRegion] + if found { + lb.DefaultPools = append(lb.DefaultPools, filterNotSameID(cf, currentLb.DefaultPools, id)...) + + regionSlice = append(regionSlice, currentPools...) + } else { + defPool := []string{} + defPool = append(defPool, filterNotSameID(cf, currentPools, id)...) + lb.RegionPools[currentRegion] = defPool + } + } + updateLbs = append(updateLbs, lb) + } + } + } + } + } + + return updateLbs +} + +func hasPoolsWithOtherID(cf *cloudflare.Cloudflare, id string, lb *cloudflare.LoadBalancer) bool { + filteredPools := filterNotSameID(cf, lb.DefaultPools, id) + if filteredPools != nil && len(filteredPools) > 0 { + return true + } + return false +} + +func filterSameID(cf *cloudflare.Cloudflare, pools []string, id string) []string { + ret := make([]string, 0) + for _, poolID := range pools { + poolDet, err := cf.GetLoadBalancerPoolDetails(poolID) + if err != nil { + return nil + } + if poolDet.Description == id { + ret = append(ret, poolID) + } + } + return ret +} + +func filterNotSameID(cf *cloudflare.Cloudflare, pools []string, id string) []string { + ret := make([]string, 0) + for _, poolID := range pools { + poolDet, err := cf.GetLoadBalancerPoolDetails(poolID) + if err != nil { + return nil + } + if poolDet.Description != id { + ret = append(ret, poolID) + } + } + return ret +} diff --git a/internal/operator/networking/kinds/networking/legacycf/app/pools.go b/internal/operator/networking/kinds/networking/legacycf/app/pools.go new file mode 100644 index 000000000..b2b57715e --- /dev/null +++ b/internal/operator/networking/kinds/networking/legacycf/app/pools.go @@ -0,0 +1,123 @@ +package app + +import ( + "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/cloudflare" + "reflect" + "strings" +) + +func getPoolName(domain, region, clusterID string) string { + return strings.Join([]string{clusterID, region, strings.ReplaceAll(domain, ".", "-")}, "-") +} + +func (a *App) EnsureLoadBalancerPools(id string, pools []*cloudflare.LoadBalancerPool) (func() error, error) { + destroy := func() error { + return nil + } + currentPools, err := a.cloudflare.ListLoadBalancerPools() + if err != nil { + return nil, err + } + + filteredCurrentPools := make([]*cloudflare.LoadBalancerPool, 0) + for _, currentPool := range currentPools { + if currentPool.Description == id { + filteredCurrentPools = append(filteredCurrentPools, currentPool) + } + } + + deletePools := getLoadBalancerPoolsToDelete(filteredCurrentPools, pools) + if deletePools != nil && len(deletePools) > 0 { + destroy = func() error { + for _, pool := range deletePools { + if err := a.cloudflare.DeleteLoadBalancerPools(pool); err != nil { + return err + } + } + return nil + } + } + + createPools := getLoadBalancerPoolsToCreate(currentPools, pools) + if createPools != nil && len(createPools) > 0 { + for _, pool := range createPools { + created, err := a.cloudflare.CreateLoadBalancerPools(pool) + if err != nil { + return nil, err + } + pool.ID = created.ID + } + } + + updatePools := getLoadBalancerPoolsToUpdate(currentPools, pools) + if updatePools != nil && len(updatePools) > 0 { + for _, pool := range updatePools { + updated, err := a.cloudflare.UpdateLoadBalancerPools(pool) + if err != nil { + return nil, err + } + pool.ID = updated.ID + } + } + + return destroy, nil +} + +func getLoadBalancerPoolsToDelete(currentPools []*cloudflare.LoadBalancerPool, pools []*cloudflare.LoadBalancerPool) []string { + deletePools := make([]string, 0) + for _, currentPool := range currentPools { + found := false + if pools != nil { + for _, pool := range pools { + if currentPool.Name == pool.Name { + found = true + } + } + } + + if !found { + deletePools = append(deletePools, currentPool.ID) + } + } + + return deletePools +} + +func getLoadBalancerPoolsToCreate(currentPools []*cloudflare.LoadBalancerPool, pools []*cloudflare.LoadBalancerPool) []*cloudflare.LoadBalancerPool { + createPools := make([]*cloudflare.LoadBalancerPool, 0) + + if pools != nil { + for _, pool := range pools { + found := false + for _, currentPool := range currentPools { + if currentPool.Name == pool.Name { + found = true + break + } + } + if found == false { + createPools = append(createPools, pool) + } + } + } + + return createPools +} + +func getLoadBalancerPoolsToUpdate(currentPools []*cloudflare.LoadBalancerPool, pools []*cloudflare.LoadBalancerPool) []*cloudflare.LoadBalancerPool { + updatePools := make([]*cloudflare.LoadBalancerPool, 0) + + if pools != nil { + for _, pool := range pools { + for _, currentPool := range currentPools { + if currentPool.Name == pool.Name && + !reflect.DeepEqual(currentPool, pool) { + pool.ID = currentPool.ID + updatePools = append(updatePools, pool) + } + } + } + } + + return updatePools +} diff --git a/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go b/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go index d6de59953..d63dca4d3 100644 --- a/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go +++ b/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go @@ -20,6 +20,7 @@ func New(user string, key string, userServiceKey string) (*Cloudflare, error) { } api.APIUserServiceKey = userServiceKey + api.AccountID = "86ed4d09664b2b395548c37339c7f179" return &Cloudflare{ api: api, diff --git a/internal/operator/networking/kinds/networking/legacycf/cloudflare/loadbalancer.go b/internal/operator/networking/kinds/networking/legacycf/cloudflare/loadbalancer.go new file mode 100644 index 000000000..207993ad0 --- /dev/null +++ b/internal/operator/networking/kinds/networking/legacycf/cloudflare/loadbalancer.go @@ -0,0 +1,156 @@ +package cloudflare + +import ( + "github.com/cloudflare/cloudflare-go" + "time" +) + +type LoadBalancer struct { + ID string `json:"id,omitempty"` + CreatedOn *time.Time `json:"created_on,omitempty"` + ModifiedOn *time.Time `json:"modified_on,omitempty"` + Description string `json:"description"` + Name string `json:"name"` + TTL int `json:"ttl,omitempty"` + FallbackPool string `json:"fallback_pool"` + DefaultPools []string `json:"default_pools"` + RegionPools map[string][]string `json:"region_pools"` + PopPools map[string][]string `json:"pop_pools"` + Proxied bool `json:"proxied"` + Enabled *bool `json:"enabled,omitempty"` + Persistence string `json:"session_affinity,omitempty"` + PersistenceTTL int `json:"session_affinity_ttl,omitempty"` + SessionAffinityAttributes *SessionAffinityAttributes `json:"session_affinity_attributes,omitempty"` + + // SteeringPolicy controls pool selection logic. + // "off" select pools in DefaultPools order + // "geo" select pools based on RegionPools/PopPools + // "dynamic_latency" select pools based on RTT (requires health checks) + // "random" selects pools in a random order + // "" maps to "geo" if RegionPools or PopPools have entries otherwise "off" + SteeringPolicy string `json:"steering_policy,omitempty"` +} + +// SessionAffinityAttributes represents the fields used to set attributes in a load balancer session affinity cookie. +type SessionAffinityAttributes struct { + SameSite string `json:"samesite,omitempty"` + Secure string `json:"secure,omitempty"` +} + +func (c *Cloudflare) CreateLoadBalancer(domain string, lb *LoadBalancer) (*LoadBalancer, error) { + id, err := c.api.ZoneIDByName(domain) + if err != nil { + return nil, err + } + + createdLb, err := c.api.CreateLoadBalancer(id, internalLbToLb(lb)) + + if err != nil { + return nil, err + } + + return lbToInternalLb(createdLb), err +} + +func (c *Cloudflare) UpdateLoadBalancer(domain string, lb *LoadBalancer) (*LoadBalancer, error) { + id, err := c.api.ZoneIDByName(domain) + if err != nil { + return nil, err + } + + updated, err := c.api.ModifyLoadBalancer(id, internalLbToLb(lb)) + if err != nil { + return nil, err + } + + return lbToInternalLb(updated), err +} + +func (c *Cloudflare) DeleteLoadBalancer(domain string, lbID string) error { + id, err := c.api.ZoneIDByName(domain) + if err != nil { + return err + } + + return c.api.DeleteLoadBalancer(id, lbID) +} + +func (c *Cloudflare) ListLoadBalancers(domain string) ([]*LoadBalancer, error) { + id, err := c.api.ZoneIDByName(domain) + if err != nil { + return nil, err + } + + lbs, err := c.api.ListLoadBalancers(id) + if err != nil { + return nil, err + } + return lbsToInternalLbs(lbs), nil +} + +func lbsToInternalLbs(lbs []cloudflare.LoadBalancer) []*LoadBalancer { + ret := make([]*LoadBalancer, 0) + for _, lb := range lbs { + ret = append(ret, lbToInternalLb(lb)) + } + return ret +} + +func lbToInternalLb(lb cloudflare.LoadBalancer) *LoadBalancer { + return &LoadBalancer{ + ID: lb.ID, + CreatedOn: lb.CreatedOn, + ModifiedOn: lb.ModifiedOn, + Description: lb.Description, + Name: lb.Name, + TTL: lb.TTL, + FallbackPool: lb.FallbackPool, + DefaultPools: lb.DefaultPools, + RegionPools: lb.RegionPools, + PopPools: lb.PopPools, + Proxied: lb.Proxied, + Enabled: lb.Enabled, + Persistence: lb.Persistence, + PersistenceTTL: lb.PersistenceTTL, + SessionAffinityAttributes: saaToInternalSaa(lb.SessionAffinityAttributes), + SteeringPolicy: lb.SteeringPolicy, + } +} + +func saaToInternalSaa(saa *cloudflare.SessionAffinityAttributes) *SessionAffinityAttributes { + return &SessionAffinityAttributes{ + SameSite: saa.SameSite, + Secure: saa.Secure, + } +} + +func internalLbToLb(lb *LoadBalancer) cloudflare.LoadBalancer { + return cloudflare.LoadBalancer{ + ID: lb.ID, + CreatedOn: lb.CreatedOn, + ModifiedOn: lb.ModifiedOn, + Description: lb.Description, + Name: lb.Name, + TTL: lb.TTL, + FallbackPool: lb.FallbackPool, + DefaultPools: lb.DefaultPools, + RegionPools: lb.RegionPools, + PopPools: lb.PopPools, + Proxied: lb.Proxied, + Enabled: lb.Enabled, + Persistence: lb.Persistence, + PersistenceTTL: lb.PersistenceTTL, + SessionAffinityAttributes: internalSaaToSaa(lb.SessionAffinityAttributes), + SteeringPolicy: lb.SteeringPolicy, + } +} + +func internalSaaToSaa(saa *SessionAffinityAttributes) *cloudflare.SessionAffinityAttributes { + if saa == nil { + return nil + } + return &cloudflare.SessionAffinityAttributes{ + SameSite: saa.SameSite, + Secure: saa.Secure, + } +} diff --git a/internal/operator/networking/kinds/networking/legacycf/cloudflare/pool.go b/internal/operator/networking/kinds/networking/legacycf/cloudflare/pool.go new file mode 100644 index 000000000..a2d07b579 --- /dev/null +++ b/internal/operator/networking/kinds/networking/legacycf/cloudflare/pool.go @@ -0,0 +1,137 @@ +package cloudflare + +import ( + "github.com/cloudflare/cloudflare-go" + "time" +) + +type LoadBalancerPool struct { + ID string `json:"id,omitempty"` + CreatedOn *time.Time `json:"created_on,omitempty"` + ModifiedOn *time.Time `json:"modified_on,omitempty"` + Description string `json:"description"` + Name string `json:"name"` + Enabled bool `json:"enabled"` + MinimumOrigins int `json:"minimum_origins,omitempty"` + Monitor string `json:"monitor,omitempty"` + Origins []*LoadBalancerOrigin `json:"origins"` + NotificationEmail string `json:"notification_email,omitempty"` + + // CheckRegions defines the geographic region(s) from where to run health-checks from - e.g. "WNAM", "WEU", "SAF", "SAM". + // Providing a null/empty value means "all regions", which may not be available to all plan types. + CheckRegions []string `json:"check_regions"` +} + +type LoadBalancerOrigin struct { + Name string `json:"name"` + Address string `json:"address"` + Enabled bool `json:"enabled"` + Weight float64 `json:"weight"` +} + +func (c *Cloudflare) GetLoadBalancerPoolDetails(ID string) (*LoadBalancerPool, error) { + pool, err := c.api.LoadBalancerPoolDetails(ID) + + if err != nil { + return nil, err + } + + return poolToInternalPool(pool), err +} + +func (c *Cloudflare) CreateLoadBalancerPools(pool *LoadBalancerPool) (*LoadBalancerPool, error) { + createdPool, err := c.api.CreateLoadBalancerPool(internalPoolToPool(pool)) + + if err != nil { + return nil, err + } + + return poolToInternalPool(createdPool), err +} + +func (c *Cloudflare) UpdateLoadBalancerPools(pool *LoadBalancerPool) (*LoadBalancerPool, error) { + updatedPool, err := c.api.ModifyLoadBalancerPool(internalPoolToPool(pool)) + if err != nil { + return nil, err + } + + return poolToInternalPool(updatedPool), err +} + +func (c *Cloudflare) DeleteLoadBalancerPools(poolID string) error { + return c.api.DeleteLoadBalancerPool(poolID) +} + +func (c *Cloudflare) ListLoadBalancerPools() ([]*LoadBalancerPool, error) { + pools, err := c.api.ListLoadBalancerPools() + if err != nil { + return nil, err + } + return poolsToInternalPools(pools), nil +} + +func poolsToInternalPools(pools []cloudflare.LoadBalancerPool) []*LoadBalancerPool { + retPools := make([]*LoadBalancerPool, 0) + for _, pool := range pools { + retPools = append(retPools, poolToInternalPool(pool)) + } + return retPools +} + +func poolToInternalPool(pool cloudflare.LoadBalancerPool) *LoadBalancerPool { + return &LoadBalancerPool{ + ID: pool.ID, + CreatedOn: pool.CreatedOn, + ModifiedOn: pool.ModifiedOn, + Description: pool.Description, + Name: pool.Name, + Enabled: pool.Enabled, + MinimumOrigins: pool.MinimumOrigins, + Monitor: pool.Monitor, + Origins: originsToInternalOrigins(pool.Origins), + NotificationEmail: pool.NotificationEmail, + CheckRegions: pool.CheckRegions, + } +} + +func originsToInternalOrigins(origins []cloudflare.LoadBalancerOrigin) []*LoadBalancerOrigin { + internalOrigins := make([]*LoadBalancerOrigin, 0) + for _, origin := range origins { + internalOrigins = append(internalOrigins, &LoadBalancerOrigin{ + Name: origin.Name, + Address: origin.Address, + Enabled: origin.Enabled, + Weight: origin.Weight, + }) + } + return internalOrigins +} + +func internalPoolToPool(pool *LoadBalancerPool) cloudflare.LoadBalancerPool { + return cloudflare.LoadBalancerPool{ + ID: pool.ID, + CreatedOn: pool.CreatedOn, + ModifiedOn: pool.ModifiedOn, + Description: pool.Description, + Name: pool.Name, + Enabled: pool.Enabled, + MinimumOrigins: pool.MinimumOrigins, + Monitor: pool.Monitor, + Origins: internalOriginsToOrigins(pool.Origins), + NotificationEmail: pool.NotificationEmail, + CheckRegions: pool.CheckRegions, + } +} + +func internalOriginsToOrigins(internalOrigins []*LoadBalancerOrigin) []cloudflare.LoadBalancerOrigin { + origins := make([]cloudflare.LoadBalancerOrigin, 0) + for _, origin := range internalOrigins { + origins = append(origins, cloudflare.LoadBalancerOrigin{ + Name: origin.Name, + Address: origin.Address, + Enabled: origin.Enabled, + Weight: origin.Weight, + }) + } + return origins +} diff --git a/internal/operator/networking/kinds/networking/legacycf/config/external.go b/internal/operator/networking/kinds/networking/legacycf/config/external.go index eec1b39e4..c85d259d5 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/external.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/external.go @@ -2,6 +2,7 @@ package config import ( "errors" + "strings" core2 "github.com/caos/orbos/internal/operator/core" "github.com/caos/orbos/internal/operator/networking/kinds/networking/core" @@ -11,8 +12,12 @@ import ( ) type ExternalConfig struct { + ID string Verbose bool Domain string + ClusterID string `yaml:"clusterid"` + Region string `yaml:"region"` + LoadBalancer bool `yaml:"loadbalancer"` IP orbiter.IPAddress Rules []*Rule Groups []*Group `yaml:"groups"` @@ -38,6 +43,7 @@ func (i *ExternalConfig) IsZero() bool { func (e *ExternalConfig) Internal(namespace string, apiLabels *labels.API) (*InternalConfig, *current) { dom, curr := e.internalDomain() return &InternalConfig{ + ID: e.ID, Domains: []*InternalDomain{dom}, Groups: e.Groups, Credentials: e.Credentials, @@ -59,22 +65,36 @@ func (e *ExternalConfig) Validate() error { } func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { - + subdomains := []*Subdomain{} // TODO: Remove - subdomains := []*Subdomain{ - subdomain("accounts", e.IP), - subdomain("api", e.IP), - subdomain("console", e.IP), - subdomain("issuer", e.IP), + if e.LoadBalancer { + lbName := GetLBName(e.Domain) + subdomains = append(subdomains, + subdomain("accounts", lbName, "CNAME"), + subdomain("api", lbName, "CNAME"), + subdomain("console", lbName, "CNAME"), + subdomain("issuer", lbName, "CNAME"), + ) + } else { + subdomains = append(subdomains, + subdomain("accounts", string(e.IP), "A"), + subdomain("api", string(e.IP), "A"), + subdomain("console", string(e.IP), "A"), + subdomain("issuer", string(e.IP), "A"), + ) } for _, sd := range e.AdditionalDNS { subdomains = append(subdomains, sd) } return &InternalDomain{ - Domain: e.Domain, - Subdomains: subdomains, - Rules: e.Rules, + FloatingIP: string(e.IP), + ClusterID: e.ClusterID, + Region: e.Region, + Domain: e.Domain, + Subdomains: subdomains, + Rules: e.Rules, + LoadBalancer: e.LoadBalancer, }, ¤t{ domain: e.Domain, @@ -85,14 +105,17 @@ func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { tlsCertName: "tls-cert-wildcard", } } +func GetLBName(domain string) string { + return strings.Join([]string{"lb", domain}, ".") +} -func subdomain(subdomain string, ip orbiter.IPAddress) *Subdomain { +func subdomain(subdomain string, target string, ty string) *Subdomain { return &Subdomain{ Subdomain: subdomain, - IP: string(ip), + IP: target, Proxied: true, TTL: 0, - Type: "A", + Type: ty, } } diff --git a/internal/operator/networking/kinds/networking/legacycf/config/internal.go b/internal/operator/networking/kinds/networking/legacycf/config/internal.go index 77e01972a..6225b954e 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/internal.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/internal.go @@ -6,6 +6,7 @@ import ( ) type InternalConfig struct { + ID string Domains []*InternalDomain `yaml:"domains"` Groups []*Group `yaml:"groups"` Credentials *Credentials @@ -36,10 +37,14 @@ type Group struct { } type InternalDomain struct { - Domain string `yaml:"domain"` - Origin *Origin `yaml:"origin"` - Subdomains []*Subdomain `yaml:"subdomains"` - Rules []*Rule `yaml:"rules"` + FloatingIP string + ClusterID string `yaml:"clusterid"` + Region string `yaml:"region"` + Domain string `yaml:"domain"` + Origin *Origin `yaml:"origin"` + Subdomains []*Subdomain `yaml:"subdomains"` + Rules []*Rule `yaml:"rules"` + LoadBalancer bool `yaml:"loadbalancer"` } type Origin struct { diff --git a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go index 064848070..34681dd63 100644 --- a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go +++ b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go @@ -36,7 +36,19 @@ func adaptFunc( caSecretLabels := labels.MustForName(labels.MustForComponent(cfg.Labels, "cloudflare"), cfg.OriginCASecretName) for _, domain := range cfg.Domains { - err = apps.Ensure(k8sClient, cfg.Namespace, domain.Domain, domain.Subdomains, domain.Rules, caSecretLabels) + err = apps.Ensure( + cfg.ID, + k8sClient, + cfg.Namespace, + domain.Domain, + domain.Subdomains, + domain.Rules, + caSecretLabels, + domain.ClusterID, + domain.Region, + domain.LoadBalancer, + domain.FloatingIP, + ) if err != nil { return err } diff --git a/internal/operator/networking/kinds/networking/networking.go b/internal/operator/networking/kinds/networking/networking.go index 2751362af..4d40035eb 100644 --- a/internal/operator/networking/kinds/networking/networking.go +++ b/internal/operator/networking/kinds/networking/networking.go @@ -12,6 +12,7 @@ import ( func GetQueryAndDestroyFuncs( monitor mntr.Monitor, + ID string, operatorLabels *labels.Operator, desiredTree *tree.Tree, currentTree *tree.Tree, @@ -24,7 +25,7 @@ func GetQueryAndDestroyFuncs( ) { switch desiredTree.Common.Kind { case "networking.caos.ch/LegacyCloudflare": - return legacycf.AdaptFunc(namespace, operatorLabels)(monitor, desiredTree, currentTree) + return legacycf.AdaptFunc(namespace, ID, operatorLabels)(monitor, desiredTree, currentTree) default: return nil, nil, nil, errors.Errorf("unknown networking kind %s", desiredTree.Common.Kind) } diff --git a/internal/operator/networking/kinds/orb/adapt.go b/internal/operator/networking/kinds/orb/adapt.go index a85eb7313..4d75b6a4c 100644 --- a/internal/operator/networking/kinds/orb/adapt.go +++ b/internal/operator/networking/kinds/orb/adapt.go @@ -15,7 +15,7 @@ func OperatorSelector() *labels.Selector { return labels.OpenOperatorSelector("ORBOS", "networking.caos.ch") } -func AdaptFunc(binaryVersion *string) core.AdaptFunc { +func AdaptFunc(ID string, binaryVersion *string) core.AdaptFunc { namespaceStr := "caos-zitadel" return func(monitor mntr.Monitor, desiredTree *tree.Tree, currentTree *tree.Tree) (queryFunc core.QueryFunc, destroyFunc core.DestroyFunc, secrets map[string]*secret.Secret, err error) { @@ -38,7 +38,7 @@ func AdaptFunc(binaryVersion *string) core.AdaptFunc { operatorLabels := mustDatabaseOperator(binaryVersion) networkingCurrent := &tree.Tree{} - queryNW, destroyNW, secrets, err := networking.GetQueryAndDestroyFuncs(orbMonitor, operatorLabels, desiredKind.Networking, networkingCurrent, namespaceStr) + queryNW, destroyNW, secrets, err := networking.GetQueryAndDestroyFuncs(orbMonitor, ID, operatorLabels, desiredKind.Networking, networkingCurrent, namespaceStr) if err != nil { return nil, nil, nil, err } diff --git a/internal/secret/operators/operators.go b/internal/secret/operators/operators.go index 9a29c6abe..0517782e3 100644 --- a/internal/secret/operators/operators.go +++ b/internal/secret/operators/operators.go @@ -86,7 +86,7 @@ func GetAllSecretsFunc(orb *orb.Orb, binaryVersion *string) func(monitor mntr.Mo } allTrees[networking] = nwYML - _, _, nwSecrets, err := nwOrb.AdaptFunc(nil)(monitor, nwYML, nil) + _, _, nwSecrets, err := nwOrb.AdaptFunc("", nil)(monitor, nwYML, nil) if err != nil { return nil, nil, err } diff --git a/internal/start/networking.go b/internal/start/networking.go index 9cf067f42..bf77e9a60 100644 --- a/internal/start/networking.go +++ b/internal/start/networking.go @@ -31,7 +31,7 @@ func Networking(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernete return err } - takeoff := networking.Takeoff(monitor, gitClient, orb.AdaptFunc(binaryVersion), k8sClient) + takeoff := networking.Takeoff(monitor, gitClient, orb.AdaptFunc(orbConfig.URL, binaryVersion), k8sClient) go func() { started := time.Now() From 300dc999ab607e64ee09a93900c0f994b7eea65f Mon Sep 17 00:00:00 2001 From: Stefan Benz Date: Tue, 2 Feb 2021 15:15:25 +0100 Subject: [PATCH 2/8] fix(cloudflare): add read for accountID which is used for LBs --- .../kinds/networking/legacycf/app/app.go | 20 ++++++------- .../legacycf/cloudflare/cloudflare.go | 20 +++++++++++-- .../networking/legacycf/config/external.go | 28 +++++++++++-------- .../networking/legacycf/config/internal.go | 20 ++++++++----- .../networking/legacycf/legacyadapter.go | 4 +-- 5 files changed, 58 insertions(+), 34 deletions(-) diff --git a/internal/operator/networking/kinds/networking/legacycf/app/app.go b/internal/operator/networking/kinds/networking/legacycf/app/app.go index 034f74045..16fae9251 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/app.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/app.go @@ -17,8 +17,8 @@ type App struct { internalPrefix string } -func New(user string, key string, userServiceKey string, groups map[string][]string, internalPrefix string) (*App, error) { - api, err := cloudflare.New(user, key, userServiceKey) +func New(accountName string, user string, key string, userServiceKey string, groups map[string][]string, internalPrefix string) (*App, error) { + api, err := cloudflare.New(accountName, user, key, userServiceKey) if err != nil { return nil, err } @@ -46,9 +46,7 @@ func (a *App) Ensure( subdomains []*config.Subdomain, rules []*config.Rule, originCALabels *labels.Name, - clusterID string, - region string, - lbs bool, + lbs *config.LoadBalancer, floatingIP string, ) error { firewallRulesInt := make([]*cloudflare.FirewallRule, 0) @@ -57,17 +55,17 @@ func (a *App) Ensure( poolsInt := make([]*cloudflare.LoadBalancerPool, 0) lbsInt := make([]*cloudflare.LoadBalancer, 0) - if lbs { + if lbs != nil && lbs.Create { originsInt := []*cloudflare.LoadBalancerOrigin{{ - Name: getPoolName(domain, region, clusterID), + Name: getPoolName(domain, lbs.Region, lbs.ClusterID), Address: floatingIP, Enabled: true, }} poolsInt = append(poolsInt, &cloudflare.LoadBalancerPool{ - Name: getPoolName(domain, region, clusterID), + Name: getPoolName(domain, lbs.Region, lbs.ClusterID), Description: id, - Enabled: lbs, + Enabled: lbs.Enabled, Origins: originsInt, }) } @@ -77,7 +75,7 @@ func (a *App) Ensure( return err } - if lbs { + if lbs != nil && lbs.Create { //ids get filled in the EnsureLoadBalancerPools-function poolNames := []string{} if poolsInt != nil { @@ -98,7 +96,7 @@ func (a *App) Ensure( }) } - if err := a.EnsureLoadBalancers(id, clusterID, region, domain, lbsInt); err != nil { + if err := a.EnsureLoadBalancers(id, lbs.ClusterID, lbs.Region, domain, lbsInt); err != nil { return err } diff --git a/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go b/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go index d63dca4d3..216b27214 100644 --- a/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go +++ b/internal/operator/networking/kinds/networking/legacycf/cloudflare/cloudflare.go @@ -1,6 +1,7 @@ package cloudflare import ( + "errors" "github.com/cloudflare/cloudflare-go" ) @@ -13,14 +14,29 @@ type Cloudflare struct { api *cloudflare.API } -func New(user string, key string, userServiceKey string) (*Cloudflare, error) { +func New(accountName string, user string, key string, userServiceKey string) (*Cloudflare, error) { api, err := cloudflare.New(key, user) if err != nil { return nil, err } api.APIUserServiceKey = userServiceKey - api.AccountID = "86ed4d09664b2b395548c37339c7f179" + if accountName != "" { + accounts, _, err := api.Accounts(cloudflare.PaginationOptions{}) + if err != nil { + return nil, err + } + found := false + for _, account := range accounts { + if account.Name == accountName { + found = true + api.AccountID = account.ID + } + } + if !found { + return nil, errors.New("no account with given name found") + } + } return &Cloudflare{ api: api, diff --git a/internal/operator/networking/kinds/networking/legacycf/config/external.go b/internal/operator/networking/kinds/networking/legacycf/config/external.go index c85d259d5..22fd4c3bb 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/external.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/external.go @@ -12,18 +12,17 @@ import ( ) type ExternalConfig struct { + AccountName string `yaml:"accountName"` ID string Verbose bool Domain string - ClusterID string `yaml:"clusterid"` - Region string `yaml:"region"` - LoadBalancer bool `yaml:"loadbalancer"` IP orbiter.IPAddress Rules []*Rule - Groups []*Group `yaml:"groups"` - Credentials *Credentials `yaml:"credentials"` - Prefix string `yaml:"prefix"` - AdditionalDNS []*Subdomain `yaml:"additionalSubdomains,omitempty"` + Groups []*Group `yaml:"groups"` + Credentials *Credentials `yaml:"credentials"` + Prefix string `yaml:"prefix"` + AdditionalDNS []*Subdomain `yaml:"additionalSubdomains,omitempty"` + LoadBalancer *LoadBalancer `yaml:"loadBalancer,omitempty"` } func (i *ExternalConfig) IsZero() bool { @@ -43,6 +42,7 @@ func (i *ExternalConfig) IsZero() bool { func (e *ExternalConfig) Internal(namespace string, apiLabels *labels.API) (*InternalConfig, *current) { dom, curr := e.internalDomain() return &InternalConfig{ + AccountName: e.AccountName, ID: e.ID, Domains: []*InternalDomain{dom}, Groups: e.Groups, @@ -67,7 +67,7 @@ func (e *ExternalConfig) Validate() error { func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { subdomains := []*Subdomain{} // TODO: Remove - if e.LoadBalancer { + if e.LoadBalancer != nil && e.LoadBalancer.Enabled { lbName := GetLBName(e.Domain) subdomains = append(subdomains, subdomain("accounts", lbName, "CNAME"), @@ -87,14 +87,20 @@ func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { subdomains = append(subdomains, sd) } + lb := &LoadBalancer{} + if e.LoadBalancer != nil { + lb.Enabled = e.LoadBalancer.Enabled + lb.Create = e.LoadBalancer.Create + lb.Region = e.LoadBalancer.Region + lb.ClusterID = e.LoadBalancer.ClusterID + } + return &InternalDomain{ FloatingIP: string(e.IP), - ClusterID: e.ClusterID, - Region: e.Region, Domain: e.Domain, Subdomains: subdomains, Rules: e.Rules, - LoadBalancer: e.LoadBalancer, + LoadBalancer: lb, }, ¤t{ domain: e.Domain, diff --git a/internal/operator/networking/kinds/networking/legacycf/config/internal.go b/internal/operator/networking/kinds/networking/legacycf/config/internal.go index 6225b954e..8ae8e9171 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/internal.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/internal.go @@ -6,6 +6,7 @@ import ( ) type InternalConfig struct { + AccountName string ID string Domains []*InternalDomain `yaml:"domains"` Groups []*Group `yaml:"groups"` @@ -38,13 +39,18 @@ type Group struct { type InternalDomain struct { FloatingIP string - ClusterID string `yaml:"clusterid"` - Region string `yaml:"region"` - Domain string `yaml:"domain"` - Origin *Origin `yaml:"origin"` - Subdomains []*Subdomain `yaml:"subdomains"` - Rules []*Rule `yaml:"rules"` - LoadBalancer bool `yaml:"loadbalancer"` + Domain string `yaml:"domain"` + Origin *Origin `yaml:"origin"` + Subdomains []*Subdomain `yaml:"subdomains"` + Rules []*Rule `yaml:"rules"` + LoadBalancer *LoadBalancer `yaml:"loadbalancer"` +} + +type LoadBalancer struct { + Create bool `yaml:"create"` + ClusterID string `yaml:"clusterid"` + Region string `yaml:"region"` + Enabled bool `yaml:"enabled"` } type Origin struct { diff --git a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go index 34681dd63..2a3089247 100644 --- a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go +++ b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go @@ -29,7 +29,7 @@ func adaptFunc( } } - apps, err := app.New(cfg.Credentials.User.Value, cfg.Credentials.APIKey.Value, cfg.Credentials.UserServiceKey.Value, groups, cfg.Prefix) + apps, err := app.New(cfg.AccountName, cfg.Credentials.User.Value, cfg.Credentials.APIKey.Value, cfg.Credentials.UserServiceKey.Value, groups, cfg.Prefix) if err != nil { return err } @@ -44,8 +44,6 @@ func adaptFunc( domain.Subdomains, domain.Rules, caSecretLabels, - domain.ClusterID, - domain.Region, domain.LoadBalancer, domain.FloatingIP, ) From 4f8384b434526702b646abf857652cff95a06e07 Mon Sep 17 00:00:00 2001 From: Stefan Benz Date: Tue, 2 Feb 2021 17:12:43 +0100 Subject: [PATCH 3/8] fix(cloudflare): corrected steering policy --- .../operator/networking/kinds/networking/legacycf/app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/operator/networking/kinds/networking/legacycf/app/app.go b/internal/operator/networking/kinds/networking/legacycf/app/app.go index 16fae9251..65dc0599f 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/app.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/app.go @@ -92,7 +92,7 @@ func (a *App) Ensure( FallbackPool: poolNames[0], Enabled: &enabled, Proxied: true, - SteeringPolicy: "Random", + SteeringPolicy: "random", }) } From 7d8087bd3859d74ba3d4a23fb62f631225c63d44 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Mon, 8 Feb 2021 16:09:46 +0100 Subject: [PATCH 4/8] refactor: remove internal id from desired state --- .../operator/networking/kinds/networking/legacycf/adapt.go | 5 ++--- .../networking/kinds/networking/legacycf/app/dnsrecords.go | 7 ++++--- .../kinds/networking/legacycf/config/external.go | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/internal/operator/networking/kinds/networking/legacycf/adapt.go b/internal/operator/networking/kinds/networking/legacycf/adapt.go index 0611ae47c..55d9af411 100644 --- a/internal/operator/networking/kinds/networking/legacycf/adapt.go +++ b/internal/operator/networking/kinds/networking/legacycf/adapt.go @@ -14,7 +14,7 @@ import ( func AdaptFunc( namespace string, - ID string, + id string, operatorLabels *labels.Operator, ) opcore.AdaptFunc { return func( @@ -35,7 +35,6 @@ func AdaptFunc( return nil, nil, nil, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind - desiredKind.Spec.ID = ID if !monitor.IsVerbose() && desiredKind.Spec.Verbose { internalMonitor.Verbose() @@ -49,7 +48,7 @@ func AdaptFunc( return nil, nil, nil, err } - internalSpec, current := desiredKind.Spec.Internal(namespace, apiLabels) + internalSpec, current := desiredKind.Spec.Internal(id, namespace, apiLabels) legacyQuerier, legacyDestroyer, readyCertificate, err := adaptFunc(monitor, internalSpec) current.ReadyCertificate = readyCertificate diff --git a/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go b/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go index 693661466..b2acd663c 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/dnsrecords.go @@ -1,8 +1,9 @@ package app import ( - "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/cloudflare" "strings" + + "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/cloudflare" ) func (a *App) EnsureDNSRecords(domain string, records []*cloudflare.DNSRecord) error { @@ -19,7 +20,7 @@ func (a *App) EnsureDNSRecords(domain string, records []*cloudflare.DNSRecord) e } } - createRecords, updateRecords := getRecordsToCreateAndUpdate(domain, currentRecords, records) + createRecords, updateRecords := getRecordsToCreateAndUpdate(currentRecords, records) if createRecords != nil && len(createRecords) > 0 { _, err := a.cloudflare.CreateDNSRecords(domain, createRecords) if err != nil { @@ -67,7 +68,7 @@ func getRecordsToDelete(currentRecords []*cloudflare.DNSRecord, records []*cloud return deleteRecords } -func getRecordsToCreateAndUpdate(domain string, currentRecords []*cloudflare.DNSRecord, records []*cloudflare.DNSRecord) ([]*cloudflare.DNSRecord, []*cloudflare.DNSRecord) { +func getRecordsToCreateAndUpdate(currentRecords []*cloudflare.DNSRecord, records []*cloudflare.DNSRecord) ([]*cloudflare.DNSRecord, []*cloudflare.DNSRecord) { createRecords := make([]*cloudflare.DNSRecord, 0) updateRecords := make([]*cloudflare.DNSRecord, 0) diff --git a/internal/operator/networking/kinds/networking/legacycf/config/external.go b/internal/operator/networking/kinds/networking/legacycf/config/external.go index 22fd4c3bb..fe21c2176 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/external.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/external.go @@ -13,7 +13,6 @@ import ( type ExternalConfig struct { AccountName string `yaml:"accountName"` - ID string Verbose bool Domain string IP orbiter.IPAddress @@ -39,11 +38,11 @@ func (i *ExternalConfig) IsZero() bool { return false } -func (e *ExternalConfig) Internal(namespace string, apiLabels *labels.API) (*InternalConfig, *current) { +func (e *ExternalConfig) Internal(id, namespace string, apiLabels *labels.API) (*InternalConfig, *current) { dom, curr := e.internalDomain() return &InternalConfig{ AccountName: e.AccountName, - ID: e.ID, + ID: id, Domains: []*InternalDomain{dom}, Groups: e.Groups, Credentials: e.Credentials, From fafad7fd12e49a2367699ed268ab99051e16d259 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Mon, 8 Feb 2021 16:30:30 +0100 Subject: [PATCH 5/8] refactor: less indentation --- .../networking/legacycf/app/loadbalancers.go | 103 ++++++++++-------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go index d8d433de5..5b143ba61 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go @@ -70,6 +70,7 @@ func getLoadBalancerToDelete( for _, lb := range lbs { if currentLb.Name == lb.Name { found = true + break } } } @@ -94,19 +95,21 @@ func getLoadBalancerToDelete( func getLoadBalancerToCreate(currentLbs []*cloudflare.LoadBalancer, lbs []*cloudflare.LoadBalancer) []*cloudflare.LoadBalancer { createLbs := make([]*cloudflare.LoadBalancer, 0) - if lbs != nil { - for _, lb := range lbs { - found := false - for _, currentLb := range currentLbs { - if currentLb.Name == lb.Name { - found = true - break - } - } - if found == false { - createLbs = append(createLbs, lb) + if lbs == nil { + return createLbs + } + + for _, lb := range lbs { + found := false + for _, currentLb := range currentLbs { + if currentLb.Name == lb.Name { + found = true + break } } + if !found { + createLbs = append(createLbs, lb) + } } return createLbs @@ -123,52 +126,60 @@ func getLoadBalancerToUpdate( ) []*cloudflare.LoadBalancer { updateLbs := make([]*cloudflare.LoadBalancer, 0) + if lbs == nil { + return updateLbs + } + poolName := getPoolName(domain, region, clusterID) - if lbs != nil { - for _, lb := range lbs { - for _, currentLb := range currentLbs { - if currentLb.Name == config.GetLBName(domain) { - containedRegion := false - containedDefault := false - for _, currentPool := range currentLb.DefaultPools { - if currentPool == poolName { - containedDefault = true - } + for _, lb := range lbs { + for _, currentLb := range currentLbs { + if currentLb.Name == config.GetLBName(domain) { + containedRegion := false + containedDefault := false + for _, currentPool := range currentLb.DefaultPools { + if currentPool == poolName { + containedDefault = true + break } - for currentRegion, currentPools := range currentLb.RegionPools { - if currentRegion == region { - for _, currentPool := range currentPools { - if currentPool == poolName { - containedRegion = true - } + } + + regionPoolsLoop: + for currentRegion, currentPools := range currentLb.RegionPools { + if currentRegion == region { + for _, currentPool := range currentPools { + if currentPool == poolName { + containedRegion = true + break regionPoolsLoop } } } + } - //only update the lb if a pool has to be added - if !containedDefault || !containedRegion { - lb.ID = currentLb.ID - // add already entered pools for update - //all pools which are maintained by operators with other ids + //only update the lb if a pool has to be added + if !containedDefault && !containedRegion { + continue + } + + lb.ID = currentLb.ID + // add already entered pools for update + //all pools which are maintained by operators with other ids + lb.DefaultPools = append(lb.DefaultPools, filterNotSameID(cf, currentLb.DefaultPools, id)...) + + // combine the defined region pools for update + for currentRegion, currentPools := range currentLb.RegionPools { + regionSlice, found := lb.RegionPools[currentRegion] + if found { lb.DefaultPools = append(lb.DefaultPools, filterNotSameID(cf, currentLb.DefaultPools, id)...) - // combine the defined region pools for update - for currentRegion, currentPools := range currentLb.RegionPools { - regionSlice, found := lb.RegionPools[currentRegion] - if found { - lb.DefaultPools = append(lb.DefaultPools, filterNotSameID(cf, currentLb.DefaultPools, id)...) - - regionSlice = append(regionSlice, currentPools...) - } else { - defPool := []string{} - defPool = append(defPool, filterNotSameID(cf, currentPools, id)...) - lb.RegionPools[currentRegion] = defPool - } - } - updateLbs = append(updateLbs, lb) + regionSlice = append(regionSlice, currentPools...) + } else { + defPool := []string{} + defPool = append(defPool, filterNotSameID(cf, currentPools, id)...) + lb.RegionPools[currentRegion] = defPool } } + updateLbs = append(updateLbs, lb) } } } From b1017a56303397c13b522c0a1d6c9d499c820463 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Mon, 8 Feb 2021 16:44:13 +0100 Subject: [PATCH 6/8] fix: update lb if pool not in default OR not in region --- .../networking/kinds/networking/legacycf/app/loadbalancers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go index 5b143ba61..bac67a168 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go @@ -157,7 +157,7 @@ func getLoadBalancerToUpdate( } //only update the lb if a pool has to be added - if !containedDefault && !containedRegion { + if containedDefault && containedRegion { continue } From c357152a6a2213a0fe2d9619528719de197415c1 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Thu, 25 Mar 2021 12:59:37 +0100 Subject: [PATCH 7/8] ci: resolve conflicts --- build/orbos/Dockerfile | 3 +- cmd/boom-debug/main.go | 36 +- cmd/gen-crds/main.go | 39 ++ cmd/gen-executables/main.go | 4 +- cmd/networking-debug/main.go | 59 ++- cmd/nodeagent/main.go | 9 + cmd/orbctl/api.go | 26 +- cmd/orbctl/cmds/deploy.go | 131 ++++-- cmd/orbctl/cmds/takeoff.go | 95 ++-- cmd/orbctl/configure.go | 95 ++-- cmd/orbctl/edit.go | 14 +- cmd/orbctl/exec.go | 15 +- cmd/orbctl/list.go | 15 +- cmd/orbctl/machines.go | 5 +- cmd/orbctl/main.go | 30 +- cmd/orbctl/node.go | 5 +- cmd/orbctl/readsecret.go | 34 +- cmd/orbctl/reboot.go | 17 +- cmd/orbctl/replace.go | 16 +- cmd/orbctl/root.go | 72 ++- cmd/orbctl/takeoff.go | 118 +++-- cmd/orbctl/teardown.go | 24 +- cmd/orbctl/writesecret.go | 44 +- cmd/takeoff-debug/main.go | 13 +- go.mod | 30 +- go.sum | 227 +++++---- hack/boilerplate.go.txt | 15 + internal/api/boom/api.go | 57 +++ internal/api/boom/v1/boom.go | 102 ++++ internal/api/boom/v1/zz_generated.deepcopy.go | 118 +++++ internal/api/boom/v1beta1/boom.go | 48 ++ .../api/boom/v1beta1/zz_generated.deepcopy.go | 118 +++++ internal/api/boom/v1beta2/boom.go | 48 ++ .../api/boom/v1beta2/zz_generated.deepcopy.go | 118 +++++ internal/api/networking/api.go | 76 +++ internal/api/networking/v1/networking.go | 57 +++ .../networking/v1/zz_generated.deepcopy.go | 146 ++++++ internal/cmd/headed.go | 5 - internal/ctrlcrd/boom/boom.go | 56 +++ internal/ctrlcrd/controller.go | 106 +++++ internal/ctrlcrd/networking/networking.go | 67 +++ internal/{start => ctrlgitops}/boom.go | 11 +- internal/{start => ctrlgitops}/common.go | 5 +- internal/{start => ctrlgitops}/networking.go | 13 +- internal/{start => ctrlgitops}/orbiter.go | 88 ++-- internal/executables/targz.go | 2 +- internal/operator/boom/api/api.go | 41 +- .../operator/boom/api/latest/apigateway.go | 2 +- internal/operator/boom/api/latest/funcs.go | 105 +++-- .../boom/api/latest/monitoring/admin/admin.go | 5 +- .../latest/monitoring/auth/Github/github.go | 4 +- .../latest/monitoring/auth/Gitlab/gitlab.go | 4 +- .../latest/monitoring/auth/Google/google.go | 4 +- .../boom/api/latest/monitoring/auth/auth.go | 24 + .../boom/api/latest/reconciling/auth/auth.go | 27 ++ .../latest/reconciling/auth/github/github.go | 4 +- .../latest/reconciling/auth/gitlab/gitlab.go | 4 +- .../latest/reconciling/auth/google/google.go | 6 +- .../api/latest/reconciling/auth/oidc/oidc.go | 4 +- .../api/latest/reconciling/reconciling.go | 4 +- .../reconciling/repository/repository.go | 6 +- .../boom/api/migrate/v1beta1tov1beta2.go | 5 +- .../operator/boom/api/migrate/v1beta2tov1.go | 13 +- .../boom/api/v1beta1/argocd/argocd.go | 8 +- .../boom/api/v1beta1/argocd/auth/auth.go | 27 ++ .../api/v1beta1/argocd/auth/github/github.go | 4 +- .../api/v1beta1/argocd/auth/gitlab/gitlab.go | 4 +- .../api/v1beta1/argocd/auth/google/google.go | 6 +- .../boom/api/v1beta1/argocd/auth/oidc/oidc.go | 4 +- .../v1beta1/argocd/repository/repository.go | 39 +- internal/operator/boom/api/v1beta1/funcs.go | 114 +---- .../boom/api/v1beta1/grafana/admin/admin.go | 2 +- .../v1beta1/grafana/auth/Generic/generic.go | 4 +- .../api/v1beta1/grafana/auth/Github/github.go | 4 +- .../api/v1beta1/grafana/auth/Gitlab/gitlab.go | 4 +- .../api/v1beta1/grafana/auth/Google/google.go | 4 +- internal/operator/boom/api/v1beta2/funcs.go | 6 +- internal/operator/boom/app/app.go | 88 ++-- .../applications/argocd/config/auth/github.go | 6 +- .../applications/argocd/config/auth/gitlab.go | 6 +- .../applications/argocd/config/auth/google.go | 9 +- .../applications/argocd/config/auth/oidc.go | 6 +- .../argocd/config/credential/credential.go | 20 +- .../argocd/config/repository/repository.go | 20 +- .../argocd/customimage/customimage.go | 7 +- .../applications/grafana/admin/admin.go | 6 +- .../grafana/auth/generic_oauth.go | 6 +- .../applications/grafana/auth/github.go | 6 +- .../applications/grafana/auth/gitlab.go | 6 +- .../applications/grafana/auth/google.go | 6 +- .../applications/grafana/helm/default.go | 2 +- .../metricsserver/helm/default.go | 7 +- internal/operator/boom/bundle/apply.go | 2 +- internal/operator/boom/bundle/delete.go | 2 +- internal/operator/boom/cmd/reconcile.go | 19 +- internal/operator/boom/crd/crd.go | 46 +- internal/operator/boom/gitcrd/gitcrd.go | 50 +- internal/operator/boom/takeoff.go | 10 +- internal/operator/common/nodeagent-model.go | 9 + internal/operator/core/adapt.go | 13 +- .../kinds/networking/legacycf/adapt.go | 23 +- .../networking/legacycf/config/external.go | 45 +- .../networking/legacycf/config/internal.go | 21 +- .../networking/legacycf/legacyadapter.go | 20 +- .../kinds/networking/legacycf/secrets.go | 28 +- .../networking/kinds/networking/networking.go | 4 +- .../operator/networking/kinds/orb/adapt.go | 28 +- .../operator/networking/kinds/orb/desired.go | 25 +- .../networking/kinds/orb/reconcile.go | 41 +- .../kinds/orb/zz_generated.deepcopy.go | 54 +++ internal/operator/networking/takeoff.go | 3 +- .../operator/nodeagent/dep/conv/converter.go | 3 +- internal/operator/nodeagent/dep/cri/ensure.go | 81 ++-- internal/operator/nodeagent/dep/k8s/common.go | 18 +- internal/operator/nodeagent/dep/nginx/dep.go | 33 +- .../operator/nodeagent/dep/package-manager.go | 12 +- .../nodeagent/firewall/centos/centOS.go | 8 +- .../nodeagent/firewall/centos/ports.go | 81 +++- .../operator/nodeagent/firewall/firewall.go | 4 +- internal/operator/nodeagent/iterator.go | 49 +- .../nodeagent/networking/centos/centOS.go | 1 + internal/operator/orbiter/adapt.go | 33 +- internal/operator/orbiter/config.go | 4 +- internal/operator/orbiter/destroy.go | 15 +- .../orbiter/kinds/clusters/clusters.go | 48 +- .../kinds/clusters/kubernetes/adapt.go | 12 +- .../kinds/clusters/kubernetes/destroy.go | 2 +- .../orbiter/kinds/clusters/kubernetes/join.go | 1 + .../kinds/loadbalancers/dynamic/adapt.go | 11 +- .../kinds/loadbalancers/loadbalancers.go | 5 +- internal/operator/orbiter/kinds/orb/adapt.go | 28 +- .../operator/orbiter/kinds/orb/desired.go | 1 + .../operator/orbiter/kinds/orb/machines.go | 1 + .../orbiter/kinds/providers/core/nodeagent.go | 21 +- .../orbiter/kinds/providers/cs/adapt.go | 23 +- .../kinds/providers/cs/machinesservice.go | 10 +- .../orbiter/kinds/providers/gce/adapt.go | 37 +- .../kinds/providers/gce/computesservice.go | 27 +- .../orbiter/kinds/providers/gce/pool.go | 2 +- .../orbiter/kinds/providers/providers.go | 30 +- .../orbiter/kinds/providers/ssh/machine.go | 2 + .../orbiter/kinds/providers/static/adapt.go | 33 +- .../kinds/providers/static/computesservice.go | 18 +- .../orbiter/kinds/providers/static/desired.go | 22 +- .../kinds/providers/static/desired_test.go | 67 +++ internal/operator/orbiter/takeoff.go | 113 +++-- internal/orb/orb.go | 82 ---- internal/secret/operators/operators.go | 263 +++++++---- internal/ssh/ssh.go | 17 +- internal/utils/clientgo/clientgo.go | 51 +- internal/utils/clientgo/resource.go | 24 +- internal/utils/clientgo/secret.go | 3 +- internal/utils/helper/secret.go | 42 -- pkg/git/git.go | 25 +- pkg/helper/secret.go | 58 +++ pkg/kubernetes/artifacts.go | 439 +----------------- pkg/kubernetes/boom.go | 249 ++++++++++ pkg/kubernetes/cli/client.go | 90 ++++ pkg/kubernetes/client.go | 244 +++++++--- pkg/kubernetes/crds.go | 190 ++++++++ pkg/kubernetes/mock/client.mock.go | 96 +++- pkg/kubernetes/networking.go | 299 ++++++++++++ pkg/kubernetes/orbiter.go | 171 +++++++ .../resources/ambassador/host/adapt.go | 2 +- .../resources/ambassador/mapping/adapt.go | 53 +-- .../resources/ambassador/module/adapt.go | 8 +- pkg/kubernetes/resources/ingress/adapt.go | 59 +++ pkg/kubernetes/resources/job/adapt.go | 56 ++- pkg/kubernetes/resources/service/service.go | 4 +- pkg/labels/mocklabels/mock.go | 6 +- pkg/orb/orb.go | 91 +++- pkg/secret/rwsecret.go | 268 +++++++++-- pkg/secret/secret.go | 33 +- pkg/tree/tree.go | 4 +- scripts/cs_get_pprof_profile_from_na.sh | 12 + scripts/gce_get_pprof_profile_from_na.sh | 11 + scripts/generateCrd.sh | 3 + scripts/orbctl.sh | 2 +- 178 files changed, 5236 insertions(+), 2143 deletions(-) create mode 100644 cmd/gen-crds/main.go create mode 100644 hack/boilerplate.go.txt create mode 100644 internal/api/boom/api.go create mode 100644 internal/api/boom/v1/boom.go create mode 100644 internal/api/boom/v1/zz_generated.deepcopy.go create mode 100644 internal/api/boom/v1beta1/boom.go create mode 100644 internal/api/boom/v1beta1/zz_generated.deepcopy.go create mode 100644 internal/api/boom/v1beta2/boom.go create mode 100644 internal/api/boom/v1beta2/zz_generated.deepcopy.go create mode 100644 internal/api/networking/api.go create mode 100644 internal/api/networking/v1/networking.go create mode 100644 internal/api/networking/v1/zz_generated.deepcopy.go delete mode 100644 internal/cmd/headed.go create mode 100644 internal/ctrlcrd/boom/boom.go create mode 100644 internal/ctrlcrd/controller.go create mode 100644 internal/ctrlcrd/networking/networking.go rename internal/{start => ctrlgitops}/boom.go (89%) rename internal/{start => ctrlgitops}/common.go (95%) rename internal/{start => ctrlgitops}/networking.go (77%) rename internal/{start => ctrlgitops}/orbiter.go (68%) create mode 100644 internal/operator/networking/kinds/orb/zz_generated.deepcopy.go create mode 100644 internal/operator/orbiter/kinds/providers/static/desired_test.go delete mode 100644 internal/orb/orb.go delete mode 100644 internal/utils/helper/secret.go create mode 100644 pkg/helper/secret.go create mode 100644 pkg/kubernetes/boom.go create mode 100644 pkg/kubernetes/cli/client.go create mode 100644 pkg/kubernetes/crds.go create mode 100644 pkg/kubernetes/networking.go create mode 100644 pkg/kubernetes/orbiter.go create mode 100644 pkg/kubernetes/resources/ingress/adapt.go create mode 100755 scripts/cs_get_pprof_profile_from_na.sh create mode 100755 scripts/gce_get_pprof_profile_from_na.sh create mode 100755 scripts/generateCrd.sh diff --git a/build/orbos/Dockerfile b/build/orbos/Dockerfile index dca8ff367..35d2f2507 100644 --- a/build/orbos/Dockerfile +++ b/build/orbos/Dockerfile @@ -28,10 +28,9 @@ ENV PATH="/dependencies:${PATH}" ENTRYPOINT [ "dlv", "exec", "/orbctl", "--api-version", "2", "--headless", "--listen", "127.0.0.1:2345", "--" ] -FROM python:3.8.3-alpine3.11 as prod +FROM alpine:3.13.1 as prod RUN apk update && \ - apk add openssh && \ addgroup -S -g 1000 orbiter && \ adduser -S -u 1000 orbiter -G orbiter diff --git a/cmd/boom-debug/main.go b/cmd/boom-debug/main.go index 888a0259c..0b908b49e 100644 --- a/cmd/boom-debug/main.go +++ b/cmd/boom-debug/main.go @@ -4,6 +4,8 @@ import ( "context" "flag" + "github.com/caos/orbos/internal/ctrlcrd" + "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/internal/helpers" @@ -14,8 +16,10 @@ import ( func main() { + gitops := flag.Bool("gitops", false, "defines if the operator should run in gitops mode not crd mode") orbconfig := flag.String("orbconfig", "~/.orb/config", "The orbconfig file to use") verbose := flag.Bool("verbose", false, "Print debug levelled logs") + metricsAddr := flag.String("metrics-addr", ":8080", "The address the metric endpoint binds to.") flag.Parse() @@ -29,21 +33,27 @@ func main() { monitor = monitor.Verbose() } - ensure := git.New(context.Background(), monitor.WithField("task", "ensure"), "Boom", "boom@caos.ch") - query := git.New(context.Background(), monitor.WithField("task", "query"), "Boom", "boom@caos.ch") + if !*gitops { + if err := ctrlcrd.Start(monitor, "crdoperators", "./artifacts", *metricsAddr, "", ctrlcrd.Boom); err != nil { + panic(err) + } + } else { + + ensure := git.New(context.Background(), monitor.WithField("task", "ensure"), "Boom", "boom@caos.ch") + query := git.New(context.Background(), monitor.WithField("task", "query"), "Boom", "boom@caos.ch") - ensure.Clone() - query.Clone() + ensure.Clone() + query.Clone() - takeoff, _ := boom.Takeoff( - monitor, - "./artifacts", - true, - helpers.PruneHome(*orbconfig), - ensure, query, - ) + takeoff, _ := boom.Takeoff( + monitor, + "./artifacts", + helpers.PruneHome(*orbconfig), + ensure, query, + ) - for { - takeoff() + for { + takeoff() + } } } diff --git a/cmd/gen-crds/main.go b/cmd/gen-crds/main.go new file mode 100644 index 000000000..a7ab0a1a0 --- /dev/null +++ b/cmd/gen-crds/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "path/filepath" +) + +const ( + crdFolder = "crds" +) + +func main() { + var basePath string + var boilerplatePath string + var kubeconfig string + flag.StringVar(&kubeconfig, "kubeconfig", "", "If kubeconfig is provided, crds will get applied") + flag.StringVar(&basePath, "basepath", "./artifacts", "The local path where the base folder should be") + flag.StringVar(&boilerplatePath, "boilerplatepath", "./hack/boilerplate.go.txt", "The local path where the boilerplate text file lies") + flag.Parse() + + if kubeconfig != "" { + k8sClient, err := kubernetes.NewK8sClientWithPath(mntr.Monitor{}, kubeconfig) + if err != nil { + panic(err) + } + + if k8sClient.Available() { + if err := kubernetes.ApplyCRDs(boilerplatePath, "./...", k8sClient); err != nil { + panic(err) + } + } + } else { + if err := kubernetes.WriteCRDs(boilerplatePath, "./...", filepath.Join(basePath, crdFolder)); err != nil { + panic(err) + } + } +} diff --git a/cmd/gen-executables/main.go b/cmd/gen-executables/main.go index 00d7716c2..1db3b837c 100644 --- a/cmd/gen-executables/main.go +++ b/cmd/gen-executables/main.go @@ -15,8 +15,8 @@ import ( func main() { - version := flag.String("version", "none", "Path to the git repositorys path to the file containing orbiters current state") - commit := flag.String("commit", "none", "Path to the git repositorys path to the file containing orbiters current state") + version := flag.String("version", "none", "Value shown by orbctl --version") + commit := flag.String("commit", "none", "Commit SHA shown by orbctl --version") githubClientID := flag.String("githubclientid", "none", "ClientID used for OAuth with github as store") githubClientSecret := flag.String("githubclientsecret", "none", "ClientSecret used for OAuth with github as store") orbctldir := flag.String("orbctl", "", "Build orbctl binaries to this directory") diff --git a/cmd/networking-debug/main.go b/cmd/networking-debug/main.go index 404bcde97..baaf0b024 100644 --- a/cmd/networking-debug/main.go +++ b/cmd/networking-debug/main.go @@ -1,22 +1,29 @@ package main import ( + "context" "flag" - "io/ioutil" + "github.com/caos/orbos/internal/ctrlcrd" + "github.com/caos/orbos/internal/ctrlgitops" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes/cli" + "os" - "github.com/caos/orbos/pkg/kubernetes" - - "github.com/caos/orbos/internal/start" + "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/internal/helpers" "github.com/caos/orbos/mntr" ) func main() { + var orbconfig, kubeconfig, metricsAddr string + var verbose, gitopsmode bool - orbconfig := flag.String("orbconfig", "~/.orb/config", "The orbconfig file to use") - kubeconfig := flag.String("kubeconfig", "~/.kube/config", "The kubeconfig file to use") - verbose := flag.Bool("verbose", false, "Print debug levelled logs") + flag.StringVar(&orbconfig, "orbconfig", "~/.orb/config", "The orbconfig file to use") + flag.StringVar(&kubeconfig, "kc", "~/.kube/config", "The kubeconfig file to use") + flag.BoolVar(&verbose, "verbose", false, "Print debug levelled logs") + flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") + flag.BoolVar(&gitopsmode, "gitopsmode", false, "defines if the operator should run in gitops mode not crd mode") flag.Parse() @@ -26,25 +33,35 @@ func main() { OnError: mntr.LogError, } - if *verbose { + if verbose { monitor = monitor.Verbose() } - kc, err := ioutil.ReadFile(helpers.PruneHome(*kubeconfig)) + prunedPath := helpers.PruneHome(orbconfig) + orbConfig, err := orb.ParseOrbConfig(prunedPath) if err != nil { - panic(err) + monitor.Error(err) + os.Exit(1) } + gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") + kubeconfig = helpers.PruneHome(kubeconfig) + version := "networking-development" - if err := start.Networking( - monitor, - helpers.PruneHome(*orbconfig), - kubernetes.NewK8sClient(monitor, strPtr(string(kc))), - strPtr("networking-development"), - ); err != nil { - panic(err) - } -} + if gitopsmode { -func strPtr(str string) *string { - return &str + k8sClient, _, err := cli.Client(monitor, orbConfig, gitClient, kubeconfig, gitopsmode) + if err != nil { + monitor.Error(err) + os.Exit(1) + } + if err := ctrlgitops.Networking(monitor, orbConfig.Path, k8sClient, &version); err != nil { + monitor.Error(err) + os.Exit(1) + } + } else { + if err := ctrlcrd.Start(monitor, version, "/boom", metricsAddr, kubeconfig, ctrlcrd.Networking); err != nil { + monitor.Error(err) + os.Exit(1) + } + } } diff --git a/cmd/nodeagent/main.go b/cmd/nodeagent/main.go index 2da450a41..4f8dc9085 100644 --- a/cmd/nodeagent/main.go +++ b/cmd/nodeagent/main.go @@ -6,6 +6,7 @@ import ( "flag" "fmt" "github.com/caos/orbos/internal/operator/nodeagent/networking" + "net/http" "os" "strings" "time" @@ -17,6 +18,7 @@ import ( "github.com/caos/orbos/internal/operator/nodeagent/dep" "github.com/caos/orbos/internal/operator/nodeagent/dep/conv" "github.com/caos/orbos/internal/operator/nodeagent/firewall" + _ "net/http/pprof" ) var gitCommit string @@ -36,6 +38,7 @@ func main() { printVersion := flag.Bool("version", false, "Print build information") ignorePorts := flag.String("ignore-ports", "", "Comma separated list of firewall ports that are ignored") nodeAgentID := flag.String("id", "", "The managed machines ID") + pprof := flag.Bool("pprof", false, "start pprof as port 6060") flag.Parse() @@ -64,6 +67,12 @@ func main() { "nodeAgentID": *nodeAgentID, }).Info("Node Agent is starting") + if *pprof { + go func() { + monitor.Info(http.ListenAndServe("localhost:6060", nil).Error()) + }() + } + os, err := dep.GetOperatingSystem() if err != nil { panic(err) diff --git a/cmd/orbctl/api.go b/cmd/orbctl/api.go index 3f5eae234..de7648e22 100644 --- a/cmd/orbctl/api.go +++ b/cmd/orbctl/api.go @@ -1,15 +1,19 @@ package main import ( + "errors" + + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/internal/api" boomapi "github.com/caos/orbos/internal/operator/boom/api" "github.com/caos/orbos/internal/operator/orbiter" - "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" + orbadapter "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" "github.com/caos/orbos/pkg/labels" "github.com/spf13/cobra" ) -func APICommand(rv RootValues) *cobra.Command { +func APICommand(getRv GetRootValues) *cobra.Command { var ( cmd = &cobra.Command{ Use: "api", @@ -20,15 +24,23 @@ func APICommand(rv RootValues) *cobra.Command { cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() - if err := orbConfig.IsComplete(); err != nil { + if !rv.Gitops { + return errors.New("api command is only supported with the --gitops flag") + } + + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if err := orbcfg.IsComplete(orbConfig); err != nil { return err } @@ -46,7 +58,7 @@ func APICommand(rv RootValues) *cobra.Command { } if foundOrbiter { - _, _, _, migrate, desired, _, _, err := orbiter.Adapt(gitClient, monitor, make(chan struct{}), orb.AdaptFunc( + _, _, _, migrate, desired, _, _, err := orbiter.Adapt(gitClient, monitor, make(chan struct{}), orbadapter.AdaptFunc( labels.NoopOperator("ORBOS"), orbConfig, gitCommit, @@ -76,7 +88,7 @@ func APICommand(rv RootValues) *cobra.Command { return err } - toolset, migrate, _, _, _, err := boomapi.ParseToolset(desired) + toolset, migrate, _, _, err := boomapi.ParseToolset(desired) if err != nil { return err } diff --git a/cmd/orbctl/cmds/deploy.go b/cmd/orbctl/cmds/deploy.go index 43439cad6..dee77c3df 100644 --- a/cmd/orbctl/cmds/deploy.go +++ b/cmd/orbctl/cmds/deploy.go @@ -3,6 +3,7 @@ package cmds import ( "github.com/caos/orbos/internal/api" boomapi "github.com/caos/orbos/internal/operator/boom/api" + "github.com/caos/orbos/internal/operator/boom/api/latest" cmdboom "github.com/caos/orbos/internal/operator/boom/cmd" orbnw "github.com/caos/orbos/internal/operator/networking/kinds/orb" "github.com/caos/orbos/mntr" @@ -11,65 +12,105 @@ import ( "github.com/caos/orbos/pkg/labels" ) -func deployBoom(monitor mntr.Monitor, gitClient *git.Client, kubeconfig *string, binaryVersion string) error { - foundBoom, err := api.ExistsBoomYml(gitClient) - if err != nil { - return err - } - if !foundBoom { - monitor.Info("No BOOM deployed as no boom.yml present") - return nil - } - desiredTree, err := api.ReadBoomYml(gitClient) - if err != nil { - return err - } +func deployBoom(monitor mntr.Monitor, gitClient *git.Client, k8sClient kubernetes.ClientInt, binaryVersion string, gitops bool) error { - // TODO: Parse toolset in cmdboom.Reconcile function (see deployDatabase, deployNetworking) - desiredKind, _, _, apiKind, apiVersion, err := boomapi.ParseToolset(desiredTree) - if err != nil { - return err - } + if gitops { + foundBoom, err := api.ExistsBoomYml(gitClient) + if err != nil { + return err + } + if !foundBoom { + monitor.Info("No BOOM deployed as no boom.yml present") + return nil + } + desiredTree, err := api.ReadBoomYml(gitClient) + if err != nil { + return err + } - k8sClient := kubernetes.NewK8sClient(monitor, kubeconfig) + // TODO: Parse toolset in cmdboom.Reconcile function (see deployDatabase, deployNetworking) + desiredKind, _, apiKind, apiVersion, err := boomapi.ParseToolset(desiredTree) + if err != nil { + return err + } - if desiredKind != nil && - desiredKind.Spec != nil && - desiredKind.Spec.Boom != nil && - desiredKind.Spec.Boom.Version != "" { - binaryVersion = desiredKind.Spec.Boom.Version - } + if desiredKind != nil && + desiredKind.Spec != nil && + desiredKind.Spec.Boom != nil && + desiredKind.Spec.Boom.Version != "" { + binaryVersion = desiredKind.Spec.Boom.Version + } + + if err := cmdboom.Reconcile( + monitor, + labels.MustForAPI(labels.MustForOperator("ORBOS", "boom.caos.ch", binaryVersion), apiKind, apiVersion), + k8sClient, + desiredKind.Spec.Boom, + binaryVersion, + gitops, + ); err != nil { + return err + } + } else { + boom := &latest.Boom{ + Version: binaryVersion, + SelfReconciling: true, + } - if err := cmdboom.Reconcile( - monitor, - labels.MustForAPI(labels.MustForOperator("ORBOS", "boom.caos.ch", binaryVersion), apiKind, apiVersion), - k8sClient, - desiredKind.Spec.Boom, - binaryVersion, - ); err != nil { - return err + if err := cmdboom.Reconcile( + monitor, + labels.MustForAPI(labels.MustForOperator("ORBOS", "boom.caos.ch", binaryVersion), "BOOM", "v1"), + k8sClient, + boom, + binaryVersion, + gitops, + ); err != nil { + return err + } } return nil } -func deployNetworking(monitor mntr.Monitor, gitClient *git.Client, kubeconfig *string) error { - found, err := api.ExistsNetworkingYml(gitClient) - if err != nil { - return err - } - if found { - k8sClient := kubernetes.NewK8sClient(monitor, kubeconfig) - if k8sClient.Available() { - tree, err := api.ReadNetworkinglYml(gitClient) +func deployNetworking(monitor mntr.Monitor, gitClient *git.Client, k8sClient kubernetes.ClientInt, version string, gitops bool) error { + if gitops { + found, err := api.ExistsNetworkingYml(gitClient) + if err != nil { + return err + } + if found { + desiredTree, err := api.ReadNetworkinglYml(gitClient) if err != nil { return err } + desired, err := orbnw.ParseDesiredV0(desiredTree) + if err != nil { + return err + } + spec := desired.Spec - if err := orbnw.Reconcile(monitor, tree)(k8sClient); err != nil { + // at takeoff the artifacts have to be applied + spec.SelfReconciling = true + if err := orbnw.Reconcile( + monitor, + spec, + gitops, + )(k8sClient); err != nil { return err } - } else { - monitor.Info("Failed to connect to k8s") + } + } else { + // at takeoff the artifacts have to be applied + spec := &orbnw.Spec{ + Version: version, + SelfReconciling: true, + } + + if err := orbnw.Reconcile( + monitor, + spec, + gitops, + )(k8sClient); err != nil { + return err } } return nil diff --git a/cmd/orbctl/cmds/takeoff.go b/cmd/orbctl/cmds/takeoff.go index 43e3c7034..914e1506c 100644 --- a/cmd/orbctl/cmds/takeoff.go +++ b/cmd/orbctl/cmds/takeoff.go @@ -2,12 +2,15 @@ package cmds import ( "context" - "errors" - "io/ioutil" - "github.com/caos/orbos/internal/api" - "github.com/caos/orbos/internal/orb" - "github.com/caos/orbos/internal/start" + "gopkg.in/yaml.v3" + + "github.com/caos/orbos/pkg/kubernetes/cli" + + orbcfg "github.com/caos/orbos/pkg/orb" + + "github.com/caos/orbos/internal/ctrlgitops" + "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/kubernetes" @@ -16,7 +19,7 @@ import ( func Takeoff( monitor mntr.Monitor, ctx context.Context, - orbConfig *orb.Orb, + orbConfig *orbcfg.Orb, gitClient *git.Client, recur bool, destroy bool, @@ -26,26 +29,34 @@ func Takeoff( version string, gitCommit string, kubeconfig string, + gitOpsBoom bool, + gitOpsNetworking bool, ) error { - if err := orbConfig.IsComplete(); err != nil { - return err - } - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - return err + if !deploy { + monitor.Info("Skipping operator deployments") + return nil } - if err := gitClient.Clone(); err != nil { - return err + getKubeClient := func() (*kubernetes.Client, bool, error) { + return cli.Client( + monitor, + orbConfig, + gitClient, + kubeconfig, + gitOpsBoom || gitOpsNetworking, + ) } - allKubeconfigs := make([]string, 0) - foundOrbiter, err := api.ExistsOrbiterYml(gitClient) - if err != nil { + k8sClient, fromOrbiter, err := getKubeClient() + + if !fromOrbiter && err != nil { return err } - if foundOrbiter { - orbiterConfig := &start.OrbiterConfig{ + + if fromOrbiter { + err = nil + orbiterConfig := &ctrlgitops.OrbiterConfig{ Recur: recur, Destroy: destroy, Deploy: deploy, @@ -56,52 +67,36 @@ func Takeoff( IngestionAddress: ingestionAddress, } - kubeconfigs, err := start.Orbiter(ctx, monitor, orbiterConfig, gitClient, orbConfig, version) - if err != nil { + if err = ctrlgitops.Orbiter(ctx, monitor, orbiterConfig, gitClient); err != nil { return err } - allKubeconfigs = append(allKubeconfigs, kubeconfigs...) - } else { - if kubeconfig == "" { - return errors.New("Error to deploy BOOM as no kubeconfig is provided") - } - value, err := ioutil.ReadFile(kubeconfig) + + k8sClient, fromOrbiter, err = getKubeClient() if err != nil { return err } - allKubeconfigs = append(allKubeconfigs, string(value)) } - if !deploy { - monitor.Info("Skipping operator deployments") - return nil + if err := kubernetes.EnsureCaosSystemNamespace(monitor, k8sClient); err != nil { + monitor.Info("failed to apply common resources into k8s-cluster") + return err } - for _, kubeconfig := range allKubeconfigs { - k8sClient := kubernetes.NewK8sClient(monitor, &kubeconfig) - if k8sClient.Available() { - if err := kubernetes.EnsureCommonArtifacts(monitor, k8sClient); err != nil { - monitor.Info("failed to apply common resources into k8s-cluster") - return err - } - monitor.Info("Applied common resources") - - if err := kubernetes.EnsureConfigArtifacts(monitor, k8sClient, orbConfig); err != nil { - monitor.Info("failed to apply configuration resources into k8s-cluster") - return err - } - monitor.Info("Applied configuration resources") - } else { - monitor.Info("Failed to connect to k8s") - } + if fromOrbiter || gitOpsBoom || gitOpsNetworking { - if err := deployBoom(monitor, gitClient, &kubeconfig, version); err != nil { + orbConfigBytes, err := yaml.Marshal(orbConfig) + if err != nil { return err } - if err := deployNetworking(monitor, gitClient, &kubeconfig); err != nil { + if err := kubernetes.EnsureOrbconfigSecret(monitor, k8sClient, orbConfigBytes); err != nil { + monitor.Info("failed to apply configuration resources into k8s-cluster") return err } } - return nil + + if err := deployBoom(monitor, gitClient, k8sClient, version, gitOpsBoom); err != nil { + return err + } + return deployNetworking(monitor, gitClient, k8sClient, version, gitOpsNetworking) } diff --git a/cmd/orbctl/configure.go b/cmd/orbctl/configure.go index fb8e4eb3d..575f155cf 100644 --- a/cmd/orbctl/configure.go +++ b/cmd/orbctl/configure.go @@ -3,17 +3,18 @@ package main import ( "errors" "fmt" - "io/ioutil" "path/filepath" + "gopkg.in/yaml.v3" + + "github.com/caos/orbos/pkg/kubernetes/cli" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/labels" secret2 "github.com/caos/orbos/pkg/secret" boomapi "github.com/caos/orbos/internal/operator/boom/api" - "github.com/caos/orbos/internal/start" - "github.com/caos/orbos/internal/operator/orbiter" "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" @@ -25,7 +26,7 @@ import ( "github.com/spf13/cobra" ) -func ConfigCommand(rv RootValues) *cobra.Command { +func ConfigCommand(getRv GetRootValues) *cobra.Command { var ( kubeconfig string @@ -45,14 +46,21 @@ func ConfigCommand(rv RootValues) *cobra.Command { flags.StringVar(&newRepoURL, "repourl", "", "Configures the repository URL") cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { - ctx, monitor, orbConfig, gitClient, errFunc, err := rv() - if err != nil { - return err - } + + rv, _ := getRv() defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + if !rv.Gitops { + return errors.New("configure command is only supported with the --gitops flag") + } + + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + ctx := rv.Ctx + if orbConfig.URL == "" && newRepoURL == "" { return errors.New("repository url is neighter passed by flag repourl nor written in orbconfig") } @@ -133,18 +141,18 @@ func ConfigCommand(rv RootValues) *cobra.Command { return err } - allKubeconfigs := make([]string, 0) - foundOrbiter, err := api.ExistsOrbiterYml(gitClient) - if err != nil { - return err - } - rewriteKey := orbConfig.Masterkey if newMasterKey != "" { rewriteKey = newMasterKey } - if foundOrbiter { + k8sClient, fromOrbiter, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops) + if err != nil { + // ignore + err = nil + } + + if fromOrbiter { _, _, configure, _, desired, _, _, err := orbiter.Adapt(gitClient, monitor, make(chan struct{}), orb.AdaptFunc( labels.NoopOperator("ORBOS"), @@ -171,29 +179,20 @@ func ConfigCommand(rv RootValues) *cobra.Command { api.PushOrbiterDesiredFunc); err != nil { return err } - - monitor.Info("Reading kubeconfigs from orbiter.yml") - kubeconfigs, err := start.GetKubeconfigs(monitor, gitClient, orbConfig, version) - if err == nil { - allKubeconfigs = append(allKubeconfigs, kubeconfigs...) - } - - } else { - monitor.Info("No orbiter.yml existent, reading kubeconfig from path provided as parameter") - if kubeconfig == "" { - return errors.New("error to change config as no kubeconfig is provided") - } - value, err := ioutil.ReadFile(kubeconfig) - if err != nil { - return err - } - allKubeconfigs = append(allKubeconfigs, string(value)) + /* + monitor.Info("Reading kubeconfigs from orbiter.yml") + kubeconfigs, err := ctrlgitops.GetKubeconfigs(monitor, gitClient, orbConfig) + if err == nil { + allKubeconfigs = append(allKubeconfigs, kubeconfigs...) + } + */ } foundBoom, err := api.ExistsBoomYml(gitClient) if err != nil { return err } + if foundBoom { monitor.Info("Repopulating boom secrets") @@ -202,7 +201,7 @@ func ConfigCommand(rv RootValues) *cobra.Command { return err } - toolset, _, _, _, _, err := boomapi.ParseToolset(tree) + toolset, _, _, _, err := boomapi.ParseToolset(tree) if err != nil { return err } @@ -218,21 +217,25 @@ func ConfigCommand(rv RootValues) *cobra.Command { } } - for _, kubeconfig := range allKubeconfigs { - k8sClient := kubernetes.NewK8sClient(monitor, &kubeconfig) - if k8sClient.Available() { - monitor.Info("Ensuring orbconfig in kubernetes cluster") - if err := kubernetes.EnsureConfigArtifacts(monitor, k8sClient, orbConfig); err != nil { - monitor.Error(errors.New("failed to apply configuration resources into k8s-cluster")) - return err - } + if k8sClient == nil { + monitor.Info("Writing new orbconfig skipped as no kubernetes cluster connection is available") + return nil + } - monitor.Info("Applied configuration resources") - } else { - monitor.Info("No connection to the k8s-cluster possible") - } + monitor.Info("Ensuring orbconfig in kubernetes cluster") + + orbConfigBytes, err := yaml.Marshal(orbConfig) + if err != nil { + return err } + if err := kubernetes.EnsureOrbconfigSecret(monitor, k8sClient, orbConfigBytes); err != nil { + monitor.Error(errors.New("failed to apply configuration resources into k8s-cluster")) + return err + } + + monitor.Info("Applied configuration resources") + return nil } return cmd diff --git a/cmd/orbctl/edit.go b/cmd/orbctl/edit.go index c9e6bd1e4..2dde49348 100644 --- a/cmd/orbctl/edit.go +++ b/cmd/orbctl/edit.go @@ -4,6 +4,7 @@ package main import ( "bytes" + "errors" "io" "io/ioutil" "os" @@ -16,7 +17,7 @@ import ( "github.com/caos/orbos/pkg/git" ) -func EditCommand(rv RootValues) *cobra.Command { +func EditCommand(getRv GetRootValues) *cobra.Command { return &cobra.Command{ Use: "edit [file]", Short: "Edit a file and push changes to the remote orb repository", @@ -24,14 +25,21 @@ func EditCommand(rv RootValues) *cobra.Command { Example: `orbctl edit desired.yml`, RunE: func(cmd *cobra.Command, args []string) (err error) { - _, _, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if !rv.Gitops { + return errors.New("edit command is only supported with the --gitops flag") + } + if err := orbConfig.IsConnectable(); err != nil { return err } diff --git a/cmd/orbctl/exec.go b/cmd/orbctl/exec.go index 245fbbcce..535ba09a6 100644 --- a/cmd/orbctl/exec.go +++ b/cmd/orbctl/exec.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" ) -func ExecCommand(rv RootValues) *cobra.Command { +func ExecCommand(getRv GetRootValues) *cobra.Command { var ( command string cmd = &cobra.Command{ @@ -27,14 +27,23 @@ func ExecCommand(rv RootValues) *cobra.Command { flags.StringVar(&command, "command", "", "Command to be executed") cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if !rv.Gitops { + return errors.New("exec command is only supported with the --gitops flag and a committed orbiter.yml") + } + return machines(monitor, gitClient, orbConfig, func(machineIDs []string, machines map[string]infra.Machine, _ *tree.Tree) error { machineID := "" diff --git a/cmd/orbctl/list.go b/cmd/orbctl/list.go index aee5340d8..daf3678ff 100644 --- a/cmd/orbctl/list.go +++ b/cmd/orbctl/list.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "os" "reflect" @@ -14,7 +15,7 @@ import ( "github.com/caos/orbos/pkg/tree" ) -func ListCommand(rv RootValues) *cobra.Command { +func ListCommand(getRv GetRootValues) *cobra.Command { var ( column, context string cmd = &cobra.Command{ @@ -30,14 +31,22 @@ func ListCommand(rv RootValues) *cobra.Command { flags.StringVar(&context, "context", "", "Print machines from this context only") cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if !rv.Gitops { + return errors.New("list command is only supported with the --gitops flag and a committed orbiter.yml") + } + return machines(monitor, gitClient, orbConfig, func(machineIDs []string, machines map[string]infra.Machine, _ *tree.Tree) error { printer := tableprinter.New(os.Stdout) diff --git a/cmd/orbctl/machines.go b/cmd/orbctl/machines.go index 9ad17e456..38c63a11f 100644 --- a/cmd/orbctl/machines.go +++ b/cmd/orbctl/machines.go @@ -3,18 +3,19 @@ package main import ( "errors" + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/internal/api" "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra" "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" - cfg "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/tree" ) -func machines(monitor mntr.Monitor, gitClient *git.Client, orbConfig *cfg.Orb, do func(machineIDs []string, machines map[string]infra.Machine, desired *tree.Tree) error) error { +func machines(monitor mntr.Monitor, gitClient *git.Client, orbConfig *orbcfg.Orb, do func(machineIDs []string, machines map[string]infra.Machine, desired *tree.Tree) error) error { if err := orbConfig.IsConnectable(); err != nil { return err diff --git a/cmd/orbctl/main.go b/cmd/orbctl/main.go index 9d43b376f..e975d3bb0 100644 --- a/cmd/orbctl/main.go +++ b/cmd/orbctl/main.go @@ -32,31 +32,31 @@ func main() { github.ClientSecret = githubClientSecret github.Key = RandStringBytes(32) - rootCmd, rootValues := RootCommand() + rootCmd, getRootValues := RootCommand() rootCmd.Version = fmt.Sprintf("%s %s\n", version, gitCommit) - takeoff := TakeoffCommand(rootValues) + takeoff := TakeoffCommand(getRootValues) takeoff.AddCommand( - StartBoom(rootValues), - StartOrbiter(rootValues), - StartNetworking(rootValues), + StartBoom(getRootValues), + StartOrbiter(getRootValues), + StartNetworking(getRootValues), ) nodes := NodeCommand() nodes.AddCommand( - ReplaceCommand(rootValues), - RebootCommand(rootValues), - ExecCommand(rootValues), - ListCommand(rootValues), + ReplaceCommand(getRootValues), + RebootCommand(getRootValues), + ExecCommand(getRootValues), + ListCommand(getRootValues), ) rootCmd.AddCommand( - ReadSecretCommand(rootValues), - WriteSecretCommand(rootValues), - EditCommand(rootValues), - TeardownCommand(rootValues), - ConfigCommand(rootValues), - APICommand(rootValues), + ReadSecretCommand(getRootValues), + WriteSecretCommand(getRootValues), + EditCommand(getRootValues), + TeardownCommand(getRootValues), + ConfigCommand(getRootValues), + APICommand(getRootValues), takeoff, nodes, ) diff --git a/cmd/orbctl/node.go b/cmd/orbctl/node.go index e1dbac9bb..f1845fe38 100644 --- a/cmd/orbctl/node.go +++ b/cmd/orbctl/node.go @@ -3,10 +3,11 @@ package main import ( "fmt" + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/AlecAivazis/survey/v2" "github.com/caos/orbos/internal/api" "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/tree" @@ -24,7 +25,7 @@ func NodeCommand() *cobra.Command { } } -func requireMachines(monitor mntr.Monitor, gitClient *git.Client, orbConfig *orb.Orb, args []string, method func(machine infra.Machine) (required bool, require func(), unrequire func())) error { +func requireMachines(monitor mntr.Monitor, gitClient *git.Client, orbConfig *orbcfg.Orb, args []string, method func(machine infra.Machine) (required bool, require func(), unrequire func())) error { return machines(monitor, gitClient, orbConfig, func(machineIDs []string, machines map[string]infra.Machine, desired *tree.Tree) error { if len(args) <= 0 { diff --git a/cmd/orbctl/readsecret.go b/cmd/orbctl/readsecret.go index 742b80862..1907f9370 100644 --- a/cmd/orbctl/readsecret.go +++ b/cmd/orbctl/readsecret.go @@ -3,6 +3,8 @@ package main import ( "os" + "github.com/caos/orbos/pkg/kubernetes/cli" + "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/internal/secret/operators" @@ -10,7 +12,7 @@ import ( "github.com/spf13/cobra" ) -func ReadSecretCommand(rv RootValues) *cobra.Command { +func ReadSecretCommand(getRv GetRootValues) *cobra.Command { return &cobra.Command{ Use: "readsecret [path]", @@ -20,36 +22,34 @@ func ReadSecretCommand(rv RootValues) *cobra.Command { Example: `orbctl readsecret orbiter.k8s.kubeconfig > ~/.kube/config`, RunE: func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() - if err := orbConfig.IsComplete(); err != nil { - return err - } - - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - return err - } - - if err := gitClient.Clone(); err != nil { - return err - } + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient path := "" if len(args) > 0 { path = args[0] } + k8sClient, _, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops) + if err != nil && !rv.Gitops { + return err + } + err = nil + value, err := secret.Read( - monitor, - gitClient, + k8sClient, path, - operators.GetAllSecretsFunc(orbConfig, &version)) + operators.GetAllSecretsFunc(monitor, path == "", rv.Gitops, gitClient, k8sClient, orbConfig), + ) if err != nil { return err } diff --git a/cmd/orbctl/reboot.go b/cmd/orbctl/reboot.go index d85e1eb46..01154652a 100644 --- a/cmd/orbctl/reboot.go +++ b/cmd/orbctl/reboot.go @@ -1,25 +1,36 @@ package main import ( + "errors" + "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra" "github.com/spf13/cobra" ) -func RebootCommand(rv RootValues) *cobra.Command { +func RebootCommand(getRv GetRootValues) *cobra.Command { return &cobra.Command{ Use: "reboot", Short: "Gracefully reboot machines", Long: "Pass machine ids as arguments, omit arguments for selecting machines interactively", RunE: func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if !rv.Gitops { + return errors.New("reboot command is only supported with the --gitops flag and a committed orbiter.yml") + } + return requireMachines(monitor, gitClient, orbConfig, args, func(machine infra.Machine) (required bool, require func(), unrequire func()) { return machine.RebootRequired() }) diff --git a/cmd/orbctl/replace.go b/cmd/orbctl/replace.go index 805396a1c..c9d2ae036 100644 --- a/cmd/orbctl/replace.go +++ b/cmd/orbctl/replace.go @@ -1,25 +1,35 @@ package main import ( + "errors" + "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra" "github.com/spf13/cobra" ) -func ReplaceCommand(rv RootValues) *cobra.Command { +func ReplaceCommand(getRv GetRootValues) *cobra.Command { return &cobra.Command{ Use: "replace", Short: "Replace a node with a new machine available in the same pool", Long: "Pass machine ids as arguments, omit arguments for selecting machines interactively", RunE: func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if !rv.Gitops { + return errors.New("replace command is only supported with the --gitops flag and a committed orbiter.yml") + } + return requireMachines(monitor, gitClient, orbConfig, args, func(machine infra.Machine) (required bool, require func(), unrequire func()) { return machine.ReplacementRequired() }) diff --git a/cmd/orbctl/root.go b/cmd/orbctl/root.go index 86c06f31c..84832d678 100644 --- a/cmd/orbctl/root.go +++ b/cmd/orbctl/root.go @@ -6,22 +6,44 @@ import ( "github.com/caos/orbos/internal/helpers" "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/orb" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/spf13/cobra" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" ) -type RootValues func() (context.Context, mntr.Monitor, *orb.Orb, *git.Client, errFunc, error) +type RootValues struct { + Ctx context.Context + Monitor mntr.Monitor + Gitops bool + OrbConfig *orbcfg.Orb + Kubeconfig string + GitClient *git.Client + ErrFunc errFunc +} + +type GetRootValues func() (*RootValues, error) type errFunc func(err error) error -func RootCommand() (*cobra.Command, RootValues) { +func RootCommand() (*cobra.Command, GetRootValues) { + + ctx := context.Background() + rv := &RootValues{ + Ctx: ctx, + ErrFunc: func(err error) error { + if err != nil { + monitor.Error(err) + } + return nil + }, + } var ( - verbose bool orbConfigPath string + verbose bool ) cmd := &cobra.Command{ @@ -30,41 +52,47 @@ func RootCommand() (*cobra.Command, RootValues) { Long: `orbctl launches orbiters, booms, database-operators and networking-operators and simplifies common tasks such as updating your kubeconfig. Participate in our community on https://github.com/caos/orbos and visit our website at https://caos.ch`, - Example: `$ mkdir -p ~/.orb + Example: `$ # For being able to use the --gitops flag, you need to create an orbconfig and add an SSH deploy key to your github project +$ # Create an ssh key pair +$ ssh-keygen -b 2048 -t rsa -f ~/.ssh/myorbrepo -q -N "" +$ # Create the orbconfig +$ mkdir -p ~/.orb $ cat > ~/.orb/myorb << EOF +> # this is the ssh URL to your git repository > url: git@github.com:me/my-orb.git -> masterkey: "$(gopass my-secrets/orbs/myorb/masterkey)" +> masterkey: "$(openssl rand -base64 21)" # used for encrypting and decrypting secrets +> # the repokey is used to connect to your git repository > repokey: | > $(cat ~/.ssh/myorbrepo | sed s/^/\ \ /g) > EOF -$ orbctl -f ~/.orb/myorb [command] +$ orbctl --gitops -f ~/.orb/myorb [command] `, } flags := cmd.PersistentFlags() flags.StringVarP(&orbConfigPath, "orbconfig", "f", "~/.orb/config", "Path to the file containing the orbs git repo URL, deploy key and the master key for encrypting and decrypting secrets") + flags.StringVarP(&rv.Kubeconfig, "kubeconfig", "k", "~/.kube/config", "Path to the kubeconfig file to the cluster orbctl should target") + flags.BoolVar(&rv.Gitops, "gitops", false, "Run orbctl in gitops mode. Not specifying this flag is only supported for BOOM and Networking Operator") flags.BoolVar(&verbose, "verbose", false, "Print debug levelled logs") - return cmd, func() (context.Context, mntr.Monitor, *orb.Orb, *git.Client, errFunc, error) { + return cmd, func() (*RootValues, error) { if verbose { monitor = monitor.Verbose() } - - prunedPath := helpers.PruneHome(orbConfigPath) - orbConfig, err := orb.ParseOrbConfig(prunedPath) - if err != nil { - orbConfig = &orb.Orb{Path: prunedPath} - return nil, mntr.Monitor{}, nil, nil, nil, err - } - - ctx := context.Background() - - return ctx, monitor, orbConfig, git.New(ctx, monitor, "orbos", "orbos@caos.ch"), func(err error) error { + rv.Monitor = monitor + rv.Kubeconfig = helpers.PruneHome(rv.Kubeconfig) + rv.GitClient = git.New(ctx, monitor, "orbos", "orbos@caos.ch") + + var err error + if rv.Gitops { + prunedPath := helpers.PruneHome(orbConfigPath) + rv.OrbConfig, err = orb.ParseOrbConfig(prunedPath) if err != nil { - monitor.Error(err) + rv.OrbConfig = &orb.Orb{Path: prunedPath} } - return nil - }, nil + } + + return rv, err } } diff --git a/cmd/orbctl/takeoff.go b/cmd/orbctl/takeoff.go index d6e33428d..52e3f2477 100644 --- a/cmd/orbctl/takeoff.go +++ b/cmd/orbctl/takeoff.go @@ -1,22 +1,31 @@ package main import ( + "log" + "net/http" + _ "net/http/pprof" + + "github.com/caos/orbos/pkg/kubernetes/cli" + + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/cmd/orbctl/cmds" - "github.com/caos/orbos/internal/start" - kubernetes2 "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/internal/ctrlcrd" + "github.com/caos/orbos/internal/ctrlgitops" "github.com/pkg/errors" "github.com/spf13/cobra" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" ) -func TakeoffCommand(rv RootValues) *cobra.Command { +func TakeoffCommand(getRv GetRootValues) *cobra.Command { var ( verbose bool recur bool destroy bool deploy bool - kubeconfig string ingestionAddress string + gitOpsBoom bool + gitOpsNetworking bool cmd = &cobra.Command{ Use: "takeoff", Short: "Launch an orbiter", @@ -27,22 +36,27 @@ func TakeoffCommand(rv RootValues) *cobra.Command { flags := cmd.Flags() flags.BoolVar(&recur, "recur", false, "Ensure the desired state continously") flags.BoolVar(&deploy, "deploy", true, "Ensure Orbiter and Boom deployments continously") + flags.BoolVar(&gitOpsBoom, "gitops-boom", false, "Ensure Boom runs in gitops mode") + flags.BoolVar(&gitOpsNetworking, "gitops-networking", false, "Ensure Networking-operator runs in gitops mode") flags.StringVar(&ingestionAddress, "ingestion", "", "Ingestion API address") - flags.StringVar(&kubeconfig, "kubeconfig", "", "Kubeconfig for boom deployment") cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { if recur && destroy { - return errors.New("flags --recur and --destroy are mutually exclusive, please provide eighter one or none") + return errors.New("flags --recur and --destroy are mutually exclusive, please provide either one or none") } - ctx, monitor, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + ctx := rv.Ctx + return cmds.Takeoff( monitor, ctx, @@ -55,19 +69,22 @@ func TakeoffCommand(rv RootValues) *cobra.Command { ingestionAddress, version, gitCommit, - kubeconfig, + rv.Kubeconfig, + rv.Gitops || gitOpsBoom, + rv.Gitops || gitOpsNetworking, ) } return cmd } -func StartOrbiter(rv RootValues) *cobra.Command { +func StartOrbiter(getRv GetRootValues) *cobra.Command { var ( verbose bool recur bool destroy bool deploy bool ingestionAddress string + pprof bool cmd = &cobra.Command{ Use: "orbiter", Short: "Launch an orbiter", @@ -78,6 +95,7 @@ func StartOrbiter(rv RootValues) *cobra.Command { flags := cmd.Flags() flags.BoolVar(&recur, "recur", true, "Ensure the desired state continously") flags.BoolVar(&deploy, "deploy", true, "Ensure Orbiter deployment continously") + flags.BoolVar(&pprof, "pprof", false, "Start pprof to analyse memory usage") flags.StringVar(&ingestionAddress, "ingestion", "", "Ingestion API address") cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { @@ -85,19 +103,28 @@ func StartOrbiter(rv RootValues) *cobra.Command { return errors.New("flags --recur and --destroy are mutually exclusive, please provide eighter one or none") } - ctx, monitor, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + ctx := rv.Ctx + + if err := orbcfg.IsComplete(orbConfig); err != nil { + return err + } + if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { return err } - orbiterConfig := &start.OrbiterConfig{ + orbiterConfig := &ctrlgitops.OrbiterConfig{ Recur: recur, Destroy: destroy, Deploy: deploy, @@ -108,16 +135,21 @@ func StartOrbiter(rv RootValues) *cobra.Command { IngestionAddress: ingestionAddress, } - _, err = start.Orbiter(ctx, monitor, orbiterConfig, gitClient, orbConfig, version) - return err + if pprof { + go func() { + log.Println(http.ListenAndServe("localhost:6060", nil)) + }() + } + + return ctrlgitops.Orbiter(ctx, monitor, orbiterConfig, gitClient) } return cmd } -func StartBoom(rv RootValues) *cobra.Command { +func StartBoom(getRv GetRootValues) *cobra.Command { var ( - localmode bool - cmd = &cobra.Command{ + metricsAddr string + cmd = &cobra.Command{ Use: "boom", Short: "Launch a boom", Long: "Ensures a desired state", @@ -125,50 +157,68 @@ func StartBoom(rv RootValues) *cobra.Command { ) flags := cmd.Flags() - flags.BoolVar(&localmode, "localmode", false, "Local mode for boom") + flags.StringVar(&metricsAddr, "metrics-addr", "", "The address the metric endpoint binds to.") cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, _, errFunc, err := rv() + + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() - return start.Boom(monitor, orbConfig.Path, localmode, version) + monitor := rv.Monitor + orbConfig := rv.OrbConfig + + monitor.Info("Takeoff Boom") + + if rv.Gitops { + return ctrlgitops.Boom(monitor, orbConfig.Path, version) + } else { + return ctrlcrd.Start(monitor, version, "/boom", metricsAddr, "", ctrlcrd.Boom) + } } return cmd } -func StartNetworking(rv RootValues) *cobra.Command { +func StartNetworking(getRv GetRootValues) *cobra.Command { var ( - kubeconfig string - cmd = &cobra.Command{ + metricsAddr string + cmd = &cobra.Command{ Use: "networking", Short: "Launch a networking operator", Long: "Ensures a desired state of networking for an application", } ) flags := cmd.Flags() - flags.StringVar(&kubeconfig, "kubeconfig", "", "kubeconfig used by zitadel operator") + flags.StringVar(&metricsAddr, "metrics-addr", "", "The address the metric endpoint binds to.") cmd.RunE = func(cmd *cobra.Command, args []string) error { - _, monitor, orbConfig, _, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() - k8sClient, err := kubernetes2.NewK8sClientWithPath(monitor, kubeconfig) - if err != nil { - return err - } + monitor := rv.Monitor + orbConfig := rv.OrbConfig + + monitor.Info("Takeoff Networking") + + if rv.Gitops { + + k8sClient, _, err := cli.Client(monitor, orbConfig, rv.GitClient, rv.Kubeconfig, rv.Gitops) + if err != nil { + return err + } - if k8sClient.Available() { - return start.Networking(monitor, orbConfig.Path, k8sClient, &version) + return ctrlgitops.Networking(monitor, orbConfig.Path, k8sClient, &version) + } else { + return ctrlcrd.Start(monitor, version, "/boom", metricsAddr, rv.Kubeconfig, ctrlcrd.Networking) } return nil } diff --git a/cmd/orbctl/teardown.go b/cmd/orbctl/teardown.go index 5c760f46c..2f728f883 100644 --- a/cmd/orbctl/teardown.go +++ b/cmd/orbctl/teardown.go @@ -1,19 +1,22 @@ package main import ( + "errors" "fmt" "strings" + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/internal/api" "github.com/spf13/cobra" "github.com/caos/orbos/internal/operator/orbiter" - "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" + orbadapter "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" ) -func TeardownCommand(rv RootValues) *cobra.Command { +func TeardownCommand(getRv GetRootValues) *cobra.Command { var ( cmd = &cobra.Command{ @@ -45,15 +48,24 @@ func TeardownCommand(rv RootValues) *cobra.Command { ) cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { - _, monitor, orbConfig, gitClient, errFunc, err := rv() + + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() - if err := orbConfig.IsComplete(); err != nil { + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + + if !rv.Gitops { + return errors.New("teardown command is only supported with the --gitops flag and a committed orbiter.yml") + } + + if err := orbcfg.IsComplete(orbConfig); err != nil { return err } @@ -88,7 +100,7 @@ func TeardownCommand(rv RootValues) *cobra.Command { return orbiter.Destroy( monitor, gitClient, - orb.AdaptFunc( + orbadapter.AdaptFunc( labels.NoopOperator("ORBOS"), orbConfig, gitCommit, diff --git a/cmd/orbctl/writesecret.go b/cmd/orbctl/writesecret.go index 2f8416112..6002d2317 100644 --- a/cmd/orbctl/writesecret.go +++ b/cmd/orbctl/writesecret.go @@ -1,17 +1,20 @@ package main import ( - "github.com/caos/orbos/internal/secret/operators" "io/ioutil" "os" + "github.com/caos/orbos/pkg/kubernetes/cli" + + "github.com/caos/orbos/internal/secret/operators" + "github.com/caos/orbos/pkg/secret" "github.com/pkg/errors" "github.com/spf13/cobra" ) -func WriteSecretCommand(rv RootValues) *cobra.Command { +func WriteSecretCommand(getRv GetRootValues) *cobra.Command { var ( value string @@ -40,41 +43,38 @@ orbctl writesecret mygceprovider.google_application_credentials_value --value "$ return err } - _, monitor, orbConfig, gitClient, errFunc, err := rv() + rv, err := getRv() if err != nil { return err } defer func() { - err = errFunc(err) + err = rv.ErrFunc(err) }() - if err := orbConfig.IsComplete(); err != nil { - return err - } - - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - return err - } - - if err := gitClient.Clone(); err != nil { - return err - } + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient path := "" if len(args) > 0 { path = args[0] } - if err := secret.Write( + k8sClient, _, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops) + if err != nil && !rv.Gitops { + return err + } + err = nil + + return secret.Write( monitor, - gitClient, + k8sClient, path, s, - operators.GetAllSecretsFunc(orbConfig, &version), - operators.PushFunc()); err != nil { - return err - } - return nil + "orbctl", + version, + operators.GetAllSecretsFunc(monitor, true, rv.Gitops, gitClient, k8sClient, orbConfig), + operators.PushFunc(monitor, rv.Gitops, gitClient, k8sClient)) } return cmd } diff --git a/cmd/takeoff-debug/main.go b/cmd/takeoff-debug/main.go index 10dae9b0f..f2bbbce84 100644 --- a/cmd/takeoff-debug/main.go +++ b/cmd/takeoff-debug/main.go @@ -2,17 +2,20 @@ package main import ( "flag" + "github.com/caos/orbos/cmd/orbctl/cmds" "github.com/caos/orbos/internal/helpers" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/orb" + orbcfg "github.com/caos/orbos/pkg/orb" "golang.org/x/net/context" ) func main() { orbConfigPath := flag.String("orbconfig", "~/.orb/config", "The orbconfig file to use") kubeconfig := flag.String("kubeconfig", "~/.kube/config", "The kubeconfig file to use") + gitops := flag.Bool("gitops", false, "Use gitops mode") verbose := flag.Bool("verbose", false, "Print debug levelled logs") flag.Parse() @@ -20,7 +23,7 @@ func main() { prunedPath := helpers.PruneHome(*orbConfigPath) orbConfig, err := orb.ParseOrbConfig(prunedPath) if err != nil { - orbConfig = &orb.Orb{Path: prunedPath} + orbConfig = &orbcfg.Orb{Path: prunedPath} } monitor := mntr.Monitor{ @@ -47,9 +50,11 @@ func main() { true, *verbose, "", - string(version), - string(gitCommit), + version, + gitCommit, *kubeconfig, + *gitops, + *gitops, ); err != nil { monitor.Error(err) panic(err) diff --git a/go.mod b/go.mod index 42f08c352..1ad002ad2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/caos/orbos go 1.14 require ( - cloud.google.com/go/storage v1.6.0 github.com/AlecAivazis/survey/v2 v2.0.8 github.com/AppsFlyer/go-sundheit v0.2.0 github.com/aws/aws-sdk-go v1.31.12 @@ -11,36 +10,37 @@ require ( github.com/cloudflare/cloudflare-go v0.12.1 github.com/cloudscale-ch/cloudscale-go-sdk v1.6.0 github.com/ghodss/yaml v1.0.0 + github.com/go-git/go-billy/v5 v5.0.0 + github.com/go-git/go-git/v5 v5.2.0 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.2 github.com/google/go-github/v31 v31.0.0 - github.com/googleapis/gnostic v0.3.1 // indirect - github.com/imdario/mergo v0.3.6 // indirect github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23 + github.com/kr/pty v1.1.8 // indirect github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1 - github.com/manifoldco/promptui v0.7.0 github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-isatty v0.0.11 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/pires/go-proxyproto v0.3.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.6.0 + github.com/prometheus/client_golang v1.7.1 github.com/satori/go.uuid v1.2.0 - github.com/spf13/cobra v0.0.7 + github.com/spf13/cobra v1.0.0 github.com/stretchr/testify v1.6.1 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 - golang.org/x/net v0.0.0-20200625001655-4c5254603344 + golang.org/x/net v0.0.0-20200707034311-ab3426394381 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d google.golang.org/api v0.26.0 google.golang.org/grpc v1.29.1 - google.golang.org/protobuf v1.23.0 - gopkg.in/src-d/go-billy.v4 v4.3.2 - gopkg.in/src-d/go-git.v4 v4.13.1 + google.golang.org/protobuf v1.24.0 gopkg.in/yaml.v2 v2.3.0 - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c - k8s.io/api v0.18.5 - k8s.io/apiextensions-apiserver v0.18.5 - k8s.io/apimachinery v0.18.5 - k8s.io/client-go v0.18.5 + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 + k8s.io/api v0.19.2 + k8s.io/apiextensions-apiserver v0.19.2 + k8s.io/apimachinery v0.19.2 + k8s.io/client-go v0.19.2 k8s.io/kubectl v0.18.3 + sigs.k8s.io/controller-runtime v0.7.0 + sigs.k8s.io/controller-tools v0.4.1 + sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 8f5abe03e..4d5aa0a35 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,7 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4= @@ -34,10 +35,14 @@ github.com/AppsFlyer/go-sundheit v0.2.0/go.mod h1:rCRkVTMQo7/krF7xQ9X0XEF1an68vi github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= @@ -80,7 +85,6 @@ github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/caos/oidc v0.6.2 h1:ejp6uTepVSlgLoPhXIAqFe8SbCdoxqO4vZv1H4fF0Yk= github.com/caos/oidc v0.6.2/go.mod h1:ozoi3b+aY33gzdvjz4w90VZShIHGsmDa0goruuV0arQ= -github.com/caos/zitadel v0.110.1 h1:53wDYmd7g+zoVSje33Mxs17gq25HNxAQW8Cr2PCDo1U= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -117,6 +121,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -146,6 +152,9 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -154,6 +163,8 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -161,6 +172,14 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= +github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= +github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= +github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= +github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -169,6 +188,11 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= +github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4= +github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -214,6 +238,8 @@ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2K github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/flect v0.2.0 h1:EWCvMGGxOjsgwlWaP+f4+Hh6yrrte7JeFL2S6b+0hdM= +github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= @@ -243,6 +269,7 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= @@ -257,6 +284,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6CCb0plo= github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= @@ -281,8 +310,10 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -300,6 +331,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= @@ -307,27 +340,22 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23 h1:M8exrBzuhWcU6aoHJlHWPe4qFjVKzkMGRal78f5jRRU= github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23/go.mod h1:kBSna6b0/RzsOcOZf515vAXwSsXYusl2U7SA0XP09yI= @@ -337,28 +365,23 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1 h1:xUwSaTDYl+Ib5OoFxWJnqYFG9N31++qfeNXzTZ1cc8o= github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1/go.mod h1:f0X1c0za3TbET/rl5ThtCSel0+G3/yZ8iuU9BxnyVK0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -366,8 +389,6 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4= -github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= @@ -380,8 +401,9 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 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/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -389,6 +411,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -399,19 +422,24 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pires/go-proxyproto v0.3.0 h1:++BY4zWOpWha50IDjdnp7+NRTLuOHqMQC5PkgS7I4u4= @@ -420,14 +448,13 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.6.0 h1:YVPodQOcK15POxhgARIvnDRVpLcuK8mglnMrWfyrw6A= -github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= +github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -436,13 +463,13 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= -github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -450,8 +477,9 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -464,8 +492,8 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU= -github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -474,8 +502,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= -github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -484,7 +511,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -501,9 +527,12 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -515,8 +544,14 @@ go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -528,10 +563,11 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -555,7 +591,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -563,8 +598,9 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -593,9 +629,12 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190517181255-950ef44c6e07/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -610,7 +649,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -618,7 +656,6 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -636,9 +673,12 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -648,16 +688,20 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -681,12 +725,15 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -701,12 +748,16 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5 h1:UaoXseXAWUJUcuJ2E2oczJdLxAJXL0lOmVaBl7kuk+I= +golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= +gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -723,8 +774,8 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -742,8 +793,9 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -762,16 +814,18 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -780,13 +834,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= -gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= -gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -799,55 +846,79 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA= -k8s.io/api v0.18.5 h1:fKbCxr+U3fu7k6jB+QeYPD/c6xKYeSJ2KVWmyUypuWM= -k8s.io/api v0.18.5/go.mod h1:tN+e/2nbdGKOAH55NMV8oGrMG+3uRlA9GaRfvnCCSNk= -k8s.io/apiextensions-apiserver v0.18.5 h1:pvbXjB/BRXZiO+/Erp5Pxr+lnhDCv5uxNxHh3FLGZ/g= -k8s.io/apiextensions-apiserver v0.18.5/go.mod h1:woZ7PkEIMHjhHIyApvOwkGOkBLUYKuet0VWVkPTQ/Fs= +k8s.io/api v0.19.2 h1:q+/krnHWKsL7OBZg/rxnycsl9569Pud76UJ77MvKXms= +k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= +k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= +k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= +k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= +k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.18.5 h1:Lh6tgsM9FMkC12K5T5QjRm7rDs6aQN5JHkA0JomULDM= -k8s.io/apimachinery v0.18.5/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apiserver v0.18.5/go.mod h1:+1XgOMq7YJ3OyqPNSJ54EveHwCoBWcJT9CaPycYI5ps= +k8s.io/apimachinery v0.19.2 h1:5Gy9vQpAGTKHPVOh5c4plE274X8D/6cuEiTO2zve7tc= +k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= +k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= k8s.io/cli-runtime v0.18.3/go.mod h1:pqbbi4nqRIQhUWAVzen8uE8DD/zcZLwf+8sQYO4lwLk= +k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= -k8s.io/client-go v0.18.5 h1:cLhGZdOmyPhwtt20Lrb7uAqxxB1uvY+NTmNJvno1oKA= -k8s.io/client-go v0.18.5/go.mod h1:EsiD+7Fx+bRckKWZXnAXRKKetm1WuzPagH4iOSC8x58= +k8s.io/client-go v0.19.2 h1:gMJuU3xJZs86L1oQ99R4EViAADUPMHHtS9jFshasHSc= +k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= +k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= -k8s.io/code-generator v0.18.5/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= +k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k= -k8s.io/component-base v0.18.5/go.mod h1:RSbcboNk4B+S8Acs2JaBOVW3XNz1+A637s2jL+QQrlU= +k8s.io/component-base v0.19.2 h1:jW5Y9RcZTb79liEhW3XDVTW7MuvEGP0tQZnfSX6/+gs= +k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kubectl v0.18.3 h1:WvlO1MQvteqrpoX1SgYf5TZ+ofTGvdkhoNELzc2EBkQ= k8s.io/kubectl v0.18.3/go.mod h1:k/EpvXBDgEsHBzWr0A44l9+ArvYi3txBBnzXBjQasUQ= k8s.io/metrics v0.18.3/go.mod h1:TkuJE3ezDZ1ym8pYkZoEzJB7HDiFE7qxl+EmExEBoPA= -k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= +sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= +sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= +sigs.k8s.io/controller-tools v0.4.1 h1:VkuV0MxlRPmRu5iTgBZU4UxUX2LiR99n3sdQGRxZF4w= +sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt new file mode 100644 index 000000000..767efde98 --- /dev/null +++ b/hack/boilerplate.go.txt @@ -0,0 +1,15 @@ +/* + + +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. +*/ \ No newline at end of file diff --git a/internal/api/boom/api.go b/internal/api/boom/api.go new file mode 100644 index 000000000..6fd7b5071 --- /dev/null +++ b/internal/api/boom/api.go @@ -0,0 +1,57 @@ +package boom + +import ( + v1 "github.com/caos/orbos/internal/api/boom/v1" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "gopkg.in/yaml.v3" + macherrs "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +const ( + Namespace = "caos-system" + Name = "boom" +) + +func ReadCRD(k8sClient kubernetes.ClientInt) (*tree.Tree, error) { + unstruct, err := k8sClient.GetNamespacedCRDResource(v1.GroupVersion.Group, v1.GroupVersion.Version, "Boom", Namespace, Name) + if err != nil && !macherrs.IsNotFound(err) && !meta.IsNoMatchError(err) { + return nil, err + } + err = nil + + var data []byte + if unstruct == nil { + unstruct = &unstructured.Unstructured{Object: v1.GetEmpty(Namespace, Name)} + err = nil + } + + dataInt, err := yaml.Marshal(unstruct.Object) + if err != nil { + return nil, err + } + data = dataInt + + desired := &tree.Tree{} + return desired, yaml.Unmarshal(data, desired) +} + +func WriteCrd(k8sClient kubernetes.ClientInt, t *tree.Tree) error { + + data, err := yaml.Marshal(t) + if err != nil { + return err + } + + unstruct := &unstructured.Unstructured{ + Object: make(map[string]interface{}), + } + + if err := yaml.Unmarshal(data, unstruct.Object); err != nil { + return err + } + + return k8sClient.ApplyNamespacedCRDResource(v1.GroupVersion.Group, v1.GroupVersion.Version, "Boom", Namespace, Name, unstruct) +} diff --git a/internal/api/boom/v1/boom.go b/internal/api/boom/v1/boom.go new file mode 100644 index 000000000..3b6c8725e --- /dev/null +++ b/internal/api/boom/v1/boom.go @@ -0,0 +1,102 @@ +// +kubebuilder:object:generate=true +// +groupName=caos.ch +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "caos.ch", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// +kubebuilder:storageversion +// +kubebuilder:object:root=true +// +kubebuilder:crd=Boom +type Boom struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec *Empty `json:"spec,omitempty"` + Status Status `json:"status,omitempty"` +} + +type Status struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +type Empty struct{} + +// +kubebuilder:object:root=true +type BoomList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Boom `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Boom{}, &BoomList{}) +} + +func GetEmpty(namespace, name string) map[string]interface{} { + return map[string]interface{}{ + "apiVersion": "caos.ch/v1", + "kind": "Boom", + "metadata": map[string]interface{}{ + "name": name, + "namespace": namespace, + }, + "spec": map[string]interface{}{ + "forceApply": true, + "postApply": map[string]interface{}{ + "deploy": false, + }, + "preApply": map[string]interface{}{ + "deploy": false, + }, + "metricCollection": map[string]interface{}{ + "deploy": false, + }, + "logCollection": map[string]interface{}{ + "deploy": false, + }, + "nodeMetricsExporter": map[string]interface{}{ + "deploy": false, + }, + "systemdMetricsExporter": map[string]interface{}{ + "deploy": false, + }, + "monitoring": map[string]interface{}{ + "deploy": false, + }, + "apiGateway": map[string]interface{}{ + "deploy": false, + }, + "kubeMetricsExporter": map[string]interface{}{ + "deploy": false, + }, + "reconciling": map[string]interface{}{ + "deploy": false, + }, + "metricsPersisting": map[string]interface{}{ + "deploy": false, + }, + "logsPersisting": map[string]interface{}{ + "deploy": false, + }, + "metricsServer": map[string]interface{}{ + "deploy": false, + }, + }, + } +} diff --git a/internal/api/boom/v1/zz_generated.deepcopy.go b/internal/api/boom/v1/zz_generated.deepcopy.go new file mode 100644 index 000000000..a6b1244b3 --- /dev/null +++ b/internal/api/boom/v1/zz_generated.deepcopy.go @@ -0,0 +1,118 @@ +// +build !ignore_autogenerated + +/* + + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Boom) DeepCopyInto(out *Boom) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(Empty) + **out = **in + } + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Boom. +func (in *Boom) DeepCopy() *Boom { + if in == nil { + return nil + } + out := new(Boom) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Boom) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BoomList) DeepCopyInto(out *BoomList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Boom, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BoomList. +func (in *BoomList) DeepCopy() *BoomList { + if in == nil { + return nil + } + out := new(BoomList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BoomList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Empty) DeepCopyInto(out *Empty) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Empty. +func (in *Empty) DeepCopy() *Empty { + if in == nil { + return nil + } + out := new(Empty) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/internal/api/boom/v1beta1/boom.go b/internal/api/boom/v1beta1/boom.go new file mode 100644 index 000000000..cbd2c3960 --- /dev/null +++ b/internal/api/boom/v1beta1/boom.go @@ -0,0 +1,48 @@ +// +kubebuilder:object:generate=true +// +groupName=caos.ch +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "caos.ch", Version: "v1beta1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// +kubebuilder:object:root=true +// +kubebuilder:crd=Boom +type Boom struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec *Empty `json:"spec,omitempty"` + Status Status `json:"status,omitempty"` +} + +type Status struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +type Empty struct{} + +// +kubebuilder:object:root=true +type BoomList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Boom `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Boom{}, &BoomList{}) +} diff --git a/internal/api/boom/v1beta1/zz_generated.deepcopy.go b/internal/api/boom/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000..552cdc688 --- /dev/null +++ b/internal/api/boom/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,118 @@ +// +build !ignore_autogenerated + +/* + + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Boom) DeepCopyInto(out *Boom) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(Empty) + **out = **in + } + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Boom. +func (in *Boom) DeepCopy() *Boom { + if in == nil { + return nil + } + out := new(Boom) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Boom) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BoomList) DeepCopyInto(out *BoomList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Boom, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BoomList. +func (in *BoomList) DeepCopy() *BoomList { + if in == nil { + return nil + } + out := new(BoomList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BoomList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Empty) DeepCopyInto(out *Empty) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Empty. +func (in *Empty) DeepCopy() *Empty { + if in == nil { + return nil + } + out := new(Empty) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/internal/api/boom/v1beta2/boom.go b/internal/api/boom/v1beta2/boom.go new file mode 100644 index 000000000..e60103aca --- /dev/null +++ b/internal/api/boom/v1beta2/boom.go @@ -0,0 +1,48 @@ +// +kubebuilder:object:generate=true +// +groupName=caos.ch +package v1beta2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "caos.ch", Version: "v1beta2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// +kubebuilder:object:root=true +// +kubebuilder:crd=Boom +type Boom struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec *Empty `json:"spec,omitempty"` + Status Status `json:"status,omitempty"` +} + +type Status struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +type Empty struct{} + +// +kubebuilder:object:root=true +type BoomList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Boom `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Boom{}, &BoomList{}) +} diff --git a/internal/api/boom/v1beta2/zz_generated.deepcopy.go b/internal/api/boom/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 000000000..6cf034917 --- /dev/null +++ b/internal/api/boom/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,118 @@ +// +build !ignore_autogenerated + +/* + + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Boom) DeepCopyInto(out *Boom) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(Empty) + **out = **in + } + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Boom. +func (in *Boom) DeepCopy() *Boom { + if in == nil { + return nil + } + out := new(Boom) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Boom) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BoomList) DeepCopyInto(out *BoomList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Boom, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BoomList. +func (in *BoomList) DeepCopy() *BoomList { + if in == nil { + return nil + } + out := new(BoomList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BoomList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Empty) DeepCopyInto(out *Empty) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Empty. +func (in *Empty) DeepCopy() *Empty { + if in == nil { + return nil + } + out := new(Empty) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/internal/api/networking/api.go b/internal/api/networking/api.go new file mode 100644 index 000000000..8be838847 --- /dev/null +++ b/internal/api/networking/api.go @@ -0,0 +1,76 @@ +package networking + +import ( + "errors" + + "gopkg.in/yaml.v3" + + v1 "github.com/caos/orbos/internal/api/networking/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + macherrs "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" +) + +const ( + Namespace = "caos-system" + kind = "Networking" + apiVersion = "caos.ch/v1" + Name = "networking" +) + +func ReadCRD(k8sClient kubernetes.ClientInt) (*tree.Tree, error) { + + unstruct, err := k8sClient.GetNamespacedCRDResource(v1.GroupVersion.Group, v1.GroupVersion.Version, kind, Namespace, Name) + if err != nil { + if macherrs.IsNotFound(err) || meta.IsNoMatchError(err) { + return nil, nil + } + return nil, err + } + + spec, found := unstruct.Object["spec"] + if !found { + return nil, errors.New("no spec in crd") + } + specMap, ok := spec.(map[string]interface{}) + if !ok { + return nil, errors.New("no spec in crd") + } + + data, err := yaml.Marshal(specMap) + if err != nil { + return nil, err + } + + desired := &tree.Tree{} + return desired, yaml.Unmarshal(data, desired) +} + +func WriteCrd(k8sClient kubernetes.ClientInt, t *tree.Tree) error { + + data, err := yaml.Marshal(t) + if err != nil { + return err + } + + unstruct := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "spec": make(map[string]interface{}), + }, + } + + if err := yaml.Unmarshal(data, unstruct.Object["spec"]); err != nil { + return err + } + + unstruct.SetName(Name) + unstruct.SetNamespace(Namespace) + unstruct.SetKind(kind) + unstruct.SetAPIVersion(apiVersion) + + return k8sClient.ApplyNamespacedCRDResource(v1.GroupVersion.Group, v1.GroupVersion.Version, kind, Namespace, Name, unstruct) +} diff --git a/internal/api/networking/v1/networking.go b/internal/api/networking/v1/networking.go new file mode 100644 index 000000000..7ca818b47 --- /dev/null +++ b/internal/api/networking/v1/networking.go @@ -0,0 +1,57 @@ +// +kubebuilder:object:generate=true +// +groupName=caos.ch +package v1 + +import ( + orbnw "github.com/caos/orbos/internal/operator/networking/kinds/orb" + "github.com/caos/orbos/pkg/tree" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "caos.ch", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// +kubebuilder:storageversion +// +kubebuilder:object:root=true +// +kubebuilder:crd=Networking +type Networking struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec Spec `json:"spec,omitempty"` + Status Status `json:"status,omitempty"` +} + +type Status struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +type Spec struct { + Common *tree.Common `json:",inline" yaml:",inline"` + Spec *orbnw.Spec `json:"spec" yaml:"spec"` + Networking *Empty `json:"networking" yaml:"networking"` +} + +type Empty struct{} + +// +kubebuilder:object:root=true +type NetworkingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Networking `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Networking{}, &NetworkingList{}) +} diff --git a/internal/api/networking/v1/zz_generated.deepcopy.go b/internal/api/networking/v1/zz_generated.deepcopy.go new file mode 100644 index 000000000..05925275e --- /dev/null +++ b/internal/api/networking/v1/zz_generated.deepcopy.go @@ -0,0 +1,146 @@ +// +build !ignore_autogenerated + +/* + + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + "github.com/caos/orbos/internal/operator/networking/kinds/orb" + "github.com/caos/orbos/pkg/tree" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Empty) DeepCopyInto(out *Empty) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Empty. +func (in *Empty) DeepCopy() *Empty { + if in == nil { + return nil + } + out := new(Empty) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Networking) DeepCopyInto(out *Networking) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking. +func (in *Networking) DeepCopy() *Networking { + if in == nil { + return nil + } + out := new(Networking) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Networking) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkingList) DeepCopyInto(out *NetworkingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Networking, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkingList. +func (in *NetworkingList) DeepCopy() *NetworkingList { + if in == nil { + return nil + } + out := new(NetworkingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.Common != nil { + in, out := &in.Common, &out.Common + *out = new(tree.Common) + **out = **in + } + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(orb.Spec) + (*in).DeepCopyInto(*out) + } + if in.Networking != nil { + in, out := &in.Networking, &out.Networking + *out = new(Empty) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/internal/cmd/headed.go b/internal/cmd/headed.go deleted file mode 100644 index c1f78a00c..000000000 --- a/internal/cmd/headed.go +++ /dev/null @@ -1,5 +0,0 @@ -package cmd - -type Headed interface { - Headers() interface{} -} diff --git a/internal/ctrlcrd/boom/boom.go b/internal/ctrlcrd/boom/boom.go new file mode 100644 index 000000000..009f7ad26 --- /dev/null +++ b/internal/ctrlcrd/boom/boom.go @@ -0,0 +1,56 @@ +package boom + +import ( + "context" + "fmt" + "path/filepath" + + "github.com/caos/orbos/internal/api/boom" + + v1 "github.com/caos/orbos/internal/api/boom/v1" + "github.com/caos/orbos/internal/operator/boom/app" + gconfig "github.com/caos/orbos/internal/operator/boom/application/applications/grafana/config" + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" +) + +type Reconciler struct { + kubernetes.ClientInt + Monitor mntr.Monitor + Scheme *runtime.Scheme + ToolsDirectoryPath string + Version string +} + +func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) { + internalMonitor := r.Monitor.WithFields(map[string]interface{}{ + "kind": "Boom", + "name": req.NamespacedName, + }) + + defer func() { + r.Monitor.Error(err) + }() + + if req.Namespace != boom.Namespace || req.Name != boom.Name { + return res, fmt.Errorf("resource must be named %s and namespaced in %s", boom.Name, boom.Namespace) + } + + desired, err := boom.ReadCRD(r) + if err != nil { + return res, err + } + + gconfig.DashboardsDirectoryPath = filepath.Join(r.ToolsDirectoryPath, "dashboards") + appStruct := app.New(internalMonitor, r.ToolsDirectoryPath) + + return res, appStruct.ReconcileCrd(req.NamespacedName.String(), desired) +} + +func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&v1.Boom{}). + Complete(r) +} diff --git a/internal/ctrlcrd/controller.go b/internal/ctrlcrd/controller.go new file mode 100644 index 000000000..42e852a0a --- /dev/null +++ b/internal/ctrlcrd/controller.go @@ -0,0 +1,106 @@ +package ctrlcrd + +import ( + "fmt" + + boomv1 "github.com/caos/orbos/internal/api/boom/v1" + networkingv1 "github.com/caos/orbos/internal/api/networking/v1" + "github.com/caos/orbos/internal/ctrlcrd/boom" + "github.com/caos/orbos/internal/ctrlcrd/networking" + "github.com/caos/orbos/internal/utils/clientgo" + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + macherrs "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" +) + +const ( + Networking = "networking" + Boom = "boom" +) + +var ( + scheme = runtime.NewScheme() +) + +func init() { + if err := clientgoscheme.AddToScheme(scheme); err != nil { + panic(fmt.Errorf("adding clientgo to scheme failed: %w", err)) + } + + if err := networkingv1.AddToScheme(scheme); err != nil { + panic(fmt.Errorf("adding networking v1 to scheme failed: %w", err)) + } + + if err := boomv1.AddToScheme(scheme); err != nil { + panic(fmt.Errorf("adding boom v1 to scheme failed: %w", err)) + } + +} + +func Start(monitor mntr.Monitor, version, toolsDirectoryPath, metricsAddr string, kubeconfig string, features ...string) error { + + cfg, err := clientgo.GetClusterConfig(monitor, kubeconfig) + if err != nil { + return err + } + + k8sClient := kubernetes.NewK8sClientWithConfig(monitor, cfg) + if _, err := k8sClient.GetConfigMap("kube-public", "cluster-info"); err != nil { + if macherrs.IsNotFound(err) { + // This one and other client errors mean that the connection is basically possible + err = nil + } else { + return err + } + } + monitor.Info("successfully connected to kubernetes cluster") + + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + LeaderElection: false, + LeaderElectionID: "98jasd12l.caos.ch", + }) + if err != nil { + return fmt.Errorf("starting manager failed: %w", err) + } + + for _, feature := range features { + switch feature { + case Networking: + monitor.Debug("Setting up networking") + if err = (&networking.Reconciler{ + ClientInt: k8sClient, + Monitor: monitor, + Scheme: mgr.GetScheme(), + Version: version, + }).SetupWithManager(mgr); err != nil { + return fmt.Errorf("creating controller failed: %w", err) + } + monitor.Debug("Networking setup done") + case Boom: + monitor.Debug("Setting up BOOM") + if err = (&boom.Reconciler{ + ClientInt: k8sClient, + Monitor: monitor, + Scheme: mgr.GetScheme(), + ToolsDirectoryPath: toolsDirectoryPath, + Version: version, + }).SetupWithManager(mgr); err != nil { + return fmt.Errorf("creating controller failed: %w", err) + } + monitor.Debug("BOOM setup done") + } + } + + monitor.Debug("Controller is starting") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + return fmt.Errorf("running manager failed: %w", err) + } + monitor.Debug("Controller is done") + return nil +} diff --git a/internal/ctrlcrd/networking/networking.go b/internal/ctrlcrd/networking/networking.go new file mode 100644 index 000000000..f93789119 --- /dev/null +++ b/internal/ctrlcrd/networking/networking.go @@ -0,0 +1,67 @@ +package networking + +import ( + "context" + "errors" + "fmt" + + "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/config" + + "github.com/caos/orbos/internal/api/networking" + v1 "github.com/caos/orbos/internal/api/networking/v1" + orbnw "github.com/caos/orbos/internal/operator/networking/kinds/orb" + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" +) + +type Reconciler struct { + kubernetes.ClientInt + Monitor mntr.Monitor + Scheme *runtime.Scheme + Version string +} + +func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) { + internalMonitor := r.Monitor.WithFields(map[string]interface{}{ + "kind": "networking", + }) + + defer func() { + r.Monitor.Error(err) + }() + + if req.Namespace != networking.Namespace || req.Name != networking.Name { + return res, fmt.Errorf("resource must be named %s and namespaced in %s", networking.Name, networking.Namespace) + } + + desired, err := networking.ReadCRD(r) + if desired == nil { + return res, err + } + + query, _, _, _, _, err := orbnw.AdaptFunc("", &r.Version, false)(internalMonitor, desired, &tree.Tree{}) + if err != nil { + + if errors.Is(err, config.ErrNoLBID) { + return res, fmt.Errorf("crd mode doesn't support specifying a loadbalancer yet") + } + + return res, err + } + + ensure, err := query(r.ClientInt, map[string]interface{}{}) + if err != nil { + return res, err + } + + return res, ensure(r.ClientInt) +} + +func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&v1.Networking{}). + Complete(r) +} diff --git a/internal/start/boom.go b/internal/ctrlgitops/boom.go similarity index 89% rename from internal/start/boom.go rename to internal/ctrlgitops/boom.go index 822eb513e..b2d637718 100644 --- a/internal/start/boom.go +++ b/internal/ctrlgitops/boom.go @@ -1,13 +1,14 @@ -package start +package ctrlgitops import ( - "github.com/caos/orbos/internal/operator/boom" - "github.com/caos/orbos/mntr" "runtime/debug" "time" + + "github.com/caos/orbos/internal/operator/boom" + "github.com/caos/orbos/mntr" ) -func Boom(monitor mntr.Monitor, orbConfigPath string, localmode bool, version string) error { +func Boom(monitor mntr.Monitor, orbConfigPath string, version string) error { ensureClient := gitClient(monitor, "ensure") queryClient := gitClient(monitor, "query") @@ -30,7 +31,6 @@ func Boom(monitor mntr.Monitor, orbConfigPath string, localmode bool, version st ensure, query := boom.Takeoff( monitor, "/boom", - localmode, orbConfigPath, ensureClient, queryClient, @@ -62,6 +62,7 @@ func Boom(monitor mntr.Monitor, orbConfigPath string, localmode bool, version st <-queryChan <-ensureChan + time.Sleep(time.Second * 30) takeoffChan <- struct{}{} }() } diff --git a/internal/start/common.go b/internal/ctrlgitops/common.go similarity index 95% rename from internal/start/common.go rename to internal/ctrlgitops/common.go index bc253bedb..df844c75e 100644 --- a/internal/start/common.go +++ b/internal/ctrlgitops/common.go @@ -1,10 +1,11 @@ -package start +package ctrlgitops import ( "context" + "time" + "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" - "time" ) func gitClient(monitor mntr.Monitor, task string) *git.Client { diff --git a/internal/start/networking.go b/internal/ctrlgitops/networking.go similarity index 77% rename from internal/start/networking.go rename to internal/ctrlgitops/networking.go index bf77e9a60..717e18a66 100644 --- a/internal/start/networking.go +++ b/internal/ctrlgitops/networking.go @@ -1,12 +1,13 @@ -package start +package ctrlgitops import ( "context" "time" + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/internal/operator/networking" "github.com/caos/orbos/internal/operator/networking/kinds/orb" - orbconfig "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" kubernetes2 "github.com/caos/orbos/pkg/kubernetes" @@ -18,20 +19,21 @@ func Networking(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernete takeoffChan <- struct{}{} }() + gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") + for range takeoffChan { - orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) + orbConfig, err := orbcfg.ParseOrbConfig(orbConfigPath) if err != nil { monitor.Error(err) return err } - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { monitor.Error(err) return err } - takeoff := networking.Takeoff(monitor, gitClient, orb.AdaptFunc(orbConfig.URL, binaryVersion), k8sClient) + takeoff := networking.Takeoff(monitor, gitClient, orb.AdaptFunc(orbConfig.URL, binaryVersion, true), k8sClient) go func() { started := time.Now() @@ -41,6 +43,7 @@ func Networking(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernete "took": time.Since(started), }).Info("Iteration done") + time.Sleep(time.Second * 30) takeoffChan <- struct{}{} }() } diff --git a/internal/start/orbiter.go b/internal/ctrlgitops/orbiter.go similarity index 68% rename from internal/start/orbiter.go rename to internal/ctrlgitops/orbiter.go index 2be73c662..f8f2aa5d8 100644 --- a/internal/start/orbiter.go +++ b/internal/ctrlgitops/orbiter.go @@ -1,25 +1,20 @@ -package start +package ctrlgitops import ( "context" - "errors" - "fmt" "runtime/debug" - "strings" "time" + orbcfg "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/internal/api" "github.com/caos/orbos/internal/executables" "github.com/caos/orbos/internal/ingestion" "github.com/caos/orbos/internal/operator/orbiter" "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" - orbconfig "github.com/caos/orbos/internal/orb" - "github.com/caos/orbos/internal/secret/operators" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/secret" "github.com/golang/protobuf/ptypes" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/structpb" @@ -36,12 +31,22 @@ type OrbiterConfig struct { IngestionAddress string } -func Orbiter(ctx context.Context, monitor mntr.Monitor, conf *OrbiterConfig, orbctlGit *git.Client, orbConfig *orbconfig.Orb, version string) ([]string, error) { +func Orbiter(ctx context.Context, monitor mntr.Monitor, conf *OrbiterConfig, orbctlGit *git.Client) error { go checks(monitor, orbctlGit) finishedChan := make(chan struct{}) takeoffChan := make(chan struct{}) + healthyChan := make(chan bool) + + if conf.Recur { + go orbiter.Instrument(monitor, healthyChan) + } else { + go func() { + for range healthyChan { + } + }() + } on := func() { takeoffChan <- struct{}{} } go on() @@ -52,20 +57,32 @@ loop: case <-finishedChan: break loop case <-takeoffChan: - iterate(conf, orbctlGit, !initialized, ctx, monitor, finishedChan, func(iterated bool) { + iterate(conf, orbctlGit, !initialized, ctx, monitor, finishedChan, healthyChan, func(iterated bool) { if iterated { initialized = true } + + time.Sleep(time.Second * 30) go on() }) } } - - return GetKubeconfigs(monitor, orbctlGit, orbConfig, version) + return nil } -func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ctx context.Context, monitor mntr.Monitor, finishedChan chan struct{}, done func(iterated bool)) { - orbFile, err := orbconfig.ParseOrbConfig(conf.OrbConfigPath) +func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ctx context.Context, monitor mntr.Monitor, finishedChan chan struct{}, healthyChan chan bool, done func(iterated bool)) { + + var err error + defer func() { + go func() { + if err != nil { + healthyChan <- false + return + } + }() + }() + + orbFile, err := orbcfg.ParseOrbConfig(conf.OrbConfigPath) if err != nil { monitor.Error(err) done(false) @@ -80,6 +97,7 @@ func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ct if err := gitClient.Clone(); err != nil { monitor.Error(err) + done(false) return } @@ -103,16 +121,13 @@ func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ct } if firstIteration { - if conf.Recur { - orbiter.Metrics() - } if err := pushEvents([]*ingestion.EventRequest{{ CreationDate: ptypes.TimestampNow(), Type: "orbiter.tookoff", Data: &structpb.Struct{ Fields: map[string]*structpb.Value{ - "commit": &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: conf.GitCommit}}, + "commit": {Kind: &structpb.Value_StringValue{StringValue: conf.GitCommit}}, }, }, }}); err != nil { @@ -164,7 +179,7 @@ func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ct OrbConfig: *orbFile, } - takeoff := orbiter.Takeoff(monitor, takeoffConf) + takeoff := orbiter.Takeoff(monitor, takeoffConf, healthyChan) go func() { started := time.Now() @@ -177,38 +192,3 @@ func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ct done(true) }() } - -func GetKubeconfigs(monitor mntr.Monitor, gitClient *git.Client, orbConfig *orbconfig.Orb, version string) ([]string, error) { - kubeconfigs := make([]string, 0) - - orbTree, err := api.ReadOrbiterYml(gitClient) - if err != nil { - return nil, errors.New("Failed to parse orbiter.yml") - } - - orbDef, err := orb.ParseDesiredV0(orbTree) - if err != nil { - return nil, errors.New("Failed to parse orbiter.yml") - } - - for clustername, _ := range orbDef.Clusters { - path := strings.Join([]string{"orbiter", clustername, "kubeconfig"}, ".") - - value, err := secret.Read( - monitor, - gitClient, - path, - operators.GetAllSecretsFunc(orbConfig, &version)) - if err != nil || value == "" { - if value == "" && err == nil { - err = errors.New("no kubeconfig found") - } - return nil, fmt.Errorf("failed to get kubeconfig: %w", err) - } - monitor.Info("Read kubeconfigs") - - kubeconfigs = append(kubeconfigs, value) - } - - return kubeconfigs, nil -} diff --git a/internal/executables/targz.go b/internal/executables/targz.go index ee436ece9..cf380ba32 100644 --- a/internal/executables/targz.go +++ b/internal/executables/targz.go @@ -5,7 +5,7 @@ import ( "compress/gzip" "io" - "gopkg.in/src-d/go-git.v4/utils/ioutil" + "github.com/go-git/go-git/v5/utils/ioutil" "github.com/caos/orbos/internal/helpers" ) diff --git a/internal/operator/boom/api/api.go b/internal/operator/boom/api/api.go index 2763ba1c3..a85faef78 100644 --- a/internal/operator/boom/api/api.go +++ b/internal/operator/boom/api/api.go @@ -1,63 +1,62 @@ package api import ( + "strings" + "github.com/caos/orbos/internal/operator/boom/api/common" "github.com/caos/orbos/internal/operator/boom/api/latest" "github.com/caos/orbos/internal/operator/boom/api/migrate" "github.com/caos/orbos/internal/operator/boom/api/v1beta1" "github.com/caos/orbos/internal/operator/boom/api/v1beta2" "github.com/caos/orbos/internal/operator/boom/metrics" - "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" "github.com/pkg/errors" - "strings" ) const ( - boomPrefix = "boom.caos.ch" + boomPrefix = "caos.ch" ) -func ParseToolset(desiredTree *tree.Tree) (*latest.Toolset, bool, map[string]*secret.Secret, string, string, error) { +func ParseToolset(desiredTree *tree.Tree) (*latest.Toolset, bool, string, string, error) { desiredKindCommon := common.New() if err := desiredTree.Original.Decode(desiredKindCommon); err != nil { metrics.WrongCRDFormat() - return nil, false, nil, "", "", errors.Wrap(err, "parsing desired state failed") + return nil, false, "", "", errors.Wrap(err, "parsing desired state failed") + } + if desiredKindCommon.Kind != "Boom" { + return nil, false, "", "", errors.New("Kind unknown") } - if !strings.HasPrefix(desiredKindCommon.APIVersion, "boom.caos.ch") { + if !strings.HasPrefix(desiredKindCommon.APIVersion, boomPrefix) { metrics.UnsupportedAPIGroup() + return nil, false, "", "", errors.New("Group unknown") } switch desiredKindCommon.APIVersion { case boomPrefix + "/v1beta1": - old, _, err := v1beta1.ParseToolset(desiredTree) + old, err := v1beta1.ParseToolset(desiredTree) if err != nil { - return nil, false, nil, "", "", err + return nil, false, "", "", err } - v1beta2Toolset, _ := migrate.V1beta1Tov1beta2(old) - v1Toolset, secrets := migrate.V1beta2Tov1(v1beta2Toolset) - metrics.SuccessfulUnmarshalCRD() - return v1Toolset, true, secrets, desiredKindCommon.Kind, "v1beta1", err + return migrate.V1beta2Tov1(migrate.V1beta1Tov1beta2(old)), true, desiredKindCommon.Kind, "v1beta1", err case boomPrefix + "/v1beta2": - v1beta2Toolset, _, err := v1beta2.ParseToolset(desiredTree) + v1beta2Toolset, err := v1beta2.ParseToolset(desiredTree) if err != nil { - return nil, false, nil, "", "", err + return nil, false, "", "", err } - v1Toolset, secrets := migrate.V1beta2Tov1(v1beta2Toolset) - metrics.SuccessfulUnmarshalCRD() - return v1Toolset, true, secrets, desiredKindCommon.Kind, "v1beta2", nil + return migrate.V1beta2Tov1(v1beta2Toolset), true, desiredKindCommon.Kind, "v1beta2", nil case boomPrefix + "/v1": - desiredKind, secrets, err := latest.ParseToolset(desiredTree) + desiredKind, err := latest.ParseToolset(desiredTree) if err != nil { - return nil, false, nil, "", "", err + return nil, false, "", "", err } metrics.SuccessfulUnmarshalCRD() - return desiredKind, false, secrets, desiredKindCommon.Kind, "v1", nil + return desiredKind, false, desiredKindCommon.Kind, "v1", nil default: metrics.UnsupportedVersion() - return nil, false, nil, "", "", errors.New("APIVersion unknown") + return nil, false, "", "", errors.New("APIVersion unknown") } } diff --git a/internal/operator/boom/api/latest/apigateway.go b/internal/operator/boom/api/latest/apigateway.go index 89298abd5..b44667d2f 100644 --- a/internal/operator/boom/api/latest/apigateway.go +++ b/internal/operator/boom/api/latest/apigateway.go @@ -33,7 +33,7 @@ type APIGateway struct { type Caching struct { //Enable specifies, whether a redis instance should be deployed or not - Enable bool + Enable bool `json:"enable" yaml:"enable"` //Resource requirements Resources *k8s.Resources `json:"resources,omitempty" yaml:"resources,omitempty"` } diff --git a/internal/operator/boom/api/latest/funcs.go b/internal/operator/boom/api/latest/funcs.go index 82c123ac4..cd0ee242e 100644 --- a/internal/operator/boom/api/latest/funcs.go +++ b/internal/operator/boom/api/latest/funcs.go @@ -10,18 +10,21 @@ import ( "github.com/pkg/errors" ) -func ParseToolset(desiredTree *tree.Tree) (*Toolset, map[string]*secret.Secret, error) { +func ParseToolset(desiredTree *tree.Tree) (*Toolset, error) { desiredKind := &Toolset{} if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, nil, errors.Wrap(err, "parsing desired state failed") + return nil, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind - - return desiredKind, GetSecretsMap(desiredKind), nil + return desiredKind, nil } -func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { - ret := make(map[string]*secret.Secret, 0) +func GetSecretsMap(desiredKind *Toolset) ( + map[string]*secret.Secret, + map[string]*secret.Existing, +) { + secrets := make(map[string]*secret.Secret, 0) + existing := make(map[string]*secret.Existing, 0) if desiredKind.Spec.Monitoring == nil { desiredKind.Spec.Monitoring = &monitoring.Monitoring{} @@ -29,16 +32,32 @@ func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { grafanaSpec := desiredKind.Spec.Monitoring grafanaSpec.InitSecrets() - ret["grafana.admin.username"] = grafanaSpec.Admin.Username - ret["grafana.admin.password"] = grafanaSpec.Admin.Password - ret["grafana.sso.oauth.clientid"] = grafanaSpec.Auth.GenericOAuth.ClientID - ret["grafana.sso.oauth.clientsecret"] = grafanaSpec.Auth.GenericOAuth.ClientSecret - ret["grafana.sso.google.clientid"] = grafanaSpec.Auth.Google.ClientID - ret["grafana.sso.google.clientsecret"] = grafanaSpec.Auth.Google.ClientSecret - ret["grafana.sso.github.clientid"] = grafanaSpec.Auth.Github.ClientID - ret["grafana.sso.github.clientsecret"] = grafanaSpec.Auth.Github.ClientSecret - ret["grafana.sso.gitlab.clientid"] = grafanaSpec.Auth.Gitlab.ClientID - ret["grafana.sso.gitlab.clientsecret"] = grafanaSpec.Auth.Gitlab.ClientSecret + secrets["grafana.admin.username"] = grafanaSpec.Admin.Username + secrets["grafana.admin.password"] = grafanaSpec.Admin.Password + grafoAuthClientIDKey := "grafana.sso.oauth.clientid" + secrets[grafoAuthClientIDKey] = grafanaSpec.Auth.GenericOAuth.ClientID + existing[grafoAuthClientIDKey] = grafanaSpec.Auth.GenericOAuth.ExistingClientIDSecret + grafoAuthClientIDSecKey := "grafana.sso.oauth.clientsecret" + secrets[grafoAuthClientIDSecKey] = grafanaSpec.Auth.GenericOAuth.ClientSecret + existing[grafoAuthClientIDSecKey] = grafanaSpec.Auth.GenericOAuth.ExistingClientSecretSecret + grafoGoogClientIDKey := "grafana.sso.google.clientid" + secrets[grafoGoogClientIDKey] = grafanaSpec.Auth.Google.ClientID + existing[grafoGoogClientIDKey] = grafanaSpec.Auth.Google.ExistingClientIDSecret + grafoGoogClientIDSecKey := "grafana.sso.google.clientsecret" + secrets[grafoGoogClientIDSecKey] = grafanaSpec.Auth.Google.ClientSecret + existing[grafoGoogClientIDSecKey] = grafanaSpec.Auth.Google.ExistingClientSecretSecret + grafoGHClientIDKey := "grafana.sso.github.clientid" + secrets[grafoGHClientIDKey] = grafanaSpec.Auth.Github.ClientID + existing[grafoGHClientIDKey] = grafanaSpec.Auth.Github.ExistingClientIDSecret + grafoGHClientIDSecKey := "grafana.sso.github.clientsecret" + secrets[grafoGHClientIDSecKey] = grafanaSpec.Auth.Github.ClientSecret + existing[grafoGHClientIDSecKey] = grafanaSpec.Auth.Github.ExistingClientSecretSecret + grafoGLClientIDKey := "grafana.sso.gitlab.clientid" + secrets[grafoGLClientIDKey] = grafanaSpec.Auth.Gitlab.ClientID + existing[grafoGLClientIDKey] = grafanaSpec.Auth.Gitlab.ExistingClientIDSecret + grafoGLClientIDSecKey := "grafana.sso.gitlab.clientsecret" + secrets[grafoGLClientIDSecKey] = grafanaSpec.Auth.Gitlab.ClientSecret + existing[grafoGLClientIDSecKey] = grafanaSpec.Auth.Gitlab.ExistingClientSecretSecret if desiredKind.Spec.Reconciling == nil { desiredKind.Spec.Reconciling = &reconciling.Reconciling{} @@ -46,15 +65,33 @@ func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { argocdSpec := desiredKind.Spec.Reconciling argocdSpec.InitSecrets() - ret["argocd.sso.google.clientid"] = argocdSpec.Auth.GoogleConnector.Config.ClientID - ret["argocd.sso.google.clientsecret"] = argocdSpec.Auth.GoogleConnector.Config.ClientSecret - ret["argocd.sso.google.serviceaccountjson"] = argocdSpec.Auth.GoogleConnector.Config.ServiceAccountJSON - ret["argocd.sso.gitlab.clientid"] = argocdSpec.Auth.GitlabConnector.Config.ClientID - ret["argocd.sso.gitlab.clientsecret"] = argocdSpec.Auth.GitlabConnector.Config.ClientSecret - ret["argocd.sso.github.clientid"] = argocdSpec.Auth.GithubConnector.Config.ClientID - ret["argocd.sso.github.clientsecret"] = argocdSpec.Auth.GithubConnector.Config.ClientSecret - ret["argocd.sso.oidc.clientid"] = argocdSpec.Auth.OIDC.ClientID - ret["argocd.sso.oidc.clientsecret"] = argocdSpec.Auth.OIDC.ClientSecret + argoGoogClientIDKey := "argocd.sso.google.clientid" + secrets[argoGoogClientIDKey] = argocdSpec.Auth.GoogleConnector.Config.ClientID + existing[argoGoogClientIDKey] = argocdSpec.Auth.GoogleConnector.Config.ExistingClientIDSecret + argoGoogClientIDSecKey := "argocd.sso.google.clientsecret" + secrets[argoGoogClientIDSecKey] = argocdSpec.Auth.GoogleConnector.Config.ClientSecret + existing[argoGoogClientIDSecKey] = argocdSpec.Auth.GoogleConnector.Config.ExistingClientSecretSecret + argoGoogSAKey := "argocd.sso.google.serviceaccountjson" + secrets[argoGoogSAKey] = argocdSpec.Auth.GoogleConnector.Config.ServiceAccountJSON + existing[argoGoogSAKey] = argocdSpec.Auth.GoogleConnector.Config.ExistingServiceAccountJSONSecret + argoGLClientIDKey := "argocd.sso.gitlab.clientid" + secrets[argoGLClientIDKey] = argocdSpec.Auth.GitlabConnector.Config.ClientID + existing[argoGLClientIDKey] = argocdSpec.Auth.GitlabConnector.Config.ExistingClientIDSecret + argoGLClientIDSecKey := "argocd.sso.gitlab.clientsecret" + secrets[argoGLClientIDSecKey] = argocdSpec.Auth.GitlabConnector.Config.ClientSecret + existing[argoGLClientIDSecKey] = argocdSpec.Auth.GitlabConnector.Config.ExistingClientSecretSecret + argoGHClientIDKey := "argocd.sso.github.clientid" + secrets[argoGHClientIDKey] = argocdSpec.Auth.GithubConnector.Config.ClientID + existing[argoGHClientIDKey] = argocdSpec.Auth.GithubConnector.Config.ExistingClientIDSecret + argoGHClientIDSecKey := "argocd.sso.github.clientsecret" + secrets[argoGHClientIDSecKey] = argocdSpec.Auth.GithubConnector.Config.ClientSecret + existing[argoGHClientIDSecKey] = argocdSpec.Auth.GithubConnector.Config.ExistingClientSecretSecret + argoOIDCClientIDKey := "argocd.sso.oidc.clientid" + secrets[argoOIDCClientIDKey] = argocdSpec.Auth.OIDC.ClientID + existing[argoOIDCClientIDKey] = argocdSpec.Auth.OIDC.ExistingClientIDSecret + argoOIDCClientIDSecKey := "argocd.sso.oidc.clientsecret" + secrets[argoOIDCClientIDSecKey] = argocdSpec.Auth.OIDC.ClientSecret + existing[argoOIDCClientIDSecKey] = argocdSpec.Auth.OIDC.ExistingClientSecretSecret if argocdSpec.Credentials != nil { for _, value := range argocdSpec.Credentials { @@ -64,19 +101,19 @@ func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { if value.Username == nil { value.Username = &secret.Secret{} } - ret[key] = value.Username + secrets[key] = value.Username key = strings.Join([]string{base, "password"}, ".") if value.Password == nil { value.Password = &secret.Secret{} } - ret[key] = value.Password + secrets[key] = value.Password key = strings.Join([]string{base, "certificate"}, ".") if value.Certificate == nil { value.Certificate = &secret.Secret{} } - ret[key] = value.Certificate + secrets[key] = value.Certificate } } if argocdSpec.Repositories != nil { @@ -87,19 +124,19 @@ func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { if value.Username == nil { value.Username = &secret.Secret{} } - ret[key] = value.Username + secrets[key] = value.Username key = strings.Join([]string{base, "password"}, ".") if value.Password == nil { value.Password = &secret.Secret{} } - ret[key] = value.Password + secrets[key] = value.Password key = strings.Join([]string{base, "certificate"}, ".") if value.Certificate == nil { value.Certificate = &secret.Secret{} } - ret[key] = value.Certificate + secrets[key] = value.Certificate } } @@ -111,15 +148,15 @@ func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { if value.SSHKey == nil { value.SSHKey = &secret.Secret{} } - ret[key] = value.SSHKey + secrets[key] = value.SSHKey key = strings.Join([]string{base, "gpg"}, ".") if value.GPGKey == nil { value.GPGKey = &secret.Secret{} } - ret[key] = value.GPGKey + secrets[key] = value.GPGKey } } - return ret + return secrets, existing } diff --git a/internal/operator/boom/api/latest/monitoring/admin/admin.go b/internal/operator/boom/api/latest/monitoring/admin/admin.go index 4f03595e0..7d969330b 100644 --- a/internal/operator/boom/api/latest/monitoring/admin/admin.go +++ b/internal/operator/boom/api/latest/monitoring/admin/admin.go @@ -7,7 +7,7 @@ import ( // Admin: Not defining the admin credentials results in an user admin with password admin. type Admin struct { Username *secret.Secret `json:"username,omitempty" yaml:"username,omitempty"` - Password *secret.Secret `yaml:"password,omitempty" yaml:"username,omitempty"` + Password *secret.Secret `json:"password,omitempty" yaml:"password,omitempty"` //Existing Secret containing username and password ExistingSecret *secret.ExistingIDSecret `json:"existingSecret,omitempty" yaml:"existingSecret,omitempty"` } @@ -25,6 +25,9 @@ func (a *Admin) InitSecrets() { if a.Username == nil { a.Username = &secret.Secret{} } + if a.ExistingSecret == nil { + a.ExistingSecret = &secret.ExistingIDSecret{} + } if a.Password == nil { a.Password = &secret.Secret{} } diff --git a/internal/operator/boom/api/latest/monitoring/auth/Github/github.go b/internal/operator/boom/api/latest/monitoring/auth/Github/github.go index b94d6bd7e..5b684a3b3 100644 --- a/internal/operator/boom/api/latest/monitoring/auth/Github/github.go +++ b/internal/operator/boom/api/latest/monitoring/auth/Github/github.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` // Organizations allowed to login diff --git a/internal/operator/boom/api/latest/monitoring/auth/Gitlab/gitlab.go b/internal/operator/boom/api/latest/monitoring/auth/Gitlab/gitlab.go index 27cb108bc..d0d0e30ae 100644 --- a/internal/operator/boom/api/latest/monitoring/auth/Gitlab/gitlab.go +++ b/internal/operator/boom/api/latest/monitoring/auth/Gitlab/gitlab.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Groups of gitlab allowed to login diff --git a/internal/operator/boom/api/latest/monitoring/auth/Google/google.go b/internal/operator/boom/api/latest/monitoring/auth/Google/google.go index 42d891b51..a8a68aed7 100644 --- a/internal/operator/boom/api/latest/monitoring/auth/Google/google.go +++ b/internal/operator/boom/api/latest/monitoring/auth/Google/google.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Domains allowed to login diff --git a/internal/operator/boom/api/latest/monitoring/auth/auth.go b/internal/operator/boom/api/latest/monitoring/auth/auth.go index 861d250af..5cb3b8b0e 100644 --- a/internal/operator/boom/api/latest/monitoring/auth/auth.go +++ b/internal/operator/boom/api/latest/monitoring/auth/auth.go @@ -40,6 +40,12 @@ func (a *Auth) InitSecrets() { if a.GenericOAuth.ClientSecret == nil { a.GenericOAuth.ClientSecret = &secret.Secret{} } + if a.GenericOAuth.ExistingClientIDSecret == nil { + a.GenericOAuth.ExistingClientIDSecret = &secret.Existing{} + } + if a.GenericOAuth.ExistingClientSecretSecret == nil { + a.GenericOAuth.ExistingClientSecretSecret = &secret.Existing{} + } if a.Google == nil { a.Google = &google.Auth{} @@ -50,6 +56,12 @@ func (a *Auth) InitSecrets() { if a.Google.ClientSecret == nil { a.Google.ClientSecret = &secret.Secret{} } + if a.Google.ExistingClientIDSecret == nil { + a.Google.ExistingClientIDSecret = &secret.Existing{} + } + if a.Google.ExistingClientSecretSecret == nil { + a.Google.ExistingClientSecretSecret = &secret.Existing{} + } if a.Github == nil { a.Github = &github.Auth{} @@ -60,6 +72,12 @@ func (a *Auth) InitSecrets() { if a.Github.ClientSecret == nil { a.Github.ClientSecret = &secret.Secret{} } + if a.Github.ExistingClientIDSecret == nil { + a.Github.ExistingClientIDSecret = &secret.Existing{} + } + if a.Github.ExistingClientSecretSecret == nil { + a.Github.ExistingClientSecretSecret = &secret.Existing{} + } if a.Gitlab == nil { a.Gitlab = &gitlab.Auth{} @@ -70,4 +88,10 @@ func (a *Auth) InitSecrets() { if a.Gitlab.ClientSecret == nil { a.Gitlab.ClientSecret = &secret.Secret{} } + if a.Gitlab.ExistingClientIDSecret == nil { + a.Gitlab.ExistingClientIDSecret = &secret.Existing{} + } + if a.Gitlab.ExistingClientSecretSecret == nil { + a.Gitlab.ExistingClientSecretSecret = &secret.Existing{} + } } diff --git a/internal/operator/boom/api/latest/reconciling/auth/auth.go b/internal/operator/boom/api/latest/reconciling/auth/auth.go index 8caede503..e4b8b8cb9 100644 --- a/internal/operator/boom/api/latest/reconciling/auth/auth.go +++ b/internal/operator/boom/api/latest/reconciling/auth/auth.go @@ -39,6 +39,12 @@ func (a *Auth) InitSecrets() { if a.OIDC.ClientSecret == nil { a.OIDC.ClientSecret = &secret.Secret{} } + if a.OIDC.ExistingClientIDSecret == nil { + a.OIDC.ExistingClientIDSecret = &secret.Existing{} + } + if a.OIDC.ExistingClientSecretSecret == nil { + a.OIDC.ExistingClientSecretSecret = &secret.Existing{} + } if a.GoogleConnector == nil { a.GoogleConnector = &google.Connector{} @@ -55,6 +61,15 @@ func (a *Auth) InitSecrets() { if a.GoogleConnector.Config.ServiceAccountJSON == nil { a.GoogleConnector.Config.ServiceAccountJSON = &secret.Secret{} } + if a.GoogleConnector.Config.ExistingClientIDSecret == nil { + a.GoogleConnector.Config.ExistingClientIDSecret = &secret.Existing{} + } + if a.GoogleConnector.Config.ExistingClientSecretSecret == nil { + a.GoogleConnector.Config.ExistingClientSecretSecret = &secret.Existing{} + } + if a.GoogleConnector.Config.ExistingServiceAccountJSONSecret == nil { + a.GoogleConnector.Config.ExistingServiceAccountJSONSecret = &secret.Existing{} + } if a.GithubConnector == nil { a.GithubConnector = &github.Connector{} @@ -68,6 +83,12 @@ func (a *Auth) InitSecrets() { if a.GithubConnector.Config.ClientSecret == nil { a.GithubConnector.Config.ClientSecret = &secret.Secret{} } + if a.GithubConnector.Config.ExistingClientIDSecret == nil { + a.GithubConnector.Config.ExistingClientIDSecret = &secret.Existing{} + } + if a.GithubConnector.Config.ExistingClientSecretSecret == nil { + a.GithubConnector.Config.ExistingClientSecretSecret = &secret.Existing{} + } if a.GitlabConnector == nil { a.GitlabConnector = &gitlab.Connector{} @@ -81,4 +102,10 @@ func (a *Auth) InitSecrets() { if a.GitlabConnector.Config.ClientSecret == nil { a.GitlabConnector.Config.ClientSecret = &secret.Secret{} } + if a.GitlabConnector.Config.ExistingClientIDSecret == nil { + a.GitlabConnector.Config.ExistingClientIDSecret = &secret.Existing{} + } + if a.GitlabConnector.Config.ExistingClientSecretSecret == nil { + a.GitlabConnector.Config.ExistingClientSecretSecret = &secret.Existing{} + } } diff --git a/internal/operator/boom/api/latest/reconciling/auth/github/github.go b/internal/operator/boom/api/latest/reconciling/auth/github/github.go index 65384c74f..8041626dc 100644 --- a/internal/operator/boom/api/latest/reconciling/auth/github/github.go +++ b/internal/operator/boom/api/latest/reconciling/auth/github/github.go @@ -24,10 +24,10 @@ func (c *Connector) IsZero() bool { } type Config struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Required membership to organization in github diff --git a/internal/operator/boom/api/latest/reconciling/auth/gitlab/gitlab.go b/internal/operator/boom/api/latest/reconciling/auth/gitlab/gitlab.go index bf41ab177..4c34fc810 100644 --- a/internal/operator/boom/api/latest/reconciling/auth/gitlab/gitlab.go +++ b/internal/operator/boom/api/latest/reconciling/auth/gitlab/gitlab.go @@ -24,10 +24,10 @@ func (c *Connector) IsZero() bool { } type Config struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //BaseURL of the gitlab instance diff --git a/internal/operator/boom/api/latest/reconciling/auth/google/google.go b/internal/operator/boom/api/latest/reconciling/auth/google/google.go index bfd3ce646..7a1ac2393 100644 --- a/internal/operator/boom/api/latest/reconciling/auth/google/google.go +++ b/internal/operator/boom/api/latest/reconciling/auth/google/google.go @@ -24,17 +24,17 @@ func (c *Connector) IsZero() bool { } type Config struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //List of hosted domains which are permitted to login HostedDomains []string `json:"hostedDomains,omitempty" yaml:"hostedDomains,omitempty"` //List of groups in the hosted domains which are permitted to login Groups []string `json:"groups,omitempty" yaml:"groups,omitempty"` - ServiceAccountJSON *secret2.Secret `yaml:"serviceAccountJSON,omitempty"` + ServiceAccountJSON *secret2.Secret `json:"serviceAccountJSON,omitempty" yaml:"serviceAccountJSON,omitempty"` //Existing secret with the JSON of the service account ExistingServiceAccountJSONSecret *secret2.Existing `json:"existingServiceAccountJSONSecret,omitempty" yaml:"existingServiceAccountJSONSecret,omitempty"` //File where the serviceAccountJSON will get persisted to impersonate G Suite admin diff --git a/internal/operator/boom/api/latest/reconciling/auth/oidc/oidc.go b/internal/operator/boom/api/latest/reconciling/auth/oidc/oidc.go index b658ae022..d48b3791f 100644 --- a/internal/operator/boom/api/latest/reconciling/auth/oidc/oidc.go +++ b/internal/operator/boom/api/latest/reconciling/auth/oidc/oidc.go @@ -9,10 +9,10 @@ type OIDC struct { Name string `json:"name,omitempty" yaml:"name,omitempty"` //Issuer of the OIDC provider Issuer string `json:"issuer,omitempty" yaml:"issuer,omitempty"` - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Optional set of OIDC scopes to request. If omitted, defaults to: ["openid", "profile", "email", "groups"] diff --git a/internal/operator/boom/api/latest/reconciling/reconciling.go b/internal/operator/boom/api/latest/reconciling/reconciling.go index 98002f763..fee1a16fd 100644 --- a/internal/operator/boom/api/latest/reconciling/reconciling.go +++ b/internal/operator/boom/api/latest/reconciling/reconciling.go @@ -102,10 +102,10 @@ type CustomImage struct { } type GopassStore struct { - SSHKey *secret.Secret `yaml:"sshKey,omitempty"` + SSHKey *secret.Secret `json:"sshKey,omitempty" yaml:"sshKey,omitempty"` //Existing secret with ssh-key to clone the repository for gopass ExistingSSHKeySecret *secret.Existing `json:"existingSshKeySecret,omitempty" yaml:"existingSshKeySecret,omitempty"` - GPGKey *secret.Secret `yaml:"gpgKey,omitempty"` + GPGKey *secret.Secret `json:"gpgKey,omitempty" yaml:"gpgKey,omitempty"` //Existing secret with gpg-key to decode the repository for gopass ExistingGPGKeySecret *secret.Existing `json:"existingGpgKeySecret,omitempty" yaml:"existingGpgKeySecret,omitempty"` //URL to repository for gopass store diff --git a/internal/operator/boom/api/latest/reconciling/repository/repository.go b/internal/operator/boom/api/latest/reconciling/repository/repository.go index d8c50f75d..77a73b040 100644 --- a/internal/operator/boom/api/latest/reconciling/repository/repository.go +++ b/internal/operator/boom/api/latest/reconciling/repository/repository.go @@ -10,13 +10,13 @@ type Repository struct { Name string `json:"name,omitempty" yaml:"name,omitempty"` //Prefix where the credential should be used (starting "git@" or "https://" ) URL string `json:"url,omitempty" yaml:"url,omitempty"` - Username *secret2.Secret `yaml:"username,omitempty"` + Username *secret2.Secret `json:"username,omitempty" yaml:"username,omitempty"` //Existing secret used for username ExistingUsernameSecret *secret2.Existing `json:"existingUsernameSecret,omitempty" yaml:"existingUsernameSecret,omitempty"` - Password *secret2.Secret `yaml:"password,omitempty"` + Password *secret2.Secret `json:"password,omitempty" yaml:"password,omitempty"` //Existing secret used for password ExistingPasswordSecret *secret2.Existing `json:"existingPasswordSecret,omitempty" yaml:"existingPasswordSecret,omitempty"` - Certificate *secret2.Secret `yaml:"certificate,omitempty"` + Certificate *secret2.Secret `json:"certificate,omitempty" yaml:"certificate,omitempty"` //Existing secret used for certificate ExistingCertificateSecret *secret2.Existing `json:"existingCertificateSecret,omitempty" yaml:"existingCertificateSecret,omitempty"` } diff --git a/internal/operator/boom/api/migrate/v1beta1tov1beta2.go b/internal/operator/boom/api/migrate/v1beta1tov1beta2.go index 43bee49a4..d27af103c 100644 --- a/internal/operator/boom/api/migrate/v1beta1tov1beta2.go +++ b/internal/operator/boom/api/migrate/v1beta1tov1beta2.go @@ -7,10 +7,9 @@ import ( "github.com/caos/orbos/internal/operator/boom/api/migrate/storage" "github.com/caos/orbos/internal/operator/boom/api/v1beta1" "github.com/caos/orbos/internal/operator/boom/api/v1beta2" - "github.com/caos/orbos/pkg/secret" ) -func V1beta1Tov1beta2(oldToolset *v1beta1.Toolset) (*v1beta2.Toolset, map[string]*secret.Secret) { +func V1beta1Tov1beta2(oldToolset *v1beta1.Toolset) *v1beta2.Toolset { newToolset := &v1beta2.Toolset{ APIVersion: "boom.caos.ch/v1beta2", Metadata: &latest.Metadata{ @@ -188,5 +187,5 @@ func V1beta1Tov1beta2(oldToolset *v1beta1.Toolset) (*v1beta2.Toolset, map[string newToolset.Spec = newSpec } - return newToolset, v1beta2.GetSecretsMap(newToolset) + return newToolset } diff --git a/internal/operator/boom/api/migrate/v1beta2tov1.go b/internal/operator/boom/api/migrate/v1beta2tov1.go index a2ba59192..ba4981fd6 100644 --- a/internal/operator/boom/api/migrate/v1beta2tov1.go +++ b/internal/operator/boom/api/migrate/v1beta2tov1.go @@ -3,14 +3,9 @@ package migrate import ( "github.com/caos/orbos/internal/operator/boom/api/latest" "github.com/caos/orbos/internal/operator/boom/api/v1beta2" - "github.com/caos/orbos/pkg/secret" ) -func V1beta2Tov1(oldToolset *v1beta2.Toolset) (newToolset *latest.Toolset, secrets map[string]*secret.Secret) { - - defer func() { - secrets = latest.GetSecretsMap(newToolset) - }() +func V1beta2Tov1(oldToolset *v1beta2.Toolset) (newToolset *latest.Toolset) { newToolset = &latest.Toolset{ APIVersion: "boom.caos.ch/v1", @@ -40,7 +35,7 @@ func V1beta2Tov1(oldToolset *v1beta2.Toolset) (newToolset *latest.Toolset, secre } if oldToolset.Spec.LogCollection == nil { - return newToolset, nil + return newToolset } newToolset.Spec.LogCollection = &latest.LogCollection{ Deploy: oldToolset.Spec.LogCollection.Deploy, @@ -56,7 +51,7 @@ func V1beta2Tov1(oldToolset *v1beta2.Toolset) (newToolset *latest.Toolset, secre if oldToolset.Spec.LogCollection.Resources == nil && oldToolset.Spec.LogCollection.Tolerations == nil && oldToolset.Spec.LogCollection.NodeSelector == nil { - return newToolset, nil + return newToolset } newToolset.Spec.LogCollection.Operator = &latest.Component{ @@ -65,5 +60,5 @@ func V1beta2Tov1(oldToolset *v1beta2.Toolset) (newToolset *latest.Toolset, secre Resources: oldToolset.Spec.LogCollection.Resources, } - return newToolset, nil + return newToolset } diff --git a/internal/operator/boom/api/v1beta1/argocd/argocd.go b/internal/operator/boom/api/v1beta1/argocd/argocd.go index 8f0f65dfd..a251bbe3a 100644 --- a/internal/operator/boom/api/v1beta1/argocd/argocd.go +++ b/internal/operator/boom/api/v1beta1/argocd/argocd.go @@ -35,6 +35,10 @@ func (r *Argocd) InitSecrets() { r.Auth = &auth.Auth{} } r.Auth.InitSecrets() + + for _, repo := range append(r.Repositories, r.Credentials...) { + repo.InitSecrets() + } } func (r *Argocd) IsZero() bool { @@ -70,10 +74,10 @@ type CustomImage struct { } type GopassStore struct { - SSHKey *secret2.Secret `yaml:"sshKey,omitempty"` + SSHKey *secret2.Secret `json:"sshKey,omitempty" yaml:"sshKey,omitempty"` //Existing secret with ssh-key to clone the repository for gopass ExistingSSHKeySecret *secret2.Existing `json:"existingSshKeySecret,omitempty" yaml:"existingSshKeySecret,omitempty"` - GPGKey *secret2.Secret `yaml:"gpgKey,omitempty"` + GPGKey *secret2.Secret `json:"gpgKey,omitempty" yaml:"gpgKey,omitempty"` //Existing secret with gpg-key to decode the repository for gopass ExistingGPGKeySecret *secret2.Existing `json:"existingGpgKeySecret,omitempty" yaml:"existingGpgKeySecret,omitempty"` //URL to repository for gopass store diff --git a/internal/operator/boom/api/v1beta1/argocd/auth/auth.go b/internal/operator/boom/api/v1beta1/argocd/auth/auth.go index 458c654df..efb4b4647 100644 --- a/internal/operator/boom/api/v1beta1/argocd/auth/auth.go +++ b/internal/operator/boom/api/v1beta1/argocd/auth/auth.go @@ -36,9 +36,15 @@ func (a *Auth) InitSecrets() { if a.OIDC.ClientID == nil { a.OIDC.ClientID = &secret.Secret{} } + if a.OIDC.ExistingClientIDSecret == nil { + a.OIDC.ExistingClientIDSecret = &secret.Existing{} + } if a.OIDC.ClientSecret == nil { a.OIDC.ClientSecret = &secret.Secret{} } + if a.OIDC.ExistingClientSecretSecret == nil { + a.OIDC.ExistingClientSecretSecret = &secret.Existing{} + } if a.GoogleConnector == nil { a.GoogleConnector = &google.Connector{} @@ -49,12 +55,21 @@ func (a *Auth) InitSecrets() { if a.GoogleConnector.Config.ClientID == nil { a.GoogleConnector.Config.ClientID = &secret.Secret{} } + if a.GoogleConnector.Config.ExistingClientIDSecret == nil { + a.GoogleConnector.Config.ExistingClientIDSecret = &secret.Existing{} + } if a.GoogleConnector.Config.ClientSecret == nil { a.GoogleConnector.Config.ClientSecret = &secret.Secret{} } + if a.GoogleConnector.Config.ExistingClientSecretSecret == nil { + a.GoogleConnector.Config.ExistingClientSecretSecret = &secret.Existing{} + } if a.GoogleConnector.Config.ServiceAccountJSON == nil { a.GoogleConnector.Config.ServiceAccountJSON = &secret.Secret{} } + if a.GoogleConnector.Config.ExistingServiceAccountJSONSecret == nil { + a.GoogleConnector.Config.ExistingServiceAccountJSONSecret = &secret.Existing{} + } if a.GithubConnector == nil { a.GithubConnector = &github.Connector{} @@ -65,9 +80,15 @@ func (a *Auth) InitSecrets() { if a.GithubConnector.Config.ClientID == nil { a.GithubConnector.Config.ClientID = &secret.Secret{} } + if a.GithubConnector.Config.ExistingClientIDSecret == nil { + a.GithubConnector.Config.ExistingClientIDSecret = &secret.Existing{} + } if a.GithubConnector.Config.ClientSecret == nil { a.GithubConnector.Config.ClientSecret = &secret.Secret{} } + if a.GithubConnector.Config.ExistingClientSecretSecret == nil { + a.GithubConnector.Config.ExistingClientSecretSecret = &secret.Existing{} + } if a.GitlabConnector == nil { a.GitlabConnector = &gitlab.Connector{} @@ -78,7 +99,13 @@ func (a *Auth) InitSecrets() { if a.GitlabConnector.Config.ClientID == nil { a.GitlabConnector.Config.ClientID = &secret.Secret{} } + if a.GitlabConnector.Config.ExistingClientIDSecret == nil { + a.GitlabConnector.Config.ExistingClientIDSecret = &secret.Existing{} + } if a.GitlabConnector.Config.ClientSecret == nil { a.GitlabConnector.Config.ClientSecret = &secret.Secret{} } + if a.GitlabConnector.Config.ExistingClientSecretSecret == nil { + a.GitlabConnector.Config.ExistingClientSecretSecret = &secret.Existing{} + } } diff --git a/internal/operator/boom/api/v1beta1/argocd/auth/github/github.go b/internal/operator/boom/api/v1beta1/argocd/auth/github/github.go index 8a33b6fb4..a8c8800f3 100644 --- a/internal/operator/boom/api/v1beta1/argocd/auth/github/github.go +++ b/internal/operator/boom/api/v1beta1/argocd/auth/github/github.go @@ -38,10 +38,10 @@ func (c *Config) IsZero() bool { } type Config struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Required membership to organization in github diff --git a/internal/operator/boom/api/v1beta1/argocd/auth/gitlab/gitlab.go b/internal/operator/boom/api/v1beta1/argocd/auth/gitlab/gitlab.go index 4f04788b4..9b35281da 100644 --- a/internal/operator/boom/api/v1beta1/argocd/auth/gitlab/gitlab.go +++ b/internal/operator/boom/api/v1beta1/argocd/auth/gitlab/gitlab.go @@ -37,10 +37,10 @@ func (c *Config) IsZero() bool { } type Config struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //BaseURL of the gitlab instance diff --git a/internal/operator/boom/api/v1beta1/argocd/auth/google/google.go b/internal/operator/boom/api/v1beta1/argocd/auth/google/google.go index b2ccdf046..fb32150b1 100644 --- a/internal/operator/boom/api/v1beta1/argocd/auth/google/google.go +++ b/internal/operator/boom/api/v1beta1/argocd/auth/google/google.go @@ -40,17 +40,17 @@ func (c *Config) IsZero() bool { } type Config struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //List of hosted domains which are permitted to login HostedDomains []string `json:"hostedDomains,omitempty" yaml:"hostedDomains,omitempty"` //List of groups in the hosted domains which are permitted to login Groups []string `json:"groups,omitempty" yaml:"groups,omitempty"` - ServiceAccountJSON *secret2.Secret `yaml:"serviceAccountJSON,omitempty"` + ServiceAccountJSON *secret2.Secret `json:"serviceAccountJSON,omitempty" yaml:"serviceAccountJSON,omitempty"` //Existing secret with the JSON of the service account ExistingServiceAccountJSONSecret *secret2.Existing `json:"existingServiceAccountJSONSecret,omitempty" yaml:"existingServiceAccountJSONSecret,omitempty"` //File where the serviceAccountJSON will get persisted to impersonate G Suite admin diff --git a/internal/operator/boom/api/v1beta1/argocd/auth/oidc/oidc.go b/internal/operator/boom/api/v1beta1/argocd/auth/oidc/oidc.go index b658ae022..d48b3791f 100644 --- a/internal/operator/boom/api/v1beta1/argocd/auth/oidc/oidc.go +++ b/internal/operator/boom/api/v1beta1/argocd/auth/oidc/oidc.go @@ -9,10 +9,10 @@ type OIDC struct { Name string `json:"name,omitempty" yaml:"name,omitempty"` //Issuer of the OIDC provider Issuer string `json:"issuer,omitempty" yaml:"issuer,omitempty"` - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Optional set of OIDC scopes to request. If omitted, defaults to: ["openid", "profile", "email", "groups"] diff --git a/internal/operator/boom/api/v1beta1/argocd/repository/repository.go b/internal/operator/boom/api/v1beta1/argocd/repository/repository.go index d8c50f75d..a99188b8e 100644 --- a/internal/operator/boom/api/v1beta1/argocd/repository/repository.go +++ b/internal/operator/boom/api/v1beta1/argocd/repository/repository.go @@ -1,7 +1,7 @@ package repository import ( - secret2 "github.com/caos/orbos/pkg/secret" + "github.com/caos/orbos/pkg/secret" ) // Repository: For a repository there are two types, with ssh-connection where an url and a certificate have to be provided and an https-connection where an URL, username and password have to be provided. @@ -9,14 +9,37 @@ type Repository struct { //Internal used name Name string `json:"name,omitempty" yaml:"name,omitempty"` //Prefix where the credential should be used (starting "git@" or "https://" ) - URL string `json:"url,omitempty" yaml:"url,omitempty"` - Username *secret2.Secret `yaml:"username,omitempty"` + URL string `json:"url,omitempty" yaml:"url,omitempty"` + Username *secret.Secret `json:"username,omitempty" yaml:"username,omitempty"` //Existing secret used for username - ExistingUsernameSecret *secret2.Existing `json:"existingUsernameSecret,omitempty" yaml:"existingUsernameSecret,omitempty"` - Password *secret2.Secret `yaml:"password,omitempty"` + ExistingUsernameSecret *secret.Existing `json:"existingUsernameSecret,omitempty" yaml:"existingUsernameSecret,omitempty"` + Password *secret.Secret `json:"password,omitempty" yaml:"password,omitempty"` //Existing secret used for password - ExistingPasswordSecret *secret2.Existing `json:"existingPasswordSecret,omitempty" yaml:"existingPasswordSecret,omitempty"` - Certificate *secret2.Secret `yaml:"certificate,omitempty"` + ExistingPasswordSecret *secret.Existing `json:"existingPasswordSecret,omitempty" yaml:"existingPasswordSecret,omitempty"` + Certificate *secret.Secret `json:"certificate,omitempty" yaml:"certificate,omitempty"` //Existing secret used for certificate - ExistingCertificateSecret *secret2.Existing `json:"existingCertificateSecret,omitempty" yaml:"existingCertificateSecret,omitempty"` + ExistingCertificateSecret *secret.Existing `json:"existingCertificateSecret,omitempty" yaml:"existingCertificateSecret,omitempty"` +} + +func (r *Repository) InitSecrets() { + if r.Username == nil { + r.Username = &secret.Secret{} + } + if r.ExistingUsernameSecret == nil { + r.ExistingUsernameSecret = &secret.Existing{} + } + + if r.Password == nil { + r.Password = &secret.Secret{} + } + if r.ExistingPasswordSecret == nil { + r.ExistingPasswordSecret = &secret.Existing{} + } + + if r.Certificate == nil { + r.Certificate = &secret.Secret{} + } + if r.ExistingCertificateSecret == nil { + r.ExistingCertificateSecret = &secret.Existing{} + } } diff --git a/internal/operator/boom/api/v1beta1/funcs.go b/internal/operator/boom/api/v1beta1/funcs.go index e2141ef37..94a2b106e 100644 --- a/internal/operator/boom/api/v1beta1/funcs.go +++ b/internal/operator/boom/api/v1beta1/funcs.go @@ -1,123 +1,15 @@ package v1beta1 import ( - "github.com/caos/orbos/internal/operator/boom/api/v1beta1/argocd" - "github.com/caos/orbos/internal/operator/boom/api/v1beta1/grafana" - "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" "github.com/pkg/errors" - "strings" ) -func ParseToolset(desiredTree *tree.Tree) (*Toolset, map[string]*secret.Secret, error) { +func ParseToolset(desiredTree *tree.Tree) (*Toolset, error) { desiredKind := &Toolset{} if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, nil, errors.Wrap(err, "parsing desired state failed") + return nil, errors.Wrap(err, "parsing desired state failed") } - return desiredKind, GetSecretsMap(desiredKind), nil -} - -func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { - ret := make(map[string]*secret.Secret, 0) - - if desiredKind.Spec.Grafana == nil { - desiredKind.Spec.Grafana = &grafana.Grafana{} - } - grafanaSpec := desiredKind.Spec.Grafana - grafanaSpec.InitSecrets() - - ret["grafana.admin.username"] = grafanaSpec.Admin.Username - ret["grafana.admin.password"] = grafanaSpec.Admin.Password - ret["grafana.sso.oauth.clientid"] = grafanaSpec.Auth.GenericOAuth.ClientID - ret["grafana.sso.oauth.clientsecret"] = grafanaSpec.Auth.GenericOAuth.ClientSecret - ret["grafana.sso.google.clientid"] = grafanaSpec.Auth.Google.ClientID - ret["grafana.sso.google.clientsecret"] = grafanaSpec.Auth.Google.ClientSecret - ret["grafana.sso.github.clientid"] = grafanaSpec.Auth.Github.ClientID - ret["grafana.sso.github.clientsecret"] = grafanaSpec.Auth.Github.ClientSecret - ret["grafana.sso.gitlab.clientid"] = grafanaSpec.Auth.Gitlab.ClientID - ret["grafana.sso.gitlab.clientsecret"] = grafanaSpec.Auth.Gitlab.ClientSecret - - if desiredKind.Spec.Argocd == nil { - desiredKind.Spec.Argocd = &argocd.Argocd{} - } - argocdSpec := desiredKind.Spec.Argocd - argocdSpec.InitSecrets() - - ret["argocd.sso.google.clientid"] = argocdSpec.Auth.GoogleConnector.Config.ClientID - ret["argocd.sso.google.clientsecret"] = argocdSpec.Auth.GoogleConnector.Config.ClientSecret - ret["argocd.sso.google.serviceaccountjson"] = argocdSpec.Auth.GoogleConnector.Config.ServiceAccountJSON - ret["argocd.sso.gitlab.clientid"] = argocdSpec.Auth.GitlabConnector.Config.ClientID - ret["argocd.sso.gitlab.clientsecret"] = argocdSpec.Auth.GitlabConnector.Config.ClientSecret - ret["argocd.sso.github.clientid"] = argocdSpec.Auth.GithubConnector.Config.ClientID - ret["argocd.sso.github.clientsecret"] = argocdSpec.Auth.GithubConnector.Config.ClientSecret - ret["argocd.sso.oidc.clientid"] = argocdSpec.Auth.OIDC.ClientID - ret["argocd.sso.oidc.clientsecret"] = argocdSpec.Auth.OIDC.ClientSecret - - if argocdSpec.Credentials != nil { - for _, value := range argocdSpec.Credentials { - base := strings.Join([]string{"argocd", "credential", value.Name}, ".") - - key := strings.Join([]string{base, "username"}, ".") - if value.Username == nil { - value.Username = &secret.Secret{} - } - ret[key] = value.Username - - key = strings.Join([]string{base, "password"}, ".") - if value.Password == nil { - value.Password = &secret.Secret{} - } - ret[key] = value.Password - - key = strings.Join([]string{base, "certificate"}, ".") - if value.Certificate == nil { - value.Certificate = &secret.Secret{} - } - ret[key] = value.Certificate - } - } - if argocdSpec.Repositories != nil { - for _, value := range argocdSpec.Repositories { - base := strings.Join([]string{"argocd", "repository", value.Name}, ".") - - key := strings.Join([]string{base, "username"}, ".") - if value.Username == nil { - value.Username = &secret.Secret{} - } - ret[key] = value.Username - - key = strings.Join([]string{base, "password"}, ".") - if value.Password == nil { - value.Password = &secret.Secret{} - } - ret[key] = value.Password - - key = strings.Join([]string{base, "certificate"}, ".") - if value.Certificate == nil { - value.Certificate = &secret.Secret{} - } - ret[key] = value.Certificate - } - } - - if argocdSpec.CustomImage != nil && argocdSpec.CustomImage.GopassStores != nil { - for _, value := range argocdSpec.CustomImage.GopassStores { - base := strings.Join([]string{"argocd", "gopass", value.StoreName}, ".") - - key := strings.Join([]string{base, "ssh"}, ".") - if value.SSHKey == nil { - value.SSHKey = &secret.Secret{} - } - ret[key] = value.SSHKey - - key = strings.Join([]string{base, "gpg"}, ".") - if value.GPGKey == nil { - value.GPGKey = &secret.Secret{} - } - ret[key] = value.GPGKey - } - } - - return ret + return desiredKind, nil } diff --git a/internal/operator/boom/api/v1beta1/grafana/admin/admin.go b/internal/operator/boom/api/v1beta1/grafana/admin/admin.go index e38fd7135..c50944d19 100644 --- a/internal/operator/boom/api/v1beta1/grafana/admin/admin.go +++ b/internal/operator/boom/api/v1beta1/grafana/admin/admin.go @@ -7,7 +7,7 @@ import ( // Admin: Not defining the admin credentials results in an user admin with password admin. type Admin struct { Username *secret.Secret `json:"username,omitempty" yaml:"username,omitempty"` - Password *secret.Secret `yaml:"password,omitempty"` + Password *secret.Secret `json:"password,omitempty" yaml:"password,omitempty"` //Existing Secret containing username and password ExistingSecret *secret.ExistingIDSecret `json:"existingSecret,omitempty" yaml:"existingSecret,omitempty"` } diff --git a/internal/operator/boom/api/v1beta1/grafana/auth/Generic/generic.go b/internal/operator/boom/api/v1beta1/grafana/auth/Generic/generic.go index 11a195ae1..1c707d313 100644 --- a/internal/operator/boom/api/v1beta1/grafana/auth/Generic/generic.go +++ b/internal/operator/boom/api/v1beta1/grafana/auth/Generic/generic.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Used scopes for the OAuth-flow diff --git a/internal/operator/boom/api/v1beta1/grafana/auth/Github/github.go b/internal/operator/boom/api/v1beta1/grafana/auth/Github/github.go index b94d6bd7e..5b684a3b3 100644 --- a/internal/operator/boom/api/v1beta1/grafana/auth/Github/github.go +++ b/internal/operator/boom/api/v1beta1/grafana/auth/Github/github.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` // Organizations allowed to login diff --git a/internal/operator/boom/api/v1beta1/grafana/auth/Gitlab/gitlab.go b/internal/operator/boom/api/v1beta1/grafana/auth/Gitlab/gitlab.go index 27cb108bc..d0d0e30ae 100644 --- a/internal/operator/boom/api/v1beta1/grafana/auth/Gitlab/gitlab.go +++ b/internal/operator/boom/api/v1beta1/grafana/auth/Gitlab/gitlab.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Groups of gitlab allowed to login diff --git a/internal/operator/boom/api/v1beta1/grafana/auth/Google/google.go b/internal/operator/boom/api/v1beta1/grafana/auth/Google/google.go index 42d891b51..a8a68aed7 100644 --- a/internal/operator/boom/api/v1beta1/grafana/auth/Google/google.go +++ b/internal/operator/boom/api/v1beta1/grafana/auth/Google/google.go @@ -5,10 +5,10 @@ import ( ) type Auth struct { - ClientID *secret2.Secret `yaml:"clientID,omitempty"` + ClientID *secret2.Secret `json:"clientID,omitempty" yaml:"clientID,omitempty"` //Existing secret with the clientID ExistingClientIDSecret *secret2.Existing `json:"existingClientIDSecret,omitempty" yaml:"existingClientIDSecret,omitempty"` - ClientSecret *secret2.Secret `yaml:"clientSecret,omitempty"` + ClientSecret *secret2.Secret `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"` //Existing secret with the clientSecret ExistingClientSecretSecret *secret2.Existing `json:"existingClientSecretSecret,omitempty" yaml:"existingClientSecretSecret,omitempty"` //Domains allowed to login diff --git a/internal/operator/boom/api/v1beta2/funcs.go b/internal/operator/boom/api/v1beta2/funcs.go index cf0eb315e..1faf1f0d0 100644 --- a/internal/operator/boom/api/v1beta2/funcs.go +++ b/internal/operator/boom/api/v1beta2/funcs.go @@ -10,14 +10,14 @@ import ( "github.com/pkg/errors" ) -func ParseToolset(desiredTree *tree.Tree) (*Toolset, map[string]*secret.Secret, error) { +func ParseToolset(desiredTree *tree.Tree) (*Toolset, error) { desiredKind := &Toolset{} if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, nil, errors.Wrap(err, "parsing desired state failed") + return nil, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind - return desiredKind, GetSecretsMap(desiredKind), nil + return desiredKind, nil } func GetSecretsMap(desiredKind *Toolset) map[string]*secret.Secret { diff --git a/internal/operator/boom/app/app.go b/internal/operator/boom/app/app.go index 270261ad2..f7e8ba460 100644 --- a/internal/operator/boom/app/app.go +++ b/internal/operator/boom/app/app.go @@ -3,6 +3,10 @@ package app import ( "strings" + "github.com/caos/orbos/internal/operator/boom/api" + crdconfig "github.com/caos/orbos/internal/operator/boom/crd/config" + "github.com/caos/orbos/pkg/tree" + bundleconfig "github.com/caos/orbos/internal/operator/boom/bundle/config" "github.com/caos/orbos/internal/operator/boom/crd" "github.com/caos/orbos/internal/operator/boom/current" @@ -19,7 +23,7 @@ import ( type App struct { ToolsDirectoryPath string GitCrd *gitcrd.GitCrd - Crds map[string]crd.Crd + Crds map[string]*crd.Crd monitor mntr.Monitor } @@ -30,7 +34,7 @@ func New(monitor mntr.Monitor, toolsDirectoryPath string) *App { monitor: monitor, } - app.Crds = make(map[string]crd.Crd, 0) + app.Crds = make(map[string]*crd.Crd, 0) return app } @@ -135,40 +139,46 @@ func (a *App) WriteBackCurrentState() error { return nil } -// func (a *App) ReconcileCrd(version, namespacedName string, getToolsetCRD func(instance runtime.Object) error) error { -// a.monitor.WithFields(map[string]interface{}{ -// "name": namespacedName, -// }).Info("Started reconciling of CRD") - -// var err error -// managedcrd, ok := a.Crds[namespacedName] -// if !ok { -// crdConf := &crdconfig.Config{ -// Monitor: a.monitor, -// Version: v1beta1.GetVersion(), -// } - -// managedcrd, err = crd.New(crdConf) -// if err != nil { -// return err -// } - -// bundleConf := &bundleconfig.Config{ -// Monitor: a.monitor, -// CrdName: namespacedName, -// BundleName: bundles.Caos, -// BaseDirectoryPath: a.ToolsDirectoryPath, -// Templator: helm.GetName(), -// } -// managedcrd.SetBundle(bundleConf) - -// if err := managedcrd.GetStatus(); err != nil { -// return err -// } - -// a.Crds[namespacedName] = managedcrd -// } - -// managedcrd.ReconcileWithFunc(getToolsetCRD) -// return managedcrd.GetStatus() -// } +func (a *App) ReconcileCrd(namespacedName string, toolsetCRD *tree.Tree) error { + a.monitor.WithFields(map[string]interface{}{ + "name": namespacedName, + }).Info("Started reconciling of CRD") + + var err error + managedcrd, ok := a.Crds[namespacedName] + if !ok { + crdConf := &crdconfig.Config{ + Monitor: a.monitor, + } + + managedcrd = crd.New(crdConf) + + bundleConf := &bundleconfig.Config{ + Monitor: a.monitor, + CrdName: namespacedName, + BundleName: bundles.Caos, + BaseDirectoryPath: a.ToolsDirectoryPath, + Templator: helm.GetName(), + } + managedcrd.SetBundle(bundleConf) + + if err := managedcrd.GetStatus(); err != nil { + return err + } + + a.Crds[namespacedName] = managedcrd + } + + currentResourceList, err := a.getCurrent(a.monitor) + if err != nil { + return err + } + + desired, _, _, _, err := api.ParseToolset(toolsetCRD) + if err != nil { + return err + } + + managedcrd.Reconcile(currentResourceList, desired, false) + return managedcrd.GetStatus() +} diff --git a/internal/operator/boom/application/applications/argocd/config/auth/github.go b/internal/operator/boom/application/applications/argocd/config/auth/github.go index f706ed2ce..7c5892887 100644 --- a/internal/operator/boom/application/applications/argocd/config/auth/github.go +++ b/internal/operator/boom/application/applications/argocd/config/auth/github.go @@ -2,7 +2,7 @@ package auth import ( "github.com/caos/orbos/internal/operator/boom/api/latest/reconciling/auth/github" - helper2 "github.com/caos/orbos/internal/utils/helper" + "github.com/caos/orbos/pkg/helper" ) type githubConnector struct { @@ -20,12 +20,12 @@ type org struct { } func getGithub(spec *github.Connector, redirect string) (interface{}, error) { - clientID, err := helper2.GetSecretValue(spec.Config.ClientID, spec.Config.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.Config.ClientID, spec.Config.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.Config.ClientSecret, spec.Config.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.Config.ClientSecret, spec.Config.ExistingClientSecretSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/argocd/config/auth/gitlab.go b/internal/operator/boom/application/applications/argocd/config/auth/gitlab.go index 8b4404c56..a38c953b8 100644 --- a/internal/operator/boom/application/applications/argocd/config/auth/gitlab.go +++ b/internal/operator/boom/application/applications/argocd/config/auth/gitlab.go @@ -2,7 +2,7 @@ package auth import ( "github.com/caos/orbos/internal/operator/boom/api/latest/reconciling/auth/gitlab" - helper2 "github.com/caos/orbos/internal/utils/helper" + "github.com/caos/orbos/pkg/helper" ) type gitlabConnector struct { @@ -15,12 +15,12 @@ type gitlabConnector struct { } func getGitlab(spec *gitlab.Connector, redirect string) (interface{}, error) { - clientID, err := helper2.GetSecretValue(spec.Config.ClientID, spec.Config.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.Config.ClientID, spec.Config.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.Config.ClientSecret, spec.Config.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.Config.ClientSecret, spec.Config.ExistingClientSecretSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/argocd/config/auth/google.go b/internal/operator/boom/application/applications/argocd/config/auth/google.go index 5ef8b2992..799a99ab4 100644 --- a/internal/operator/boom/application/applications/argocd/config/auth/google.go +++ b/internal/operator/boom/application/applications/argocd/config/auth/google.go @@ -1,13 +1,12 @@ package auth import ( + "github.com/caos/orbos/pkg/helper" "io/ioutil" "os" "path/filepath" "github.com/caos/orbos/internal/operator/boom/api/latest/reconciling/auth/google" - helper2 "github.com/caos/orbos/internal/utils/helper" - "github.com/pkg/errors" ) @@ -23,17 +22,17 @@ type googleConnector struct { } func getGoogle(spec *google.Connector, redirect string) (interface{}, error) { - clientID, err := helper2.GetSecretValue(spec.Config.ClientID, spec.Config.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.Config.ClientID, spec.Config.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.Config.ClientSecret, spec.Config.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.Config.ClientSecret, spec.Config.ExistingClientSecretSecret) if err != nil { return nil, err } - serviceAccountJSON, err := helper2.GetSecretValue(spec.Config.ServiceAccountJSON, spec.Config.ExistingServiceAccountJSONSecret) + serviceAccountJSON, err := helper.GetSecretValueOnlyIncluster(spec.Config.ServiceAccountJSON, spec.Config.ExistingServiceAccountJSONSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/argocd/config/auth/oidc.go b/internal/operator/boom/application/applications/argocd/config/auth/oidc.go index d7e0eb78c..be9e7d6fb 100644 --- a/internal/operator/boom/application/applications/argocd/config/auth/oidc.go +++ b/internal/operator/boom/application/applications/argocd/config/auth/oidc.go @@ -2,7 +2,7 @@ package auth import ( "github.com/caos/orbos/internal/operator/boom/api/latest/reconciling/auth" - helper2 "github.com/caos/orbos/internal/utils/helper" + "github.com/caos/orbos/pkg/helper" "github.com/pkg/errors" "gopkg.in/yaml.v3" ) @@ -25,12 +25,12 @@ func GetOIDC(spec *auth.Auth) (string, error) { return "", nil } - clientID, err := helper2.GetSecretValue(spec.OIDC.ClientID, spec.OIDC.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.OIDC.ClientID, spec.OIDC.ExistingClientIDSecret) if err != nil { return "", err } - clientSecret, err := helper2.GetSecretValue(spec.OIDC.ClientSecret, spec.OIDC.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.OIDC.ClientSecret, spec.OIDC.ExistingClientSecretSecret) if err != nil { return "", err } diff --git a/internal/operator/boom/application/applications/argocd/config/credential/credential.go b/internal/operator/boom/application/applications/argocd/config/credential/credential.go index 88547ebe3..d4dbc6eb2 100644 --- a/internal/operator/boom/application/applications/argocd/config/credential/credential.go +++ b/internal/operator/boom/application/applications/argocd/config/credential/credential.go @@ -1,13 +1,13 @@ package credential import ( + "github.com/caos/orbos/pkg/helper" "strings" "github.com/caos/orbos/internal/operator/boom/api/latest/reconciling" "github.com/caos/orbos/internal/operator/boom/application/applications/argocd/info" "github.com/caos/orbos/internal/operator/boom/application/resources" "github.com/caos/orbos/internal/operator/boom/labels" - helper2 "github.com/caos/orbos/internal/utils/helper" "github.com/caos/orbos/mntr" ) @@ -42,7 +42,7 @@ func GetSecrets(spec *reconciling.Reconciling) []interface{} { namespace := "caos-system" for _, v := range spec.Credentials { - if helper2.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { + if helper.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { data := map[string]string{ getSecretKey(user): v.Username.Value, } @@ -56,7 +56,7 @@ func GetSecrets(spec *reconciling.Reconciling) []interface{} { secretRes := resources.NewSecret(conf) secrets = append(secrets, secretRes) } - if helper2.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { + if helper.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { data := map[string]string{ getSecretKey(pw): v.Password.Value, @@ -71,7 +71,7 @@ func GetSecrets(spec *reconciling.Reconciling) []interface{} { secretRes := resources.NewSecret(conf) secrets = append(secrets, secretRes) } - if helper2.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { + if helper.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { data := map[string]string{ getSecretKey(cert): v.Certificate.Value, } @@ -99,36 +99,36 @@ func GetFromSpec(monitor mntr.Monitor, spec *reconciling.Reconciling) []*Credent for _, v := range spec.Credentials { var us, ps, ssh *secret - if helper2.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { + if helper.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { us = &secret{ Name: getSecretName(v.Name, user), Key: getSecretKey(user), } - } else if helper2.IsExistentSecret(v.Username, v.ExistingUsernameSecret) { + } else if helper.IsExistentSecret(v.Username, v.ExistingUsernameSecret) { us = &secret{ Name: v.ExistingUsernameSecret.Name, Key: v.ExistingUsernameSecret.Key, } } - if helper2.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { + if helper.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { ps = &secret{ Name: getSecretName(v.Name, pw), Key: getSecretKey(pw), } - } else if helper2.IsExistentSecret(v.Password, v.ExistingPasswordSecret) { + } else if helper.IsExistentSecret(v.Password, v.ExistingPasswordSecret) { ps = &secret{ Name: v.ExistingPasswordSecret.Name, Key: v.ExistingPasswordSecret.Key, } } - if helper2.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { + if helper.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { ssh = &secret{ Name: getSecretName(v.Name, cert), Key: getSecretKey(cert), } - } else if helper2.IsExistentSecret(v.Certificate, v.ExistingCertificateSecret) { + } else if helper.IsExistentSecret(v.Certificate, v.ExistingCertificateSecret) { ssh = &secret{ Name: v.ExistingCertificateSecret.Name, Key: v.ExistingCertificateSecret.Key, diff --git a/internal/operator/boom/application/applications/argocd/config/repository/repository.go b/internal/operator/boom/application/applications/argocd/config/repository/repository.go index 352452f80..ada58d4ce 100644 --- a/internal/operator/boom/application/applications/argocd/config/repository/repository.go +++ b/internal/operator/boom/application/applications/argocd/config/repository/repository.go @@ -1,13 +1,13 @@ package repository import ( + "github.com/caos/orbos/pkg/helper" "strings" "github.com/caos/orbos/internal/operator/boom/api/latest/reconciling" "github.com/caos/orbos/internal/operator/boom/application/applications/argocd/info" "github.com/caos/orbos/internal/operator/boom/application/resources" "github.com/caos/orbos/internal/operator/boom/labels" - helper2 "github.com/caos/orbos/internal/utils/helper" "github.com/caos/orbos/mntr" ) @@ -42,7 +42,7 @@ func GetSecrets(spec *reconciling.Reconciling) []interface{} { namespace := "caos-system" for _, v := range spec.Repositories { - if helper2.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { + if helper.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { data := map[string]string{ getSecretKey(user): v.Username.Value, @@ -57,7 +57,7 @@ func GetSecrets(spec *reconciling.Reconciling) []interface{} { secretRes := resources.NewSecret(conf) secrets = append(secrets, secretRes) } - if helper2.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { + if helper.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { data := map[string]string{ getSecretKey(pw): v.Password.Value, @@ -72,7 +72,7 @@ func GetSecrets(spec *reconciling.Reconciling) []interface{} { secretRes := resources.NewSecret(conf) secrets = append(secrets, secretRes) } - if helper2.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { + if helper.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { data := map[string]string{ getSecretKey(cert): v.Certificate.Value, } @@ -100,36 +100,36 @@ func GetFromSpec(monitor mntr.Monitor, spec *reconciling.Reconciling) []*Reposit for _, v := range spec.Repositories { var us, ps, ssh *secret - if helper2.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { + if helper.IsCrdSecret(v.Username, v.ExistingUsernameSecret) { us = &secret{ Name: getSecretName(v.Name, user), Key: getSecretKey(user), } - } else if helper2.IsExistentSecret(v.Username, v.ExistingUsernameSecret) { + } else if helper.IsExistentSecret(v.Username, v.ExistingUsernameSecret) { us = &secret{ Name: v.ExistingUsernameSecret.Name, Key: v.ExistingUsernameSecret.Key, } } - if helper2.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { + if helper.IsCrdSecret(v.Password, v.ExistingPasswordSecret) { ps = &secret{ Name: getSecretName(v.Name, pw), Key: getSecretKey(pw), } - } else if helper2.IsExistentSecret(v.Password, v.ExistingPasswordSecret) { + } else if helper.IsExistentSecret(v.Password, v.ExistingPasswordSecret) { ps = &secret{ Name: v.ExistingPasswordSecret.Name, Key: v.ExistingPasswordSecret.Key, } } - if helper2.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { + if helper.IsCrdSecret(v.Certificate, v.ExistingCertificateSecret) { ssh = &secret{ Name: getSecretName(v.Name, cert), Key: getSecretKey(cert), } - } else if helper2.IsExistentSecret(v.Certificate, v.ExistingCertificateSecret) { + } else if helper.IsExistentSecret(v.Certificate, v.ExistingCertificateSecret) { ssh = &secret{ Name: v.ExistingCertificateSecret.Name, Key: v.ExistingCertificateSecret.Key, diff --git a/internal/operator/boom/application/applications/argocd/customimage/customimage.go b/internal/operator/boom/application/applications/argocd/customimage/customimage.go index 136c4c32e..874589308 100644 --- a/internal/operator/boom/application/applications/argocd/customimage/customimage.go +++ b/internal/operator/boom/application/applications/argocd/customimage/customimage.go @@ -2,7 +2,7 @@ package customimage import ( "encoding/json" - secret2 "github.com/caos/orbos/pkg/secret" + "github.com/caos/orbos/pkg/secret" "path/filepath" "strings" @@ -10,9 +10,8 @@ import ( "github.com/caos/orbos/internal/operator/boom/application/applications/argocd/info" "github.com/caos/orbos/internal/operator/boom/application/resources" "github.com/caos/orbos/internal/operator/boom/labels" - helper2 "github.com/caos/orbos/internal/utils/helper" - "github.com/caos/orbos/internal/utils/helper" + helper2 "github.com/caos/orbos/pkg/helper" "github.com/pkg/errors" ) @@ -136,7 +135,7 @@ func FromSpec(spec *reconciling.Reconciling, imageTags map[string]string) *Custo } } -func getVolAndVolMount(storeName string, ty string, secret *secret2.Secret, existent *secret2.Existing, foldername string) (*SecretVolume, *VolumeMount) { +func getVolAndVolMount(storeName string, ty string, secret *secret.Secret, existent *secret.Existing, foldername string) (*SecretVolume, *VolumeMount) { internalName := "" name := "" key := "" diff --git a/internal/operator/boom/application/applications/grafana/admin/admin.go b/internal/operator/boom/application/applications/grafana/admin/admin.go index b83e8dec5..51a5ce641 100644 --- a/internal/operator/boom/application/applications/grafana/admin/admin.go +++ b/internal/operator/boom/application/applications/grafana/admin/admin.go @@ -1,6 +1,7 @@ package admin import ( + "github.com/caos/orbos/pkg/helper" "strings" "github.com/caos/orbos/internal/operator/boom/api/latest/monitoring/admin" @@ -8,7 +9,6 @@ import ( "github.com/caos/orbos/internal/operator/boom/application/applications/grafana/info" "github.com/caos/orbos/internal/operator/boom/application/resources" "github.com/caos/orbos/internal/operator/boom/labels" - helper2 "github.com/caos/orbos/internal/utils/helper" ) func getSecretName() string { @@ -28,7 +28,7 @@ func GetSecrets(adminSpec *admin.Admin) []interface{} { secrets := make([]interface{}, 0) - if !helper2.IsExistentClientSecret(adminSpec.ExistingSecret) { + if !helper.IsExistentClientSecret(adminSpec.ExistingSecret) { if adminSpec.Username.Value == "" && adminSpec.Password.Value == "" { return secrets } @@ -57,7 +57,7 @@ func GetSecrets(adminSpec *admin.Admin) []interface{} { } func GetConfig(adminSpec *admin.Admin) *helm.Admin { - if helper2.IsExistentClientSecret(adminSpec.ExistingSecret) { + if helper.IsExistentClientSecret(adminSpec.ExistingSecret) { return &helm.Admin{ ExistingSecret: adminSpec.ExistingSecret.Name, UserKey: adminSpec.ExistingSecret.IDKey, diff --git a/internal/operator/boom/application/applications/grafana/auth/generic_oauth.go b/internal/operator/boom/application/applications/grafana/auth/generic_oauth.go index ba8671477..5a769cba9 100644 --- a/internal/operator/boom/application/applications/grafana/auth/generic_oauth.go +++ b/internal/operator/boom/application/applications/grafana/auth/generic_oauth.go @@ -1,19 +1,19 @@ package auth import ( + "github.com/caos/orbos/pkg/helper" "strings" generic "github.com/caos/orbos/internal/operator/boom/api/latest/monitoring/auth/Generic" - helper2 "github.com/caos/orbos/internal/utils/helper" ) func GetGenericOAuthConfig(spec *generic.Auth) (map[string]string, error) { - clientID, err := helper2.GetSecretValue(spec.ClientID, spec.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.ClientID, spec.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.ClientSecret, spec.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.ClientSecret, spec.ExistingClientSecretSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/grafana/auth/github.go b/internal/operator/boom/application/applications/grafana/auth/github.go index 89eb86a1b..ff334e64a 100644 --- a/internal/operator/boom/application/applications/grafana/auth/github.go +++ b/internal/operator/boom/application/applications/grafana/auth/github.go @@ -1,19 +1,19 @@ package auth import ( + "github.com/caos/orbos/pkg/helper" "strings" github "github.com/caos/orbos/internal/operator/boom/api/latest/monitoring/auth/Github" - helper2 "github.com/caos/orbos/internal/utils/helper" ) func GetGithubAuthConfig(spec *github.Auth) (map[string]string, error) { - clientID, err := helper2.GetSecretValue(spec.ClientID, spec.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.ClientID, spec.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.ClientSecret, spec.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.ClientSecret, spec.ExistingClientSecretSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/grafana/auth/gitlab.go b/internal/operator/boom/application/applications/grafana/auth/gitlab.go index 98f203552..ab654878c 100644 --- a/internal/operator/boom/application/applications/grafana/auth/gitlab.go +++ b/internal/operator/boom/application/applications/grafana/auth/gitlab.go @@ -1,19 +1,19 @@ package auth import ( + "github.com/caos/orbos/pkg/helper" "strings" gitlab "github.com/caos/orbos/internal/operator/boom/api/latest/monitoring/auth/Gitlab" - helper2 "github.com/caos/orbos/internal/utils/helper" ) func GetGitlabAuthConfig(spec *gitlab.Auth) (map[string]string, error) { - clientID, err := helper2.GetSecretValue(spec.ClientID, spec.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.ClientID, spec.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.ClientSecret, spec.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.ClientSecret, spec.ExistingClientSecretSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/grafana/auth/google.go b/internal/operator/boom/application/applications/grafana/auth/google.go index ac5d265eb..f0d6ed1b9 100644 --- a/internal/operator/boom/application/applications/grafana/auth/google.go +++ b/internal/operator/boom/application/applications/grafana/auth/google.go @@ -1,19 +1,19 @@ package auth import ( + "github.com/caos/orbos/pkg/helper" "strings" google "github.com/caos/orbos/internal/operator/boom/api/latest/monitoring/auth/Google" - helper2 "github.com/caos/orbos/internal/utils/helper" ) func GetGoogleAuthConfig(spec *google.Auth) (map[string]string, error) { - clientID, err := helper2.GetSecretValue(spec.ClientID, spec.ExistingClientIDSecret) + clientID, err := helper.GetSecretValueOnlyIncluster(spec.ClientID, spec.ExistingClientIDSecret) if err != nil { return nil, err } - clientSecret, err := helper2.GetSecretValue(spec.ClientSecret, spec.ExistingClientSecretSecret) + clientSecret, err := helper.GetSecretValueOnlyIncluster(spec.ClientSecret, spec.ExistingClientSecretSecret) if err != nil { return nil, err } diff --git a/internal/operator/boom/application/applications/grafana/helm/default.go b/internal/operator/boom/application/applications/grafana/helm/default.go index c686f2f1e..ac508a3a6 100644 --- a/internal/operator/boom/application/applications/grafana/helm/default.go +++ b/internal/operator/boom/application/applications/grafana/helm/default.go @@ -46,7 +46,7 @@ func DefaultValues(imageTags map[string]string) *Values { Image: "dduportal/bats", Tag: imageTags["dduportal/bats"], }, - Plugins: []string{"grafana-piechart-panel"}, + Plugins: []string{}, Ini: &Ini{ Paths: map[string]string{ "data": "/var/lib/grafana/data", diff --git a/internal/operator/boom/application/applications/metricsserver/helm/default.go b/internal/operator/boom/application/applications/metricsserver/helm/default.go index 8d7ec9ed5..b5653fad4 100644 --- a/internal/operator/boom/application/applications/metricsserver/helm/default.go +++ b/internal/operator/boom/application/applications/metricsserver/helm/default.go @@ -17,8 +17,11 @@ func DefaultValues(imageTags map[string]string) *Values { Tag: imageTags["k8s.gcr.io/metrics-server-amd64"], PullPolicy: "IfNotPresent", }, - ImagePullSecrets: nil, - Args: []string{"--kubelet-insecure-tls"}, + ImagePullSecrets: nil, + Args: []string{ + "--kubelet-insecure-tls", + "--kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP", + }, Resources: struct{}{}, NodeSelector: struct{}{}, Tolerations: nil, diff --git a/internal/operator/boom/bundle/apply.go b/internal/operator/boom/bundle/apply.go index d48db7f90..47120364d 100644 --- a/internal/operator/boom/bundle/apply.go +++ b/internal/operator/boom/bundle/apply.go @@ -62,7 +62,7 @@ func applyWithCurrentState(monitor mntr.Monitor, currentResourceList []*clientgo if deleteResources != nil && len(deleteResources) > 0 { for _, deleteResource := range deleteResources { - if err := clientgo.DeleteResource(deleteResource); err != nil { + if err := clientgo.DeleteResource(monitor, deleteResource); err != nil { return err } } diff --git a/internal/operator/boom/bundle/delete.go b/internal/operator/boom/bundle/delete.go index cfc8d388d..2db91040c 100644 --- a/internal/operator/boom/bundle/delete.go +++ b/internal/operator/boom/bundle/delete.go @@ -19,7 +19,7 @@ func deleteWithCurrentState(monitor mntr.Monitor, currentResourceList []*clientg resultFunc := func(resultFilePath, namespace string) error { for _, resource := range currentResourceList { - if err := clientgo.DeleteResource(resource); err != nil { + if err := clientgo.DeleteResource(monitor, resource); err != nil { err := errors.Wrap(err, "Failed to delete resource") delMonitor.Error(err) return err diff --git a/internal/operator/boom/cmd/reconcile.go b/internal/operator/boom/cmd/reconcile.go index 74ff9de40..2e36ba8f2 100644 --- a/internal/operator/boom/cmd/reconcile.go +++ b/internal/operator/boom/cmd/reconcile.go @@ -13,7 +13,14 @@ import ( "k8s.io/apimachinery/pkg/api/resource" ) -func Reconcile(monitor mntr.Monitor, apiLabels *labels.API, k8sClient *kubernetes.Client, boomSpec *latest.Boom, binaryVersion string) error { +func Reconcile( + monitor mntr.Monitor, + apiLabels *labels.API, + k8sClient kubernetes.ClientInt, + boomSpec *latest.Boom, + binaryVersion string, + gitops bool, +) error { resources := k8s.Resources(corev1.ResourceRequirements{ Limits: corev1.ResourceList{ @@ -55,14 +62,12 @@ func Reconcile(monitor mntr.Monitor, apiLabels *labels.API, k8sClient *kubernete recMonitor := monitor.WithField("version", boomVersion) - if !k8sClient.Available() { - recMonitor.Info("Failed to connect to k8s") - return nil - } - - if err := kubernetes.EnsureBoomArtifacts(monitor, apiLabels, k8sClient, boomVersion, tolerations, nodeselector, &resources, imageRegistry); err != nil { + if err := kubernetes.EnsureBoomArtifacts(monitor, apiLabels, k8sClient, boomVersion, tolerations, nodeselector, &resources, imageRegistry, gitops); err != nil { recMonitor.Error(errors.Wrap(err, "Failed to deploy boom into k8s-cluster")) return err } + + recMonitor.Info("Applied BOOM") + return nil } diff --git a/internal/operator/boom/crd/crd.go b/internal/operator/boom/crd/crd.go index e7aa37335..a9d1f5033 100644 --- a/internal/operator/boom/crd/crd.go +++ b/internal/operator/boom/crd/crd.go @@ -2,6 +2,12 @@ package crd import ( "errors" + "strings" + + "github.com/caos/orbos/internal/operator/boom/cmd" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/labels" + ctrl "sigs.k8s.io/controller-runtime" toolsetslatest "github.com/caos/orbos/internal/operator/boom/api/latest" "github.com/caos/orbos/internal/operator/boom/bundle" @@ -72,7 +78,7 @@ func (c *Crd) GetBundle() *bundle.Bundle { return c.bundle } -func (c *Crd) Reconcile(currentResourceList []*clientgo.Resource, toolsetCRD *toolsetslatest.Toolset) { +func (c *Crd) Reconcile(currentResourceList []*clientgo.Resource, toolsetCRD *toolsetslatest.Toolset, gitops bool) { if c.GetStatus() != nil { return } @@ -90,11 +96,47 @@ func (c *Crd) Reconcile(currentResourceList []*clientgo.Resource, toolsetCRD *to } if c.bundle == nil { - c.status = errors.New("No bundle for crd") + c.status = errors.New("no bundle for crd") monitor.Error(c.status) return } + boomSpec := toolsetCRD.Spec.Boom + if boomSpec != nil && boomSpec.SelfReconciling && boomSpec.Version != "" { + conf, err := ctrl.GetConfig() + if err != nil { + c.status = err + return + } + + dummyKubeconfig := "" + k8sClient := kubernetes.NewK8sClient(monitor, &dummyKubeconfig) + if err := k8sClient.RefreshConfig(conf); err != nil { + c.status = err + return + } + + apiVersion := toolsetCRD.APIVersion + apiVersionSplit := strings.Split(apiVersion, "/") + if len(apiVersionSplit) == 2 { + apiVersion = apiVersionSplit[1] + } + + if err := cmd.Reconcile( + monitor, + labels.MustForAPI(labels.MustForOperator("ORBOS", "boom.caos.ch", boomSpec.Version), toolsetCRD.Kind, apiVersion), + k8sClient, + boomSpec, + boomSpec.Version, + gitops, + ); err != nil { + c.status = err + return + } + } else { + monitor.Info("not reconciling BOOM itself as selfReconciling is not specified to true or version is empty") + } + c.status = c.bundle.Reconcile(currentResourceList, toolsetCRD.Spec) if c.status != nil { metrics.FailureReconcilingBundle(c.bundle.GetPredefinedBundle()) diff --git a/internal/operator/boom/gitcrd/gitcrd.go b/internal/operator/boom/gitcrd/gitcrd.go index 041c2a28d..e4a6c236c 100644 --- a/internal/operator/boom/gitcrd/gitcrd.go +++ b/internal/operator/boom/gitcrd/gitcrd.go @@ -6,15 +6,10 @@ import ( "path/filepath" "strings" - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/pkg/kubernetes" - orbosapi "github.com/caos/orbos/internal/api" "github.com/caos/orbos/internal/operator/boom/api" toolsetslatest "github.com/caos/orbos/internal/operator/boom/api/latest" bundleconfig "github.com/caos/orbos/internal/operator/boom/bundle/config" - "github.com/caos/orbos/internal/operator/boom/cmd" "github.com/caos/orbos/internal/operator/boom/crd" crdconfig "github.com/caos/orbos/internal/operator/boom/crd/config" "github.com/caos/orbos/internal/operator/boom/current" @@ -136,41 +131,12 @@ func (c *GitCrd) Reconcile(currentResourceList []*clientgo.Resource) { "action": "reconiling", }) - toolsetCRD, apiKind, apiVersion, err := c.getCrdContent() + toolsetCRD, err := c.getCrdContent() if err != nil { c.status = err return } - boomSpec := toolsetCRD.Spec.Boom - if boomSpec != nil && boomSpec.SelfReconciling && boomSpec.Version != "" { - conf, err := clientgo.GetClusterConfig() - if err != nil { - c.status = err - return - } - - dummyKubeconfig := "" - k8sClient := kubernetes.NewK8sClient(monitor, &dummyKubeconfig) - if err := k8sClient.RefreshConfig(conf); err != nil { - c.status = err - return - } - - if err := cmd.Reconcile( - monitor, - labels.MustForAPI(labels.MustForOperator("ORBOS", "boom.caos.ch", boomSpec.Version), apiKind, apiVersion), - k8sClient, - boomSpec, - boomSpec.Version, - ); err != nil { - c.status = err - return - } - } else { - monitor.Info("not reconciling BOOM itself as selfReconciling is not specified to true or version is empty") - } - // pre-steps if toolsetCRD.Spec.PreApply != nil { preapplymonitor := monitor.WithField("application", "preapply") @@ -182,7 +148,7 @@ func (c *GitCrd) Reconcile(currentResourceList []*clientgo.Resource) { preapplymonitor.Info("Done") } - c.crd.Reconcile(currentResourceList, toolsetCRD) + c.crd.Reconcile(currentResourceList, toolsetCRD, true) err = c.crd.GetStatus() if err != nil { c.status = err @@ -212,19 +178,19 @@ func (c *GitCrd) getCrdMetadata() (*toolsetslatest.ToolsetMetadata, error) { } -func (c *GitCrd) getCrdContent() (*toolsetslatest.Toolset, string, string, error) { +func (c *GitCrd) getCrdContent() (*toolsetslatest.Toolset, error) { desiredTree, err := orbosapi.ReadBoomYml(c.git) if err != nil { - return nil, "", "", err + return nil, err } - desiredKind, _, _, apiKind, apiVersion, err := api.ParseToolset(desiredTree) + desiredKind, _, _, _, err := api.ParseToolset(desiredTree) if err != nil { - return nil, "", "", errors.Wrap(err, "parsing desired state failed") + return nil, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind - return desiredKind, apiKind, apiVersion, nil + return desiredKind, nil } func (c *GitCrd) WriteBackCurrentState(currentResourceList []*clientgo.Resource) { @@ -238,7 +204,7 @@ func (c *GitCrd) WriteBackCurrentState(currentResourceList []*clientgo.Resource) return } - toolsetCRD, _, _, err := c.getCrdContent() + toolsetCRD, err := c.getCrdContent() if err != nil { c.status = err return diff --git a/internal/operator/boom/takeoff.go b/internal/operator/boom/takeoff.go index 494b8bf30..4cd5efb83 100644 --- a/internal/operator/boom/takeoff.go +++ b/internal/operator/boom/takeoff.go @@ -7,13 +7,11 @@ import ( "time" "github.com/caos/orbos/pkg/git" - - "github.com/caos/orbos/internal/orb" + "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/internal/operator/boom/app" gconfig "github.com/caos/orbos/internal/operator/boom/application/applications/grafana/config" gitcrdconfig "github.com/caos/orbos/internal/operator/boom/gitcrd/config" - "github.com/caos/orbos/internal/utils/clientgo" "github.com/caos/orbos/mntr" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -36,13 +34,9 @@ func Metrics(monitor mntr.Monitor) { }() } -func Takeoff(monitor mntr.Monitor, toolsDirectoryPath string, localMode bool, orbpath string, ensureClient, queryClient *git.Client) (func(), func()) { +func Takeoff(monitor mntr.Monitor, toolsDirectoryPath string, orbpath string, ensureClient, queryClient *git.Client) (func(), func()) { gitcrdMonitor := monitor.WithField("type", "gitcrd") - if localMode { - clientgo.InConfig = false - } - gconfig.DashboardsDirectoryPath = filepath.Join(toolsDirectoryPath, "dashboards") appStruct := app.New(monitor, toolsDirectoryPath) diff --git a/internal/operator/common/nodeagent-model.go b/internal/operator/common/nodeagent-model.go index 2c3a4b213..fd65eeba0 100644 --- a/internal/operator/common/nodeagent-model.go +++ b/internal/operator/common/nodeagent-model.go @@ -84,6 +84,11 @@ func (n *CurrentNodeAgents) Set(id string, na *NodeAgentCurrent) { if n.NA == nil { n.NA = make(map[string]*NodeAgentCurrent) } + + if _, ok := n.NA[id]; ok { + n.NA[id] = nil + } + n.NA[id] = na } @@ -121,6 +126,10 @@ type DesiredNodeAgents struct { func (n *DesiredNodeAgents) Delete(id string) { n.mux.Lock() defer n.mux.Unlock() + + if _, ok := n.NA[id]; ok { + n.NA[id] = nil + } delete(n.NA, id) } diff --git a/internal/operator/core/adapt.go b/internal/operator/core/adapt.go index a1e402ab3..9f239244c 100644 --- a/internal/operator/core/adapt.go +++ b/internal/operator/core/adapt.go @@ -11,7 +11,18 @@ import ( "gopkg.in/yaml.v3" ) -type AdaptFunc func(monitor mntr.Monitor, desired *tree.Tree, current *tree.Tree) (QueryFunc, DestroyFunc, map[string]*secret.Secret, error) +type AdaptFunc func( + monitor mntr.Monitor, + desired *tree.Tree, + current *tree.Tree, +) ( + QueryFunc, + DestroyFunc, + map[string]*secret.Secret, + map[string]*secret.Existing, + bool, + error, +) type EnsureFunc func(k8sClient kubernetes.ClientInt) error diff --git a/internal/operator/networking/kinds/networking/legacycf/adapt.go b/internal/operator/networking/kinds/networking/legacycf/adapt.go index 55d9af411..7abd4f7a7 100644 --- a/internal/operator/networking/kinds/networking/legacycf/adapt.go +++ b/internal/operator/networking/kinds/networking/legacycf/adapt.go @@ -25,6 +25,8 @@ func AdaptFunc( opcore.QueryFunc, opcore.DestroyFunc, map[string]*secret.Secret, + map[string]*secret.Existing, + bool, error, ) { internalMonitor := monitor.WithField("kind", "legacycf") @@ -32,7 +34,7 @@ func AdaptFunc( desiredKind, err := parseDesired(desiredTree) if err != nil { - return nil, nil, nil, errors.Wrap(err, "parsing desired state failed") + return nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind @@ -41,16 +43,19 @@ func AdaptFunc( } if desiredKind.Spec == nil { - return nil, nil, nil, errors.New("No specs found") + return nil, nil, nil, nil, false, errors.New("No specs found") } - if err := desiredKind.Spec.Validate(); err != nil { - return nil, nil, nil, err + if err := desiredKind.Spec.Validate(id); err != nil { + return nil, nil, nil, nil, false, err } internalSpec, current := desiredKind.Spec.Internal(id, namespace, apiLabels) legacyQuerier, legacyDestroyer, readyCertificate, err := adaptFunc(monitor, internalSpec) + if err != nil { + return nil, nil, nil, nil, false, err + } current.ReadyCertificate = readyCertificate queriers := []opcore.QueryFunc{ @@ -58,14 +63,22 @@ func AdaptFunc( } currentTree.Parsed = current + secrets, existing := getSecretsMap(desiredKind) + return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (opcore.EnsureFunc, error) { + if err := desiredKind.Spec.ValidateSecrets(); err != nil { + return nil, err + } + core.SetQueriedForNetworking(queried, currentTree) internalMonitor.Info("set current state legacycf") return opcore.QueriersToEnsureFunc(internalMonitor, true, queriers, k8sClient, queried) }, opcore.DestroyersToDestroyFunc(internalMonitor, []opcore.DestroyFunc{legacyDestroyer}), - getSecretsMap(desiredKind), + secrets, + existing, + false, nil } } diff --git a/internal/operator/networking/kinds/networking/legacycf/config/external.go b/internal/operator/networking/kinds/networking/legacycf/config/external.go index fe21c2176..94cc2a38a 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/external.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/external.go @@ -2,13 +2,15 @@ package config import ( "errors" + "fmt" "strings" - core2 "github.com/caos/orbos/internal/operator/core" - "github.com/caos/orbos/internal/operator/networking/kinds/networking/core" - "github.com/caos/orbos/pkg/labels" + "github.com/caos/orbos/pkg/secret" + opcore "github.com/caos/orbos/internal/operator/core" + "github.com/caos/orbos/internal/operator/networking/kinds/networking/core" "github.com/caos/orbos/internal/operator/orbiter" + "github.com/caos/orbos/pkg/labels" ) type ExternalConfig struct { @@ -53,14 +55,41 @@ func (e *ExternalConfig) Internal(id, namespace string, apiLabels *labels.API) ( }, curr } -func (e *ExternalConfig) Validate() error { +var ErrNoLBID = errors.New("no loadbalancer identifier provided") + +func (e *ExternalConfig) Validate(lbID string) error { if e == nil { return errors.New("domain not found") } if e.Domain == "" { - return errors.New("No domain configured") + return errors.New("no domain configured") + } + if err := e.IP.Validate(); err != nil { + return err + } + + if e.LoadBalancer != nil && lbID == "" { + return ErrNoLBID + } + + return nil +} + +func (e *ExternalConfig) ValidateSecrets() error { + if e.Credentials == nil { + return errors.New("no credentials specified") + } + + if err := secret.ValidateSecret(e.Credentials.APIKey, e.Credentials.ExistingAPIKey); err != nil { + return fmt.Errorf("validating api key failed: %w", err) + } + if err := secret.ValidateSecret(e.Credentials.User, e.Credentials.ExistingUser); err != nil { + return fmt.Errorf("validating user failed: %w", err) + } + if err := secret.ValidateSecret(e.Credentials.UserServiceKey, e.Credentials.ExistingUserServiceKey); err != nil { + return fmt.Errorf("validating userservice key failed: %w", err) } - return e.IP.Validate() + return nil } func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { @@ -133,7 +162,7 @@ type current struct { apiSubdomain string `yaml:"-"` accountsSubdomain string `yaml:"-"` tlsCertName string `yaml:"-"` - ReadyCertificate core2.EnsureFunc + ReadyCertificate opcore.EnsureFunc } func (c *current) GetDomain() string { @@ -151,7 +180,7 @@ func (c *current) GetAPISubDomain() string { func (c *current) GetAccountsSubDomain() string { return c.accountsSubdomain } -func (c *current) GetReadyCertificate() core2.EnsureFunc { +func (c *current) GetReadyCertificate() opcore.EnsureFunc { return c.ReadyCertificate } func (c *current) GetTlsCertName() string { diff --git a/internal/operator/networking/kinds/networking/legacycf/config/internal.go b/internal/operator/networking/kinds/networking/legacycf/config/internal.go index 8ae8e9171..bc2f7c84b 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/internal.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/internal.go @@ -2,7 +2,7 @@ package config import ( "github.com/caos/orbos/pkg/labels" - secret2 "github.com/caos/orbos/pkg/secret" + "github.com/caos/orbos/pkg/secret" ) type InternalConfig struct { @@ -18,15 +18,18 @@ type InternalConfig struct { } type Credentials struct { - User *secret2.Secret - APIKey *secret2.Secret - UserServiceKey *secret2.Secret + User *secret.Secret `json:"user,omitempty" yaml:"user,omitempty"` + ExistingUser *secret.Existing `json:"existinguser,omitempty" yaml:"existinguser,omitempty"` + APIKey *secret.Secret `json:"apikey,omitempty" yaml:"apikey,omitempty"` + ExistingAPIKey *secret.Existing `json:"existingapikey,omitempty" yaml:"existingapikey,omitempty"` + UserServiceKey *secret.Secret `json:"userservicekey,omitempty" yaml:"userservicekey,omitempty"` + ExistingUserServiceKey *secret.Existing `json:"existinguserservicekey,omitempty" yaml:"existinguserservicekey,omitempty"` } func (c *Credentials) IsZero() bool { - if (c.User == nil || c.User.IsZero()) && - (c.APIKey == nil || c.APIKey.IsZero()) && - (c.UserServiceKey == nil || c.UserServiceKey.IsZero()) { + if ((c.User == nil || c.User.IsZero()) && (c.ExistingUser == nil || c.ExistingUser.IsZero())) && + ((c.APIKey == nil || c.APIKey.IsZero()) && (c.ExistingAPIKey == nil || c.ExistingAPIKey.IsZero())) && + ((c.UserServiceKey == nil || c.UserServiceKey.IsZero()) && (c.ExistingUserServiceKey == nil || c.ExistingUserServiceKey.IsZero())) { return true } return false @@ -54,8 +57,8 @@ type LoadBalancer struct { } type Origin struct { - Key *secret2.Secret - Certificate *secret2.Secret + Key *secret.Secret + Certificate *secret.Secret } type Subdomain struct { diff --git a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go index 2a3089247..2a5e307a0 100644 --- a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go +++ b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go @@ -1,10 +1,13 @@ package legacycf import ( + "time" + "github.com/caos/orbos/internal/operator/core" "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/app" "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/config" "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/helper" "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/labels" "github.com/pkg/errors" @@ -29,7 +32,20 @@ func adaptFunc( } } - apps, err := app.New(cfg.AccountName, cfg.Credentials.User.Value, cfg.Credentials.APIKey.Value, cfg.Credentials.UserServiceKey.Value, groups, cfg.Prefix) + user, err := helper.GetSecretValue(k8sClient, cfg.Credentials.User, cfg.Credentials.ExistingUser) + if err != nil { + return err + } + apiKey, err := helper.GetSecretValue(k8sClient, cfg.Credentials.APIKey, cfg.Credentials.ExistingAPIKey) + if err != nil { + return err + } + userServiceKey, err := helper.GetSecretValue(k8sClient, cfg.Credentials.UserServiceKey, cfg.Credentials.ExistingUserServiceKey) + if err != nil { + return err + } + + apps, err := app.New(cfg.AccountName, user, apiKey, userServiceKey, groups, cfg.Prefix) if err != nil { return err } @@ -59,7 +75,7 @@ func adaptFunc( }, func(k8sClient kubernetes.ClientInt) error { monitor.Info("waiting for certificate to be created") - if err := k8sClient.WaitForSecret(cfg.Namespace, cfg.OriginCASecretName, 60); err != nil { + if err := k8sClient.WaitForSecret(cfg.Namespace, cfg.OriginCASecretName, 60*time.Second); err != nil { return errors.Wrap(err, "error while waiting for certificate secret to be created") } monitor.Info("certificateis created") diff --git a/internal/operator/networking/kinds/networking/legacycf/secrets.go b/internal/operator/networking/kinds/networking/legacycf/secrets.go index e7435338f..ea9080bdd 100644 --- a/internal/operator/networking/kinds/networking/legacycf/secrets.go +++ b/internal/operator/networking/kinds/networking/legacycf/secrets.go @@ -5,8 +5,9 @@ import ( "github.com/caos/orbos/pkg/secret" ) -func getSecretsMap(desiredKind *Desired) map[string]*secret.Secret { +func getSecretsMap(desiredKind *Desired) (map[string]*secret.Secret, map[string]*secret.Existing) { secrets := map[string]*secret.Secret{} + existing := map[string]*secret.Existing{} if desiredKind.Spec == nil { desiredKind.Spec = &config.ExternalConfig{} } @@ -18,18 +19,33 @@ func getSecretsMap(desiredKind *Desired) map[string]*secret.Secret { if desiredKind.Spec.Credentials.User == nil { desiredKind.Spec.Credentials.User = &secret.Secret{} } + if desiredKind.Spec.Credentials.ExistingUser == nil { + desiredKind.Spec.Credentials.ExistingUser = &secret.Existing{} + } if desiredKind.Spec.Credentials.APIKey == nil { desiredKind.Spec.Credentials.APIKey = &secret.Secret{} } + if desiredKind.Spec.Credentials.ExistingAPIKey == nil { + desiredKind.Spec.Credentials.ExistingAPIKey = &secret.Existing{} + } if desiredKind.Spec.Credentials.UserServiceKey == nil { desiredKind.Spec.Credentials.UserServiceKey = &secret.Secret{} } + if desiredKind.Spec.Credentials.ExistingUserServiceKey == nil { + desiredKind.Spec.Credentials.ExistingUserServiceKey = &secret.Existing{} + } - secrets["credentials.user"] = desiredKind.Spec.Credentials.User - secrets["credentials.apikey"] = desiredKind.Spec.Credentials.APIKey - secrets["credentials.userservicekey"] = desiredKind.Spec.Credentials.UserServiceKey - - return secrets + userKey := "credentials.user" + secrets[userKey] = desiredKind.Spec.Credentials.User + existing[userKey] = desiredKind.Spec.Credentials.ExistingUser + apiKey := "credentials.apikey" + secrets[apiKey] = desiredKind.Spec.Credentials.APIKey + existing[apiKey] = desiredKind.Spec.Credentials.ExistingAPIKey + svcKey := "credentials.userservicekey" + secrets[svcKey] = desiredKind.Spec.Credentials.UserServiceKey + existing[svcKey] = desiredKind.Spec.Credentials.ExistingUserServiceKey + + return secrets, existing } diff --git a/internal/operator/networking/kinds/networking/networking.go b/internal/operator/networking/kinds/networking/networking.go index 4d40035eb..5a598f1d3 100644 --- a/internal/operator/networking/kinds/networking/networking.go +++ b/internal/operator/networking/kinds/networking/networking.go @@ -21,12 +21,14 @@ func GetQueryAndDestroyFuncs( query core.QueryFunc, destroy core.DestroyFunc, secrets map[string]*secret.Secret, + existing map[string]*secret.Existing, + migrate bool, err error, ) { switch desiredTree.Common.Kind { case "networking.caos.ch/LegacyCloudflare": return legacycf.AdaptFunc(namespace, ID, operatorLabels)(monitor, desiredTree, currentTree) default: - return nil, nil, nil, errors.Errorf("unknown networking kind %s", desiredTree.Common.Kind) + return nil, nil, nil, nil, false, errors.Errorf("unknown networking kind %s", desiredTree.Common.Kind) } } diff --git a/internal/operator/networking/kinds/orb/adapt.go b/internal/operator/networking/kinds/orb/adapt.go index 4d75b6a4c..893e248dc 100644 --- a/internal/operator/networking/kinds/orb/adapt.go +++ b/internal/operator/networking/kinds/orb/adapt.go @@ -15,10 +15,20 @@ func OperatorSelector() *labels.Selector { return labels.OpenOperatorSelector("ORBOS", "networking.caos.ch") } -func AdaptFunc(ID string, binaryVersion *string) core.AdaptFunc { +func AdaptFunc(ID string, binaryVersion *string, gitops bool) core.AdaptFunc { namespaceStr := "caos-zitadel" - return func(monitor mntr.Monitor, desiredTree *tree.Tree, currentTree *tree.Tree) (queryFunc core.QueryFunc, destroyFunc core.DestroyFunc, secrets map[string]*secret.Secret, err error) { + return func( + monitor mntr.Monitor, + desiredTree *tree.Tree, + currentTree *tree.Tree, + ) (queryFunc core.QueryFunc, + destroyFunc core.DestroyFunc, + secrets map[string]*secret.Secret, + existing map[string]*secret.Existing, + migrate bool, + err error, + ) { defer func() { err = errors.Wrapf(err, "building %s failed", desiredTree.Common.Kind) }() @@ -27,7 +37,7 @@ func AdaptFunc(ID string, binaryVersion *string) core.AdaptFunc { desiredKind, err := ParseDesiredV0(desiredTree) if err != nil { - return nil, nil, nil, errors.Wrap(err, "parsing desired state failed") + return nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed") } desiredTree.Parsed = desiredKind currentTree = &tree.Tree{} @@ -38,18 +48,14 @@ func AdaptFunc(ID string, binaryVersion *string) core.AdaptFunc { operatorLabels := mustDatabaseOperator(binaryVersion) networkingCurrent := &tree.Tree{} - queryNW, destroyNW, secrets, err := networking.GetQueryAndDestroyFuncs(orbMonitor, ID, operatorLabels, desiredKind.Networking, networkingCurrent, namespaceStr) + queryNW, destroyNW, secrets, existing, migrate, err := networking.GetQueryAndDestroyFuncs(orbMonitor, ID, operatorLabels, desiredKind.Networking, networkingCurrent, namespaceStr) if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, false, err } queriers := []core.QueryFunc{ queryNW, - } - if desiredKind.Spec.SelfReconciling { - queriers = append(queriers, - core.EnsureFuncToQueryFunc(Reconcile(monitor, desiredTree)), - ) + core.EnsureFuncToQueryFunc(Reconcile(monitor, desiredKind.Spec, gitops)), } destroyers := []core.DestroyFunc{ @@ -74,6 +80,8 @@ func AdaptFunc(ID string, binaryVersion *string) core.AdaptFunc { return core.DestroyersToDestroyFunc(monitor, destroyers)(k8sClient) }, secrets, + existing, + migrate, nil } } diff --git a/internal/operator/networking/kinds/orb/desired.go b/internal/operator/networking/kinds/orb/desired.go index 3d1f97609..0d13e83da 100644 --- a/internal/operator/networking/kinds/orb/desired.go +++ b/internal/operator/networking/kinds/orb/desired.go @@ -7,20 +7,23 @@ import ( ) type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec struct { - Verbose bool - NodeSelector map[string]string `yaml:"nodeSelector,omitempty"` - Tolerations []corev1.Toleration `yaml:"tolerations,omitempty"` - Version string `yaml:"version,omitempty"` - SelfReconciling bool `yaml:"selfReconciling"` - //Use this registry to pull the BOOM image from - //@default: ghcr.io - CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"` - } + Common *tree.Common `json:",inline" yaml:",inline"` + Spec *Spec `json:"spec" yaml:"spec"` Networking *tree.Tree } +// +kubebuilder:object:generate=true +type Spec struct { + Verbose bool `json:"verbose" yaml:"verbose"` + NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"` + Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"` + Version string `json:"version,omitempty" yaml:"version,omitempty"` + SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"` + //Use this registry to pull the Networking-operator image from + //@default: ghcr.io + CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"` +} + func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { desiredKind := &DesiredV0{Common: desiredTree.Common} diff --git a/internal/operator/networking/kinds/orb/reconcile.go b/internal/operator/networking/kinds/orb/reconcile.go index a5a971df6..87b46a157 100644 --- a/internal/operator/networking/kinds/orb/reconcile.go +++ b/internal/operator/networking/kinds/orb/reconcile.go @@ -9,37 +9,40 @@ import ( "github.com/pkg/errors" ) -func Reconcile(monitor mntr.Monitor, desiredTree *tree.Tree) core.EnsureFunc { +func Reconcile( + monitor mntr.Monitor, + spec *Spec, + gitops bool, +) core.EnsureFunc { return func(k8sClient kubernetes.ClientInt) (err error) { - defer func() { - err = errors.Wrapf(err, "building %s failed", desiredTree.Common.Kind) - }() + recMonitor := monitor.WithField("version", spec.Version) - desiredKind, err := ParseDesiredV0(desiredTree) - if err != nil { - return errors.Wrap(err, "parsing desired state failed") - } - desiredTree.Parsed = desiredKind - - recMonitor := monitor.WithField("version", desiredKind.Spec.Version) - - if desiredKind.Spec.Version == "" { + if spec.Version == "" { err := errors.New("No version set in networking.yml") monitor.Error(err) return err } - imageRegistry := desiredKind.Spec.CustomImageRegistry + imageRegistry := spec.CustomImageRegistry if imageRegistry == "" { imageRegistry = "ghcr.io" } - if err := kubernetes.EnsureNetworkingArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&desiredKind.Spec.Version)), k8sClient, desiredKind.Spec.Version, desiredKind.Spec.NodeSelector, desiredKind.Spec.Tolerations, imageRegistry); err != nil { - recMonitor.Error(errors.Wrap(err, "Failed to deploy networking-operator into k8s-cluster")) - return err - } - recMonitor.Info("Applied networking-operator") + if spec.SelfReconciling { + desiredTree := &tree.Tree{ + Common: &tree.Common{ + Kind: "networking.caos.ch/Orb", + Version: "v0", + }, + } + + if err := kubernetes.EnsureNetworkingArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, imageRegistry, gitops); err != nil { + recMonitor.Error(errors.Wrap(err, "Failed to deploy networking-operator into k8s-cluster")) + return err + } + recMonitor.Info("Applied networking-operator") + } return nil } diff --git a/internal/operator/networking/kinds/orb/zz_generated.deepcopy.go b/internal/operator/networking/kinds/orb/zz_generated.deepcopy.go new file mode 100644 index 000000000..bf8af31d1 --- /dev/null +++ b/internal/operator/networking/kinds/orb/zz_generated.deepcopy.go @@ -0,0 +1,54 @@ +// +build !ignore_autogenerated + +/* + + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package orb + +import ( + "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Spec) DeepCopyInto(out *Spec) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} diff --git a/internal/operator/networking/takeoff.go b/internal/operator/networking/takeoff.go index bf1337741..3eb5a827d 100644 --- a/internal/operator/networking/takeoff.go +++ b/internal/operator/networking/takeoff.go @@ -2,6 +2,7 @@ package networking import ( "errors" + "github.com/caos/orbos/internal/operator/core" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" @@ -25,7 +26,7 @@ func Takeoff(monitor mntr.Monitor, gitClient *git.Client, adapt core.AdaptFunc, return } - query, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) + query, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) if err != nil { internalMonitor.Error(err) return diff --git a/internal/operator/nodeagent/dep/conv/converter.go b/internal/operator/nodeagent/dep/conv/converter.go index 36e8575b2..6d401a1f2 100644 --- a/internal/operator/nodeagent/dep/conv/converter.go +++ b/internal/operator/nodeagent/dep/conv/converter.go @@ -89,9 +89,8 @@ func (d *dependencies) ToDependencies(sw common.Software) []*nodeagent.Dependenc }, } - for key, dependency := range dependencies { + for _, dependency := range dependencies { dependency.Installer = middleware.AddLogging(d.monitor, dependency.Installer) - dependencies[key] = dependency } return dependencies diff --git a/internal/operator/nodeagent/dep/cri/ensure.go b/internal/operator/nodeagent/dep/cri/ensure.go index c10721cca..453438a29 100644 --- a/internal/operator/nodeagent/dep/cri/ensure.go +++ b/internal/operator/nodeagent/dep/cri/ensure.go @@ -38,31 +38,7 @@ func (c *criDep) ensureCentOS(runtime string, version string) error { } } - // Obviously, docker doesn't care about the exact containerd version, so neighter should ORBITER - // https://docs.docker.com/engine/install/centos/ - // https://docs.docker.com/engine/install/ubuntu/ - if err := c.manager.Install(&dep.Software{ - Package: "containerd.io", - Version: containerdVersion, - }); err != nil { - c.monitor.Error(err) - } - - if err := c.manager.Install(&dep.Software{ - Package: runtime, - Version: version, - }); err != nil { - c.monitor.Error(errors.Wrap(err, "installing container runtime failed")) - } - - c.manager.Add(&dep.Repository{ - Repository: "https://download.docker.com/linux/centos/docker-ce.repo", - }) - - if err := c.systemd.Enable("docker"); err != nil { - return err - } - return c.systemd.Start("docker") + return c.run(runtime, version, "https://download.docker.com/linux/centos/docker-ce.repo", "", "") } func (c *criDep) ensureUbuntu(runtime string, version string) error { @@ -101,22 +77,53 @@ func (c *criDep) ensureUbuntu(runtime string, version string) error { return errors.Wrapf(err, "finding line containing desired container runtime version \"%s\" failed", version) } - if err := c.manager.Install(&dep.Software{Package: "containerd.io"}); err != nil { + return c.run( + runtime, + strings.TrimSpace(strings.Split(versionLine, "|")[1]), + fmt.Sprintf("deb [arch=amd64] https://download.docker.com/linux/ubuntu %s stable", c.os.Version), + "https://download.docker.com/linux/ubuntu/gpg", + "0EBFCD88", + ) +} + +func (c *criDep) run(runtime, version, repoURL, keyURL, keyFingerprint string) error { + + try := func() error { + // Obviously, docker doesn't care about the exact containerd version, so neighter should ORBITER + // https://docs.docker.com/engine/install/centos/ + // https://docs.docker.com/engine/install/ubuntu/ + if err := c.manager.Install(&dep.Software{ + Package: "containerd.io", + Version: containerdVersion, + }); err != nil { + return err + } + + err := c.manager.Install(&dep.Software{ + Package: runtime, + Version: version, + }) return err } - if err := c.manager.Install(&dep.Software{ - Package: runtime, - Version: strings.TrimSpace(strings.Split(versionLine, "|")[1]), - }); err != nil { - c.monitor.Error(errors.Wrap(err, "installing container runtime failed")) - } + if err := try(); err != nil { + swmonitor := c.monitor.WithField("software", "docker") + swmonitor.Error(fmt.Errorf("installing software from existing repo failed, trying again after adding repo: %w", err)) - c.manager.Add(&dep.Repository{ - Repository: fmt.Sprintf("deb [arch=amd64] https://download.docker.com/linux/ubuntu %s stable", c.os.Version), - KeyURL: "https://download.docker.com/linux/ubuntu/gpg", - KeyFingerprint: "0EBFCD88", - }) + if err := c.manager.Add(&dep.Repository{ + Repository: repoURL, + KeyURL: keyURL, + KeyFingerprint: keyFingerprint, + }); err != nil { + return err + } + swmonitor.WithField("url", repoURL).Info("repo added") + + if err := try(); err != nil { + swmonitor.Error(fmt.Errorf("installing software from %s failed: %w", repoURL, err)) + return err + } + } if err := c.systemd.Enable("docker"); err != nil { return err diff --git a/internal/operator/nodeagent/dep/k8s/common.go b/internal/operator/nodeagent/dep/k8s/common.go index 1df01051f..05c6dac64 100644 --- a/internal/operator/nodeagent/dep/k8s/common.go +++ b/internal/operator/nodeagent/dep/k8s/common.go @@ -1,6 +1,7 @@ package k8s import ( + "fmt" "io/ioutil" "regexp" "strings" @@ -34,24 +35,31 @@ func (c *Common) Current() (pkg common.Package, err error) { return pkg, nil } -func (c *Common) Ensure(remove common.Package, install common.Package) error { +func (c *Common) Ensure(remove common.Package, install common.Package) (err error) { + + defer func() { + if err != nil { + err = fmt.Errorf("installing %s failed: %w", c.pkg, err) + } + }() + pkgVersion := strings.TrimLeft(install.Version, "v") + "-0" if c.os == dep.Ubuntu { pkgVersion += "0" } - err := c.manager.Install(&dep.Software{Package: c.pkg, Version: pkgVersion}) + err = c.manager.Install(&dep.Software{Package: c.pkg, Version: pkgVersion}) if err == nil { return nil } switch c.os { case dep.Ubuntu: - c.manager.Add(&dep.Repository{ + return c.manager.Add(&dep.Repository{ KeyURL: "https://packages.cloud.google.com/apt/doc/apt-key.gpg", KeyFingerprint: "", Repository: "deb https://apt.kubernetes.io/ kubernetes-xenial main", }) case dep.CentOS: - err = ioutil.WriteFile("/etc/yum.repos.d/kubernetes.repo", []byte(`[kubernetes] + return ioutil.WriteFile("/etc/yum.repos.d/kubernetes.repo", []byte(`[kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 @@ -73,5 +81,5 @@ gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cl // } } - return errors.Wrapf(err, "installing %s failed", c.pkg) + return errors.New("unknown OS") } diff --git a/internal/operator/nodeagent/dep/nginx/dep.go b/internal/operator/nodeagent/dep/nginx/dep.go index 2bc050724..677343125 100644 --- a/internal/operator/nodeagent/dep/nginx/dep.go +++ b/internal/operator/nodeagent/dep/nginx/dep.go @@ -1,6 +1,7 @@ package nginx import ( + "fmt" "io/ioutil" "os" "regexp" @@ -88,22 +89,38 @@ func (s *nginxDep) Ensure(remove common.Package, ensure common.Package) error { return nil } + // TODO: I think this should be removed, as this prevents updating nginx if _, ok := remove.Config["nginx.conf"]; !ok { - if err := s.manager.Install(&dep.Software{ - Package: "nginx", - Version: strings.TrimLeft(ensure.Version, "v"), - }); err != nil { - if err := ioutil.WriteFile("/etc/yum.repos.d/nginx.repo", []byte(`[nginx-stable] + try := func() error { + return s.manager.Install(&dep.Software{ + Package: "nginx", + Version: strings.TrimLeft(ensure.Version, "v"), + }) + } + + if err := try(); err != nil { + + swmonitor := s.monitor.WithField("software", "NGINX") + swmonitor.Error(fmt.Errorf("installing software from existing repo failed, trying again after adding repo: %w", err)) + + repoURL := "http://nginx.org/packages/centos/$releasever/$basearch/" + if err := ioutil.WriteFile("/etc/yum.repos.d/nginx.repo", []byte(fmt.Sprintf(`[nginx-stable] name=nginx stable repo -baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ +baseurl=%s gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key -module_hotfixes=true`), 0600); err != nil { +module_hotfixes=true`, repoURL)), 0600); err != nil { + return err + } + + swmonitor.WithField("url", repoURL).Info("repo added") + + if err := try(); err != nil { + swmonitor.Error(fmt.Errorf("installing software from %s failed: %w", repoURL, err)) return err } - return errors.New("nginx not installed, repo added") } if err := os.MkdirAll("/etc/nginx", 0700); err != nil { diff --git a/internal/operator/nodeagent/dep/package-manager.go b/internal/operator/nodeagent/dep/package-manager.go index 775f7f3c6..7d2143809 100644 --- a/internal/operator/nodeagent/dep/package-manager.go +++ b/internal/operator/nodeagent/dep/package-manager.go @@ -99,17 +99,13 @@ func (p *PackageManager) Install(installVersion *Software, more ...*Software) er return errors.Errorf("Package manager %s is not implemented", p.os.Packages) } -func (p *PackageManager) Add(repo *Repository) { - var err error +func (p *PackageManager) Add(repo *Repository) error { switch p.os.Packages { case DebianBased: - err = p.debbasedAdd(repo) + return p.debbasedAdd(repo) case REMBased: - err = p.rembasedAdd(repo) + return p.rembasedAdd(repo) default: - err = errors.Errorf("Package manager %s is not implemented", p.os.Packages) - } - if err != nil { - p.monitor.Info(errors.Wrap(err, "Adding repo failed").Error()) + return errors.Errorf("Package manager %s is not implemented", p.os.Packages) } } diff --git a/internal/operator/nodeagent/firewall/centos/centOS.go b/internal/operator/nodeagent/firewall/centos/centOS.go index bc1dbd461..7cb19f426 100644 --- a/internal/operator/nodeagent/firewall/centos/centOS.go +++ b/internal/operator/nodeagent/firewall/centos/centOS.go @@ -11,7 +11,7 @@ import ( "github.com/caos/orbos/mntr" ) -func Ensurer(monitor mntr.Monitor, ignore []string) nodeagent.FirewallEnsurer { +func Ensurer(monitor mntr.Monitor, open []string) nodeagent.FirewallEnsurer { return nodeagent.FirewallEnsurerFunc(func(desired common.Firewall) (common.FirewallCurrent, func() error, error) { ensurers := make([]func() error, 0) current := make(common.FirewallCurrent, 0) @@ -21,7 +21,7 @@ func Ensurer(monitor mntr.Monitor, ignore []string) nodeagent.FirewallEnsurer { } for name, _ := range desired.Zones { - currentZone, ensureFunc, err := ensureZone(monitor, name, desired, ignore) + currentZone, ensureFunc, err := ensureZone(monitor, name, desired, open) if err != nil { return current, nil, err } @@ -51,7 +51,7 @@ func Ensurer(monitor mntr.Monitor, ignore []string) nodeagent.FirewallEnsurer { }) } -func ensureZone(monitor mntr.Monitor, zoneName string, desired common.Firewall, ignore []string) (*common.ZoneDesc, func() error, error) { +func ensureZone(monitor mntr.Monitor, zoneName string, desired common.Firewall, open []string) (*common.ZoneDesc, func() error, error) { current := &common.ZoneDesc{ Name: zoneName, Interfaces: []string{}, @@ -76,7 +76,7 @@ func ensureZone(monitor mntr.Monitor, zoneName string, desired common.Firewall, return current, nil, err } - addPorts, removePorts, err := getAddAndRemovePorts(monitor, zoneName, current, desired.Ports(zoneName), ignore) + addPorts, removePorts, err := getAddAndRemovePorts(monitor, zoneName, current, desired.Ports(zoneName), open) if err != nil { return current, nil, err } diff --git a/internal/operator/nodeagent/firewall/centos/ports.go b/internal/operator/nodeagent/firewall/centos/ports.go index a452059d6..b809b61a1 100644 --- a/internal/operator/nodeagent/firewall/centos/ports.go +++ b/internal/operator/nodeagent/firewall/centos/ports.go @@ -12,35 +12,61 @@ func getAddAndRemovePorts( zone string, current *common.ZoneDesc, desiredPorts []*common.Allowed, - ignore []string, + open []string, ) ( []string, []string, error, ) { + ensure := make([]string, 0) + remove := make([]string, 0) + alreadyOpen, err := getPorts(monitor, zone) if err != nil { return nil, nil, err } + alwaysOpen := ignoredPorts(open) - addPorts := make([]string, 0) - removePorts := make([]string, 0) + //ports that should stay open + for _, open := range alwaysOpen { + found := false + openStr := fmt.Sprintf("%s/%s", open.Port, open.Protocol) + if alreadyOpen != nil && len(alreadyOpen) > 0 { + for _, open := range alreadyOpen { + if open == openStr { + found = true + break + } + } + } + if !found { + ensure = append(ensure, fmt.Sprintf("--add-port=%s", openStr)) + } + } - ensureOpen := append(desiredPorts, ignoredPorts(ignore)...) -openloop: - for _, des := range ensureOpen { - desStr := fmt.Sprintf("%s/%s", des.Port, des.Protocol) - for _, already := range alreadyOpen { - if desStr == already { - continue openloop + //desired ports + for _, desired := range desiredPorts { + found := false + desStr := fmt.Sprintf("%s/%s", desired.Port, desired.Protocol) + if alreadyOpen != nil && len(alreadyOpen) > 0 { + for _, open := range alreadyOpen { + if open == desStr { + found = true + break + } } } - addPorts = append(addPorts, fmt.Sprintf("--add-port=%s", desStr)) + if !found { + ensure = append(ensure, fmt.Sprintf("--add-port=%s", desStr)) + } } -closeloop: - for _, already := range alreadyOpen { - fields := strings.Split(already, "/") + + //port that are not desired anymore + for _, open := range alreadyOpen { + found := false + + fields := strings.Split(open, "/") port := fields[0] protocol := fields[1] @@ -49,15 +75,32 @@ closeloop: Protocol: protocol, }) - for _, des := range ensureOpen { - if des.Port == port && des.Protocol == protocol { - continue closeloop + if desiredPorts != nil && len(desiredPorts) > 0 { + for _, desired := range desiredPorts { + if desired.Port == port && desired.Protocol == protocol { + found = true + break + } + } + } + + if !found { + if alwaysOpen != nil && len(alwaysOpen) > 0 { + for _, open := range alwaysOpen { + if open.Port == port && open.Protocol == protocol { + found = true + break + } + } } } - removePorts = append(removePorts, fmt.Sprintf("--remove-port=%s", already)) + + if !found { + remove = append(remove, fmt.Sprintf("--remove-interface=%s", open)) + } } - return addPorts, removePorts, nil + return ensure, remove, nil } func getPorts(monitor mntr.Monitor, zone string) ([]string, error) { diff --git a/internal/operator/nodeagent/firewall/firewall.go b/internal/operator/nodeagent/firewall/firewall.go index 120567fe3..f640abd39 100644 --- a/internal/operator/nodeagent/firewall/firewall.go +++ b/internal/operator/nodeagent/firewall/firewall.go @@ -7,10 +7,10 @@ import ( "github.com/caos/orbos/mntr" ) -func Ensurer(monitor mntr.Monitor, os dep.OperatingSystem, ignore []string) nodeagent.FirewallEnsurer { +func Ensurer(monitor mntr.Monitor, os dep.OperatingSystem, open []string) nodeagent.FirewallEnsurer { switch os { case dep.CentOS: - return centos.Ensurer(monitor, ignore) + return centos.Ensurer(monitor, open) default: return noopEnsurer() } diff --git a/internal/operator/nodeagent/iterator.go b/internal/operator/nodeagent/iterator.go index e107c5d0d..9b476b269 100644 --- a/internal/operator/nodeagent/iterator.go +++ b/internal/operator/nodeagent/iterator.go @@ -4,10 +4,8 @@ package nodeagent import ( "fmt" - "io/ioutil" - "runtime/debug" - "gopkg.in/yaml.v3" + "io/ioutil" "github.com/caos/orbos/internal/operator/common" "github.com/caos/orbos/mntr" @@ -106,12 +104,17 @@ func Iterator( panic(err) } + /*query := func() (func() error, error) { + return doQuery(*naDesired, curr) + } + + ensure, err := QueryFuncGoroutine(query)*/ ensure, err := doQuery(*naDesired, curr) if err != nil { monitor.Error(err) return - } + } readCurrent := func() common.NodeAgentsCurrentKind { if err := gitClient.Clone(); err != nil { panic(err) @@ -140,34 +143,30 @@ func Iterator( monitor.Error(gitClient.Push()) } - events = make([]*event, 0) if err := ensure(); err != nil { monitor.Error(err) return } - current = readCurrent() - - for _, event := range events { - current.Current.Set(id, event.current) - changed, err := gitClient.StageAndCommit(event.commit, git.File{ - Path: "caos-internal/orbiter/node-agents-current.yml", - Content: common.MarshalYAML(current), - }) - if err != nil { - monitor.Error(fmt.Errorf("commiting event \"%s\" failed: %s", event.commit, err.Error())) - return - } - if !changed { - monitor.Error(fmt.Errorf("event has no effect:", event.commit)) - return + if events != nil && len(events) > 0 { + current := readCurrent() + + for _, event := range events { + current.Current.Set(id, event.current) + changed, err := gitClient.StageAndCommit(event.commit, git.File{ + Path: "caos-internal/orbiter/node-agents-current.yml", + Content: common.MarshalYAML(current), + }) + if err != nil { + monitor.Error(fmt.Errorf("commiting event \"%s\" failed: %s", event.commit, err.Error())) + return + } + if !changed { + monitor.Error(fmt.Errorf("event has no effect:", event.commit)) + return + } } - } - - if len(events) > 0 { monitor.Error(gitClient.Push()) } - - debug.FreeOSMemory() } } diff --git a/internal/operator/nodeagent/networking/centos/centOS.go b/internal/operator/nodeagent/networking/centos/centOS.go index d20f7c903..d0c3b7929 100644 --- a/internal/operator/nodeagent/networking/centos/centOS.go +++ b/internal/operator/nodeagent/networking/centos/centOS.go @@ -299,6 +299,7 @@ func getNetworkScriptPath(interfaceName string) string { func getNetworkFiles(name string, ty string, ips []string) map[string]string { tmpBuf := new(bytes.Buffer) + defer tmpBuf.Reset() tmpl := template.Must(template.New("").Parse(`NAME={{ .Name }} DEVICE={{ .Name }} ONBOOT=yes diff --git a/internal/operator/orbiter/adapt.go b/internal/operator/orbiter/adapt.go index d65a0af38..e19f34377 100644 --- a/internal/operator/orbiter/adapt.go +++ b/internal/operator/orbiter/adapt.go @@ -6,23 +6,16 @@ import ( "github.com/caos/orbos/pkg/tree" ) -type AdaptFunc func(monitor mntr.Monitor, finishedChan chan struct{}, desired *tree.Tree, current *tree.Tree) (QueryFunc, DestroyFunc, ConfigureFunc, bool, map[string]*secret.Secret, error) - -type retAdapt struct { - query QueryFunc - destroy DestroyFunc - configure ConfigureFunc - migrate bool - secrets map[string]*secret.Secret - err error -} - -func AdaptFuncGoroutine(adapt func() (QueryFunc, DestroyFunc, ConfigureFunc, bool, map[string]*secret.Secret, error)) (QueryFunc, DestroyFunc, ConfigureFunc, bool, map[string]*secret.Secret, error) { - retChan := make(chan retAdapt) - go func() { - query, destroy, configure, migrate, secret, err := adapt() - retChan <- retAdapt{query, destroy, configure, migrate, secret, err} - }() - ret := <-retChan - return ret.query, ret.destroy, ret.configure, ret.migrate, ret.secrets, ret.err -} +type AdaptFunc func( + monitor mntr.Monitor, + finishedChan chan struct{}, + desired *tree.Tree, + current *tree.Tree, +) ( + QueryFunc, + DestroyFunc, + ConfigureFunc, + bool, + map[string]*secret.Secret, + error, +) diff --git a/internal/operator/orbiter/config.go b/internal/operator/orbiter/config.go index 160a66097..629199b26 100644 --- a/internal/operator/orbiter/config.go +++ b/internal/operator/orbiter/config.go @@ -2,8 +2,8 @@ package orbiter import ( "github.com/caos/orbos/internal/ingestion" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/pkg/git" + orbcfg "github.com/caos/orbos/pkg/orb" ) type Config struct { @@ -12,5 +12,5 @@ type Config struct { Adapt AdaptFunc FinishedChan chan struct{} PushEvents func(events []*ingestion.EventRequest) error - OrbConfig orb.Orb + OrbConfig orbcfg.Orb } diff --git a/internal/operator/orbiter/destroy.go b/internal/operator/orbiter/destroy.go index 1e8d5b782..05ecfd377 100644 --- a/internal/operator/orbiter/destroy.go +++ b/internal/operator/orbiter/destroy.go @@ -5,7 +5,6 @@ import ( "github.com/caos/orbos/internal/operator/common" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" ) @@ -15,14 +14,6 @@ func NoopDestroy(map[string]interface{}) error { return nil } -func DestroyFuncGoroutine(query func() error) error { - retChan := make(chan error) - go func() { - retChan <- query() - }() - return <-retChan -} - func Destroy(monitor mntr.Monitor, gitClient *git.Client, adapt AdaptFunc, finishedChan chan struct{}) error { treeDesired, err := api.ReadOrbiterYml(gitClient) if err != nil { @@ -31,11 +22,7 @@ func Destroy(monitor mntr.Monitor, gitClient *git.Client, adapt AdaptFunc, finis treeCurrent := &tree.Tree{} - adaptFunc := func() (QueryFunc, DestroyFunc, ConfigureFunc, bool, map[string]*secret.Secret, error) { - return adapt(monitor, finishedChan, treeDesired, treeCurrent) - } - - _, destroy, _, _, _, err := AdaptFuncGoroutine(adaptFunc) + _, destroy, _, _, _, err := adapt(monitor, finishedChan, treeDesired, treeCurrent) if err != nil { return err } diff --git a/internal/operator/orbiter/kinds/clusters/clusters.go b/internal/operator/orbiter/kinds/clusters/clusters.go index 6ca93ed73..ba7d1daac 100644 --- a/internal/operator/orbiter/kinds/clusters/clusters.go +++ b/internal/operator/orbiter/kinds/clusters/clusters.go @@ -17,6 +17,7 @@ func GetQueryAndDestroyFuncs( clusterID string, clusterTree *tree.Tree, oneoff bool, + pprof bool, deployOrbiter bool, clusterCurrent *tree.Tree, destroyProviders func(map[string]interface{}) (map[string]interface{}, error), @@ -34,30 +35,29 @@ func GetQueryAndDestroyFuncs( switch clusterTree.Common.Kind { case "orbiter.caos.ch/KubernetesCluster": - adaptFunc := func() (orbiter.QueryFunc, orbiter.DestroyFunc, orbiter.ConfigureFunc, bool, map[string]*secret.Secret, error) { - return kubernetes.AdaptFunc( - labels.MustForAPI(operator, "KubernetesCluster", clusterTree.Common.Version), - clusterID, - oneoff, - deployOrbiter, - destroyProviders, - func(whitelist []*orbiter.CIDR) { - go func() { - monitor.Debug("Sending whitelist") - whitelistChan <- whitelist - close(whitelistChan) - }() - monitor.Debug("Whitelist sent") - }, - gitClient, - )( - monitor.WithFields(map[string]interface{}{"cluster": clusterID}), - finishedChan, - clusterTree, - clusterCurrent, - ) - } - return orbiter.AdaptFuncGoroutine(adaptFunc) + return kubernetes.AdaptFunc( + labels.MustForAPI(operator, "KubernetesCluster", clusterTree.Common.Version), + clusterID, + oneoff, + deployOrbiter, + pprof, + destroyProviders, + func(whitelist []*orbiter.CIDR) { + go func() { + monitor.Debug("Sending whitelist") + whitelistChan <- whitelist + close(whitelistChan) + }() + monitor.Debug("Whitelist sent") + }, + gitClient, + )( + monitor.WithFields(map[string]interface{}{"cluster": clusterID}), + finishedChan, + clusterTree, + clusterCurrent, + ) + // subassemblers[provIdx] = static.New(providerPath, generalOverwriteSpec, staticadapter.New(providermonitor, providerID, "/healthz", updatesDisabled, cfg.NodeAgent)) default: return nil, nil, nil, false, nil, errors.Errorf("unknown cluster kind %s", clusterTree.Common.Kind) diff --git a/internal/operator/orbiter/kinds/clusters/kubernetes/adapt.go b/internal/operator/orbiter/kinds/clusters/kubernetes/adapt.go index a06f40c4b..323940c26 100644 --- a/internal/operator/orbiter/kinds/clusters/kubernetes/adapt.go +++ b/internal/operator/orbiter/kinds/clusters/kubernetes/adapt.go @@ -23,6 +23,7 @@ func AdaptFunc( clusterID string, oneoff bool, deployOrbiter bool, + pprof bool, destroyProviders func(map[string]interface{}) (map[string]interface{}, error), whitelist func(whitelist []*orbiter.CIDR), gitClient *git.Client, @@ -89,7 +90,7 @@ func AdaptFunc( k8sClient := kubernetes.NewK8sClient(monitor, kc) if k8sClient.Available() && deployOrbiter { - if err := kubernetes.EnsureCommonArtifacts(monitor, k8sClient); err != nil { + if err := kubernetes.EnsureCaosSystemNamespace(monitor, k8sClient); err != nil { deployErrors++ monitor.WithFields(map[string]interface{}{ "count": deployErrors, @@ -109,6 +110,7 @@ func AdaptFunc( monitor, apiLabels, k8sClient, + pprof, desiredKind.Spec.Versions.Orbiter, imageRegistry, ); err != nil { @@ -158,7 +160,7 @@ func AdaptFunc( err = errors.Wrapf(err, "destroying %s failed", desiredKind.Common.Kind) }() - if k8sClient.Available() { + if k8sClient != nil && k8sClient.Available() { volumes, err := k8sClient.ListPersistentVolumes() if err != nil { return err @@ -178,11 +180,7 @@ func AdaptFunc( desiredKind.Spec.Kubeconfig = nil - destroyFunc := func() error { - return destroy(providers, k8sClient) - } - - return orbiter.DestroyFuncGoroutine(destroyFunc) + return destroy(providers, k8sClient) }, orbiter.NoopConfigure, migrate, diff --git a/internal/operator/orbiter/kinds/clusters/kubernetes/destroy.go b/internal/operator/orbiter/kinds/clusters/kubernetes/destroy.go index fb489d819..91811433c 100644 --- a/internal/operator/orbiter/kinds/clusters/kubernetes/destroy.go +++ b/internal/operator/orbiter/kinds/clusters/kubernetes/destroy.go @@ -7,7 +7,7 @@ import ( func destroy(providerCurrents map[string]interface{}, k8sClient *kubernetes.Client) error { - if k8sClient.Available() { + if k8sClient != nil && k8sClient.Available() { k8sClient.DeleteDeployment("caos-system", "orbiter") } diff --git a/internal/operator/orbiter/kinds/clusters/kubernetes/join.go b/internal/operator/orbiter/kinds/clusters/kubernetes/join.go index b148ae501..0d2f7a162 100644 --- a/internal/operator/orbiter/kinds/clusters/kubernetes/join.go +++ b/internal/operator/orbiter/kinds/clusters/kubernetes/join.go @@ -300,6 +300,7 @@ kubectl -n kube-system patch deployment coredns --type='json' \ }).Debug("Executed kubeadm init") kubeconfigBuf := new(bytes.Buffer) + defer kubeconfigBuf.Reset() if err := joining.infra.ReadFile("${HOME}/.kube/config", kubeconfigBuf); err != nil { return nil, err } diff --git a/internal/operator/orbiter/kinds/loadbalancers/dynamic/adapt.go b/internal/operator/orbiter/kinds/loadbalancers/dynamic/adapt.go index 54df42c2c..78956feff 100644 --- a/internal/operator/orbiter/kinds/loadbalancers/dynamic/adapt.go +++ b/internal/operator/orbiter/kinds/loadbalancers/dynamic/adapt.go @@ -222,7 +222,14 @@ func AdaptFunc(whitelist WhiteListFunc) orbiter.AdaptFunc { }).Debug("Executed command") return user, nil }, - "vip": mapVIP, + "vip": mapVIP, + "routerID": func(vip *VIP) string { + vipParts := strings.Split(mapVIP(vip), ".") + if len(vipParts) != 4 || vipParts[3] == "0" { + return "55" + } + return vipParts[3] + }, "derefBool": func(in *bool) bool { return in != nil && *in }, }) @@ -310,7 +317,7 @@ vrrp_instance VI_{{ $idx }} { {{ range $peer := $root.Peers }}{{ $peer.IP }} {{ end }} } interface {{ $root.Interface }} - virtual_router_id {{ add 55 $idx }} + virtual_router_id {{ routerID $vip }} advert_int 1 authentication { auth_type PASS diff --git a/internal/operator/orbiter/kinds/loadbalancers/loadbalancers.go b/internal/operator/orbiter/kinds/loadbalancers/loadbalancers.go index f9bbfc89b..57426c5c3 100644 --- a/internal/operator/orbiter/kinds/loadbalancers/loadbalancers.go +++ b/internal/operator/orbiter/kinds/loadbalancers/loadbalancers.go @@ -28,10 +28,7 @@ func GetQueryAndDestroyFunc( // case "orbiter.caos.ch/ExternalLoadBalancer": // return []orbiter.Assembler{external.New(depPath, generalOverwriteSpec, externallbadapter.New())}, nil case "orbiter.caos.ch/DynamicLoadBalancer": - adaptFunc := func() (orbiter.QueryFunc, orbiter.DestroyFunc, orbiter.ConfigureFunc, bool, map[string]*secret.Secret, error) { - return dynamic.AdaptFunc(whitelist)(monitor, finishedChan, loadBalancingTree, loadBalacingCurrent) - } - return orbiter.AdaptFuncGoroutine(adaptFunc) + return dynamic.AdaptFunc(whitelist)(monitor, finishedChan, loadBalancingTree, loadBalacingCurrent) default: return nil, nil, nil, false, nil, errors.Errorf("unknown loadbalancing kind %s", loadBalancingTree.Common.Kind) } diff --git a/internal/operator/orbiter/kinds/orb/adapt.go b/internal/operator/orbiter/kinds/orb/adapt.go index 5a3a66995..2a6467324 100644 --- a/internal/operator/orbiter/kinds/orb/adapt.go +++ b/internal/operator/orbiter/kinds/orb/adapt.go @@ -4,9 +4,9 @@ import ( "github.com/caos/orbos/internal/api" "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters" "github.com/caos/orbos/internal/operator/orbiter/kinds/providers" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/labels" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" "github.com/pkg/errors" @@ -22,7 +22,7 @@ func OperatorSelector() *labels.Selector { func AdaptFunc( operatorLabels *labels.Operator, - orbConfig *orb.Orb, + orbConfig *orbcfg.Orb, orbiterCommit string, oneoff bool, deployOrbiter bool, @@ -88,6 +88,7 @@ func AdaptFunc( orbConfig.URL, orbConfig.Repokey, oneoff, + desiredKind.Spec.PProf, ) if err != nil { return nil, nil, nil, migrate, nil, err @@ -100,7 +101,7 @@ func AdaptFunc( providerQueriers = append(providerQueriers, query) providerDestroyers = append(providerDestroyers, destroy) providerConfigurers = append(providerConfigurers, configure) - secret.AppendSecrets(provID, secrets, providerSecrets) + secret.AppendSecrets(provID, secrets, providerSecrets, nil, nil) } var provCurr map[string]interface{} @@ -136,6 +137,7 @@ func AdaptFunc( clusterID, clusterTree, oneoff, + desiredKind.Spec.PProf, deployOrbiter, clusterCurrent, destroyProviders, @@ -149,7 +151,7 @@ func AdaptFunc( clusterQueriers = append(clusterQueriers, query) clusterDestroyers = append(clusterDestroyers, destroy) clusterConfigurers = append(clusterConfigurers, configure) - secret.AppendSecrets(clusterID, secrets, clusterSecrets) + secret.AppendSecrets(clusterID, secrets, clusterSecrets, nil, nil) if migrateLocal { migrate = true } @@ -169,10 +171,7 @@ func AdaptFunc( providerEnsurers := make([]orbiter.EnsureFunc, 0) queriedProviders := make(map[string]interface{}) for _, querier := range providerQueriers { - queryFunc := func() (orbiter.EnsureFunc, error) { - return querier(nodeAgentsCurrent, nodeAgentsDesired, nil) - } - ensurer, err := orbiter.QueryFuncGoroutine(queryFunc) + ensurer, err := querier(nodeAgentsCurrent, nodeAgentsDesired, nil) if err != nil { return nil, err @@ -186,10 +185,7 @@ func AdaptFunc( clusterEnsurers := make([]orbiter.EnsureFunc, 0) for _, querier := range clusterQueriers { - queryFunc := func() (orbiter.EnsureFunc, error) { - return querier(nodeAgentsCurrent, nodeAgentsDesired, queriedProviders) - } - ensurer, err := orbiter.QueryFuncGoroutine(queryFunc) + ensurer, err := querier(nodeAgentsCurrent, nodeAgentsDesired, queriedProviders) if err != nil { return nil, err @@ -204,11 +200,7 @@ func AdaptFunc( done := true for _, ensurer := range append(providerEnsurers, clusterEnsurers...) { - ensureFunc := func() *orbiter.EnsureResult { - return ensurer(psf) - } - - result := orbiter.EnsureFuncGoroutine(ensureFunc) + result := ensurer(psf) if result.Err != nil { return result } @@ -230,7 +222,7 @@ func AdaptFunc( } } return nil - }, func(orb orb.Orb) error { + }, func(orb orbcfg.Orb) error { defer func() { err = errors.Wrapf(err, "ensuring %s failed", desiredKind.Common.Kind) }() diff --git a/internal/operator/orbiter/kinds/orb/desired.go b/internal/operator/orbiter/kinds/orb/desired.go index 001e413ea..e1e54e509 100644 --- a/internal/operator/orbiter/kinds/orb/desired.go +++ b/internal/operator/orbiter/kinds/orb/desired.go @@ -9,6 +9,7 @@ type DesiredV0 struct { Common *tree.Common `yaml:",inline"` Spec struct { Verbose bool + PProf bool } Clusters map[string]*tree.Tree Providers map[string]*tree.Tree diff --git a/internal/operator/orbiter/kinds/orb/machines.go b/internal/operator/orbiter/kinds/orb/machines.go index cf2fea98c..0d9194064 100644 --- a/internal/operator/orbiter/kinds/orb/machines.go +++ b/internal/operator/orbiter/kinds/orb/machines.go @@ -36,6 +36,7 @@ func ListMachines(operarorLabels *labels.Operator) MachinesFunc { clusterTree, true, false, + false, clusterCurrent, nil, nil, diff --git a/internal/operator/orbiter/kinds/providers/core/nodeagent.go b/internal/operator/orbiter/kinds/providers/core/nodeagent.go index a24734b05..c4ab9a42a 100644 --- a/internal/operator/orbiter/kinds/providers/core/nodeagent.go +++ b/internal/operator/orbiter/kinds/providers/core/nodeagent.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/caos/orbos/internal/orb" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/internal/helpers" @@ -21,8 +21,8 @@ import ( type IterateNodeAgentFuncs func(currentNodeAgents *common.CurrentNodeAgents) (queryNodeAgent func(machine infra.Machine, orbiterCommit string) (bool, error), install func(machine infra.Machine) error) -func ConfigureNodeAgents(svc MachinesService, monitor mntr.Monitor, orb orb.Orb) error { - configure, _ := NodeAgentFuncs(monitor, orb.URL, orb.Repokey) +func ConfigureNodeAgents(svc MachinesService, monitor mntr.Monitor, orb orbcfg.Orb, pprof bool) error { + configure, _ := NodeAgentFuncs(monitor, orb.URL, orb.Repokey, pprof) return Each(svc, func(pool string, machine infra.Machine) error { err := configure(machine) if err != nil { @@ -39,7 +39,12 @@ func ConfigureNodeAgents(svc MachinesService, monitor mntr.Monitor, orb orb.Orb) func NodeAgentFuncs( monitor mntr.Monitor, repoURL string, - repoKey string) (reconfigure func(machines infra.Machine) error, iterate IterateNodeAgentFuncs) { + repoKey string, + pprof bool, +) ( + reconfigure func(machines infra.Machine) error, + iterate IterateNodeAgentFuncs, +) { configure := func(machine infra.Machine) func() error { machineMonitor := monitor.WithField("machine", machine.ID()) @@ -151,6 +156,10 @@ func NodeAgentFuncs( configure(machine), func() error { if err := infra.Try(machineMonitor, time.NewTimer(8*time.Second), 2*time.Second, machine, func(cmp infra.Machine) error { + pprofStr := "" + if pprof { + pprofStr = "--pprof" + } return errors.Wrapf(cmp.WriteFile(systemdPath, strings.NewReader(fmt.Sprintf(`[Unit] Description=Node Agent After=network.target @@ -158,7 +167,7 @@ After=network.target [Service] Type=simple User=root -ExecStart=%s --id "%s" +ExecStart=%s --id "%s" %s Restart=always MemoryLimit=250M MemoryAccounting=yes @@ -168,7 +177,7 @@ MemoryAccounting=yes [Install] WantedBy=multi-user.target -`, binary, machine.ID())), 600), "creating remote file %s failed", systemdPath) +`, binary, machine.ID(), pprofStr)), 600), "creating remote file %s failed", systemdPath) }); err != nil { return errors.Wrap(err, "remotely configuring Node Agent systemd unit failed") } diff --git a/internal/operator/orbiter/kinds/providers/cs/adapt.go b/internal/operator/orbiter/kinds/providers/cs/adapt.go index d3bce949e..aa4b82d7f 100644 --- a/internal/operator/orbiter/kinds/providers/cs/adapt.go +++ b/internal/operator/orbiter/kinds/providers/cs/adapt.go @@ -6,8 +6,8 @@ import ( "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers" "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic" "github.com/caos/orbos/internal/operator/orbiter/kinds/providers/core" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/internal/ssh" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/pkg/errors" "github.com/caos/orbos/mntr" @@ -15,7 +15,16 @@ import ( "github.com/caos/orbos/pkg/tree" ) -func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoURL, repoKey string, oneoff bool) orbiter.AdaptFunc { +func AdaptFunc( + providerID, + orbID string, + whitelist dynamic.WhiteListFunc, + orbiterCommit, + repoURL, + repoKey string, + oneoff bool, + pprof bool, +) orbiter.AdaptFunc { return func(monitor mntr.Monitor, finishedChan chan struct{}, desiredTree *tree.Tree, currentTree *tree.Tree) (queryFunc orbiter.QueryFunc, destroyFunc orbiter.DestroyFunc, configureFunc orbiter.ConfigureFunc, migrate bool, secrets map[string]*secret.Secret, err error) { defer func() { err = errors.Wrapf(err, "building %s failed", desiredTree.Common.Kind) @@ -26,7 +35,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite } desiredTree.Parsed = desiredKind secrets = make(map[string]*secret.Secret, 0) - secret.AppendSecrets("", secrets, getSecretsMap(desiredKind)) + secret.AppendSecrets("", secrets, getSecretsMap(desiredKind), nil, nil) if desiredKind.Spec.RebootRequired == nil { desiredKind.Spec.RebootRequired = make([]string, 0) @@ -51,7 +60,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite if migrateLocal { migrate = true } - secret.AppendSecrets("", secrets, lbSecrets) + secret.AppendSecrets("", secrets, lbSecrets, nil, nil) ctx, err := buildContext(monitor, &desiredKind.Spec, orbID, providerID, oneoff) if err != nil { @@ -83,7 +92,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite return nil, err } - _, naFuncs := core.NodeAgentFuncs(monitor, repoURL, repoKey) + _, naFuncs := core.NodeAgentFuncs(monitor, repoURL, repoKey, pprof) return query(&desiredKind.Spec, current, lbCurrent.Parsed, ctx, nodeAgentsCurrent, nodeAgentsDesired, naFuncs, orbiterCommit) }, func(delegates map[string]interface{}) error { @@ -96,7 +105,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite } return destroy(ctx, current) - }, func(orb orb.Orb) error { + }, func(orb orbcfg.Orb) error { if err := desiredKind.validateAPIToken(); err != nil { return err @@ -123,7 +132,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite panic(err) } - return core.ConfigureNodeAgents(ctx.machinesService, ctx.monitor, orb) + return core.ConfigureNodeAgents(ctx.machinesService, ctx.monitor, orb, pprof) }, migrate, secrets, nil } } diff --git a/internal/operator/orbiter/kinds/providers/cs/machinesservice.go b/internal/operator/orbiter/kinds/providers/cs/machinesservice.go index 56a04c900..a0f045e78 100644 --- a/internal/operator/orbiter/kinds/providers/cs/machinesservice.go +++ b/internal/operator/orbiter/kinds/providers/cs/machinesservice.go @@ -254,7 +254,15 @@ func (m *machinesService) machines() (map[string][]*machine, error) { return nil, err } - m.cache.instances = make(map[string][]*machine) + if m.cache.instances == nil { + m.cache.instances = make(map[string][]*machine) + } else { + for k := range m.cache.instances { + m.cache.instances[k] = nil + delete(m.cache.instances, k) + } + } + for idx := range servers { server := servers[idx] pool := server.Tags["pool"] diff --git a/internal/operator/orbiter/kinds/providers/gce/adapt.go b/internal/operator/orbiter/kinds/providers/gce/adapt.go index e3e8af2ec..42f0fee8f 100644 --- a/internal/operator/orbiter/kinds/providers/gce/adapt.go +++ b/internal/operator/orbiter/kinds/providers/gce/adapt.go @@ -4,8 +4,8 @@ import ( "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers" "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic" "github.com/caos/orbos/internal/operator/orbiter/kinds/providers/core" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/internal/ssh" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" "github.com/pkg/errors" @@ -15,8 +15,29 @@ import ( "github.com/caos/orbos/mntr" ) -func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoURL, repoKey string, oneoff bool) orbiter.AdaptFunc { - return func(monitor mntr.Monitor, finishedChan chan struct{}, desiredTree *tree.Tree, currentTree *tree.Tree) (queryFunc orbiter.QueryFunc, destroyFunc orbiter.DestroyFunc, configureFunc orbiter.ConfigureFunc, migrate bool, secrets map[string]*secret.Secret, err error) { +func AdaptFunc( + providerID, + orbID string, + whitelist dynamic.WhiteListFunc, + orbiterCommit, + repoURL, + repoKey string, + oneoff bool, + pprof bool, +) orbiter.AdaptFunc { + return func( + monitor mntr.Monitor, + finishedChan chan struct{}, + desiredTree *tree.Tree, + currentTree *tree.Tree, + ) ( + queryFunc orbiter.QueryFunc, + destroyFunc orbiter.DestroyFunc, + configureFunc orbiter.ConfigureFunc, + migrate bool, + secrets map[string]*secret.Secret, + err error, + ) { defer func() { err = errors.Wrapf(err, "building %s failed", desiredTree.Common.Kind) }() @@ -26,7 +47,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite } desiredTree.Parsed = desiredKind secrets = make(map[string]*secret.Secret, 0) - secret.AppendSecrets("", secrets, getSecretsMap(desiredKind)) + secret.AppendSecrets("", secrets, getSecretsMap(desiredKind), nil, nil) if desiredKind.Spec.RebootRequired == nil { desiredKind.Spec.RebootRequired = make([]string, 0) @@ -58,7 +79,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite if migrateLocal { migrate = true } - secret.AppendSecrets("", secrets, lbSecrets) + secret.AppendSecrets("", secrets, lbSecrets, nil, nil) svcFunc := func() (*machinesService, error) { return service(monitor, &desiredKind.Spec, orbID, providerID, oneoff) @@ -94,7 +115,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite return nil, err } - _, naFuncs := core.NodeAgentFuncs(monitor, repoURL, repoKey) + _, naFuncs := core.NodeAgentFuncs(monitor, repoURL, repoKey, pprof) return query(&desiredKind.Spec, current, lbCurrent.Parsed, svc, nodeAgentsCurrent, nodeAgentsDesired, naFuncs, orbiterCommit) }, func(delegates map[string]interface{}) error { @@ -107,7 +128,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite return err } return destroy(ctx, delegates) - }, func(orb orb.Orb) error { + }, func(orb orbcfg.Orb) error { if err := desiredKind.validateJSONKey(); err != nil { // TODO: Create service account and write its json key to desiredKind.Spec.JSONKey and push repo @@ -140,7 +161,7 @@ func AdaptFunc(providerID, orbID string, whitelist dynamic.WhiteListFunc, orbite panic(err) } - return core.ConfigureNodeAgents(svc, svc.context.monitor, orb) + return core.ConfigureNodeAgents(svc, svc.context.monitor, orb, pprof) }, migrate, secrets, diff --git a/internal/operator/orbiter/kinds/providers/gce/computesservice.go b/internal/operator/orbiter/kinds/providers/gce/computesservice.go index b0169ad34..9f2bd3d41 100644 --- a/internal/operator/orbiter/kinds/providers/gce/computesservice.go +++ b/internal/operator/orbiter/kinds/providers/gce/computesservice.go @@ -45,7 +45,7 @@ func (m *machinesService) use(key *SSHKey) error { } func (m *machinesService) restartPreemptibleMachines() error { - pools, err := m.instances() + pools, err := getAllInstances(m) if err != nil { return err } @@ -230,21 +230,21 @@ func (m *machinesService) Create(poolName string) (infra.Machine, error) { } func (m *machinesService) ListPools() ([]string, error) { - - pools, err := m.instances() + pools, err := getAllInstances(m) if err != nil { return nil, err } var poolNames []string for poolName := range pools { - poolNames = append(poolNames, poolName) + copyPoolName := poolName + poolNames = append(poolNames, copyPoolName) } return poolNames, nil } func (m *machinesService) List(poolName string) (infra.Machines, error) { - pools, err := m.instances() + pools, err := getAllInstances(m) if err != nil { return nil, err } @@ -252,15 +252,18 @@ func (m *machinesService) List(poolName string) (infra.Machines, error) { pool := pools[poolName] machines := make([]infra.Machine, len(pool)) for idx, machine := range pool { - machines[idx] = machine + copyInstance := *machine + machines[idx] = ©Instance } return machines, nil } -func (m *machinesService) instances() (map[string][]*instance, error) { +func getAllInstances(m *machinesService) (map[string][]*instance, error) { if m.cache.instances != nil { return m.cache.instances, nil + } else { + m.cache.instances = make(map[string][]*instance) } instances, err := m.context.client.Instances. @@ -272,8 +275,8 @@ func (m *machinesService) instances() (map[string][]*instance, error) { return nil, err } - m.cache.instances = make(map[string][]*instance) for _, inst := range instances.Items { + if inst.Labels["orb"] != m.context.orbID || inst.Labels["provider"] != m.context.providerID { continue } @@ -298,7 +301,9 @@ func (m *machinesService) instances() (map[string][]*instance, error) { rebootRequired = true unrequireReboot = func(pos int) func() { return func() { - m.context.desired.RebootRequired = append(m.context.desired.RebootRequired[0:pos], m.context.desired.RebootRequired[pos+1:]...) + copy(m.context.desired.RebootRequired[pos:], m.context.desired.RebootRequired[pos+1:]) + m.context.desired.RebootRequired[len(m.context.desired.RebootRequired)-1] = "" + m.context.desired.RebootRequired = m.context.desired.RebootRequired[:len(m.context.desired.RebootRequired)-1] } }(idx) break @@ -312,7 +317,9 @@ func (m *machinesService) instances() (map[string][]*instance, error) { replacementRequired = true unrequireReplacement = func(pos int) func() { return func() { - m.context.desired.ReplacementRequired = append(m.context.desired.ReplacementRequired[0:pos], m.context.desired.ReplacementRequired[pos+1:]...) + copy(m.context.desired.ReplacementRequired[pos:], m.context.desired.ReplacementRequired[pos+1:]) + m.context.desired.ReplacementRequired[len(m.context.desired.ReplacementRequired)-1] = "" + m.context.desired.ReplacementRequired = m.context.desired.ReplacementRequired[:len(m.context.desired.ReplacementRequired)-1] } }(idx) break diff --git a/internal/operator/orbiter/kinds/providers/gce/pool.go b/internal/operator/orbiter/kinds/providers/gce/pool.go index 68082243c..d9a3f98c8 100644 --- a/internal/operator/orbiter/kinds/providers/gce/pool.go +++ b/internal/operator/orbiter/kinds/providers/gce/pool.go @@ -35,7 +35,7 @@ func (i *infraPool) EnsureMembers() error { func (i *infraPool) ensureMembers(machine infra.Machine) error { - allInstances, err := i.svc.instances() + allInstances, err := getAllInstances(i.svc) if err != nil { return err } diff --git a/internal/operator/orbiter/kinds/providers/providers.go b/internal/operator/orbiter/kinds/providers/providers.go index b9dc23788..c398b8e4b 100644 --- a/internal/operator/orbiter/kinds/providers/providers.go +++ b/internal/operator/orbiter/kinds/providers/providers.go @@ -1,10 +1,11 @@ package providers import ( - "github.com/caos/orbos/pkg/secret" "regexp" "strings" + "github.com/caos/orbos/pkg/secret" + "github.com/caos/orbos/internal/operator/orbiter/kinds/providers/cs" "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra" @@ -28,6 +29,7 @@ func GetQueryAndDestroyFuncs( finishedChan chan struct{}, orbiterCommit, repoURL, repoKey string, oneoff bool, + pprof bool, ) ( orbiter.QueryFunc, orbiter.DestroyFunc, @@ -53,6 +55,7 @@ func GetQueryAndDestroyFuncs( wlFunc, orbiterCommit, repoURL, repoKey, oneoff, + pprof, )( monitor, finishedChan, @@ -66,6 +69,7 @@ func GetQueryAndDestroyFuncs( wlFunc, orbiterCommit, repoURL, repoKey, oneoff, + pprof, )( monitor, finishedChan, @@ -73,18 +77,18 @@ func GetQueryAndDestroyFuncs( providerCurrent, ) case "orbiter.caos.ch/StaticProvider": - adaptFunc := func() (orbiter.QueryFunc, orbiter.DestroyFunc, orbiter.ConfigureFunc, bool, map[string]*secret.Secret, error) { - return static.AdaptFunc( - provID, - wlFunc, - orbiterCommit, repoURL, repoKey, - )( - monitor.WithFields(map[string]interface{}{"provider": provID}), - finishedChan, - providerTree, - providerCurrent) - } - return orbiter.AdaptFuncGoroutine(adaptFunc) + return static.AdaptFunc( + provID, + wlFunc, + orbiterCommit, + repoURL, + repoKey, + pprof, + )( + monitor.WithFields(map[string]interface{}{"provider": provID}), + finishedChan, + providerTree, + providerCurrent) default: return nil, nil, nil, false, nil, errors.Errorf("unknown provider kind %s", providerTree.Common.Kind) } diff --git a/internal/operator/orbiter/kinds/providers/ssh/machine.go b/internal/operator/orbiter/kinds/providers/ssh/machine.go index 0705305c1..51b025ef7 100644 --- a/internal/operator/orbiter/kinds/providers/ssh/machine.go +++ b/internal/operator/orbiter/kinds/providers/ssh/machine.go @@ -56,6 +56,7 @@ func (c *Machine) Execute(stdin io.Reader, cmd string) (stdout []byte, err error } buf := new(bytes.Buffer) + defer buf.Reset() sess.Stdin = stdin sess.Stderr = buf @@ -152,6 +153,7 @@ func (c *Machine) ReadFile(path string, data io.Writer) (err error) { return err } stderr := new(bytes.Buffer) + defer stderr.Reset() sess.Stdout = data sess.Stderr = stderr diff --git a/internal/operator/orbiter/kinds/providers/static/adapt.go b/internal/operator/orbiter/kinds/providers/static/adapt.go index 7b5648504..a3a16dd0c 100644 --- a/internal/operator/orbiter/kinds/providers/static/adapt.go +++ b/internal/operator/orbiter/kinds/providers/static/adapt.go @@ -4,8 +4,8 @@ import ( "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers" "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic" "github.com/caos/orbos/internal/operator/orbiter/kinds/providers/core" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/internal/ssh" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" "github.com/pkg/errors" @@ -15,7 +15,14 @@ import ( "github.com/caos/orbos/mntr" ) -func AdaptFunc(id string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoURL, repoKey string) orbiter.AdaptFunc { +func AdaptFunc( + id string, + whitelist dynamic.WhiteListFunc, + orbiterCommit, + repoURL, + repoKey string, + pprof bool, +) orbiter.AdaptFunc { return func(monitor mntr.Monitor, finishedChan chan struct{}, desiredTree *tree.Tree, currentTree *tree.Tree) (queryFunc orbiter.QueryFunc, destroyFunc orbiter.DestroyFunc, configureFunc orbiter.ConfigureFunc, migrate bool, secrets map[string]*secret.Secret, err error) { defer func() { err = errors.Wrapf(err, "building %s failed", desiredTree.Common.Kind) @@ -26,7 +33,7 @@ func AdaptFunc(id string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoUR } desiredTree.Parsed = desiredKind secrets = make(map[string]*secret.Secret, 0) - secret.AppendSecrets("", secrets, getSecretsMap(desiredKind)) + secret.AppendSecrets("", secrets, getSecretsMap(desiredKind), nil, nil) if desiredKind.Spec.Verbose && !monitor.IsVerbose() { monitor = monitor.Verbose() @@ -51,7 +58,7 @@ func AdaptFunc(id string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoUR if migrateLocal { migrate = true } - secret.AppendSecrets("", secrets, lbsecrets) + secret.AppendSecrets("", secrets, lbsecrets, nil, nil) current := &Current{ Common: &tree.Common{ @@ -71,23 +78,15 @@ func AdaptFunc(id string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoUR return nil, err } - lbQueryFunc := func() (orbiter.EnsureFunc, error) { - return lbQuery(nodeAgentsCurrent, nodeAgentsDesired, nil) - } - - if _, err := orbiter.QueryFuncGoroutine(lbQueryFunc); err != nil { + if _, err := lbQuery(nodeAgentsCurrent, nodeAgentsDesired, nil); err != nil { return nil, err } if err := svc.updateKeys(); err != nil { return nil, err } - - queryFunc := func() (orbiter.EnsureFunc, error) { - _, iterateNA := core.NodeAgentFuncs(monitor, repoURL, repoKey) - return query(desiredKind, current, nodeAgentsDesired, nodeAgentsCurrent, lbCurrent.Parsed, monitor, svc, iterateNA, orbiterCommit) - } - return orbiter.QueryFuncGoroutine(queryFunc) + _, iterateNA := core.NodeAgentFuncs(monitor, repoURL, repoKey, pprof) + return query(desiredKind, current, nodeAgentsDesired, nodeAgentsCurrent, lbCurrent.Parsed, monitor, svc, iterateNA, orbiterCommit) }, func(delegates map[string]interface{}) error { if err := lbDestroy(delegates); err != nil { return err @@ -98,7 +97,7 @@ func AdaptFunc(id string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoUR } return destroy(svc, desiredKind, current) - }, func(orb orb.Orb) error { + }, func(orb orbcfg.Orb) error { if err := lbConfigure(orb); err != nil { return err } @@ -119,7 +118,7 @@ func AdaptFunc(id string, whitelist dynamic.WhiteListFunc, orbiterCommit, repoUR return nil } - return core.ConfigureNodeAgents(svc, monitor, orb) + return core.ConfigureNodeAgents(svc, monitor, orb, pprof) }, migrate, secrets, diff --git a/internal/operator/orbiter/kinds/providers/static/computesservice.go b/internal/operator/orbiter/kinds/providers/static/computesservice.go index 0f87766ed..9fc412ff7 100644 --- a/internal/operator/orbiter/kinds/providers/static/computesservice.go +++ b/internal/operator/orbiter/kinds/providers/static/computesservice.go @@ -4,10 +4,11 @@ import ( "bytes" "errors" "fmt" - secret2 "github.com/caos/orbos/pkg/secret" "path/filepath" "strings" + secret2 "github.com/caos/orbos/pkg/secret" + "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra" "github.com/caos/orbos/internal/operator/orbiter/kinds/providers/core" "github.com/caos/orbos/mntr" @@ -86,12 +87,11 @@ func (c *machinesService) Create(poolName string) (infra.Machine, error) { } for _, machine := range pool { - - if err := machine.WriteFile(fmt.Sprintf("/home/orbiter/.ssh/authorized_keys"), bytes.NewReader([]byte(c.desired.Spec.Keys.MaintenanceKeyPublic.Value)), 600); err != nil { - return nil, err - } - if !machine.X_active { + machine.X_active = true + if err := machine.WriteFile(fmt.Sprintf("/home/orbiter/.ssh/authorized_keys"), bytes.NewReader([]byte(c.desired.Spec.Keys.MaintenanceKeyPublic.Value)), 600); err != nil { + return nil, err + } if err := machine.WriteFile(c.statusFile, strings.NewReader("active"), 600); err != nil { return nil, err @@ -101,7 +101,6 @@ func (c *machinesService) Create(poolName string) (infra.Machine, error) { return nil, err } - machine.X_active = true return machine, nil } } @@ -148,16 +147,19 @@ func (c *machinesService) cachedPool(poolName string) (cachedMachines, error) { } buf := new(bytes.Buffer) + defer buf.Reset() if err := machine.ReadFile(c.statusFile, buf); err != nil { // if error, treat as active } machine.X_active = strings.Contains(buf.String(), "active") - buf.Reset() newCache = append(newCache, machine) } if c.cache == nil { c.cache = make(map[string]cachedMachines) + } else if ok { + c.cache[poolName] = nil + delete(c.cache, poolName) } c.cache[poolName] = newCache return newCache, nil diff --git a/internal/operator/orbiter/kinds/providers/static/desired.go b/internal/operator/orbiter/kinds/providers/static/desired.go index 87f68ed22..daecdba2f 100644 --- a/internal/operator/orbiter/kinds/providers/static/desired.go +++ b/internal/operator/orbiter/kinds/providers/static/desired.go @@ -1,6 +1,9 @@ package static import ( + "fmt" + "regexp" + "github.com/caos/orbos/internal/operator/orbiter" secret2 "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" @@ -78,9 +81,24 @@ type Machine struct { ReplacementRequired bool } +var internetHosts = regexp.MustCompile("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$") + +func validateName(name string) error { + if len(name) > 63 || !internetHosts.MatchString(name) { + return errors.Errorf("name must be compatible with https://tools.ietf.org/html/rfc1123#section-2, but %s is not", name) + } + return nil +} + func (c *Machine) validate() error { - if c.ID == "" { - return errors.New("No id provided") + + if err := validateName(c.ID); err != nil { + return fmt.Errorf("validating id failed: %w", err) } + + if err := validateName(c.Hostname); err != nil { + return fmt.Errorf("validating hostname failed: %w", err) + } + return c.IP.Validate() } diff --git a/internal/operator/orbiter/kinds/providers/static/desired_test.go b/internal/operator/orbiter/kinds/providers/static/desired_test.go new file mode 100644 index 000000000..069c58674 --- /dev/null +++ b/internal/operator/orbiter/kinds/providers/static/desired_test.go @@ -0,0 +1,67 @@ +package static + +import ( + "testing" + + "github.com/caos/orbos/internal/operator/orbiter" +) + +func TestMachine_validate(t *testing.T) { + type fields struct { + ID string + Hostname string + IP orbiter.IPAddress + RebootRequired bool + ReplacementRequired bool + } + tests := []struct { + name string + fields fields + wantErr bool + }{{ + name: "It should succeed when names are RFC 1123 compatible", + fields: fields{ + ID: "valid-name-1", + Hostname: "valid-name-1", + IP: "127.0.0.1", + }, + wantErr: false, + }, { + name: "It should fail when names have uppercase letters", + fields: fields{ + ID: "inValidName", + Hostname: "inValidName", + IP: "127.0.0.1", + }, + wantErr: true, + }, { + name: "It should fail when the ID is empty", + fields: fields{ + Hostname: "valid-name-1", + IP: "127.0.0.1", + }, + wantErr: true, + }, { + name: "It should fail when the ID is too long", + fields: fields{ + ID: "a-too-long-name-that-possibly-breaks-many-applications-as-it-doesnt-adhere-to-rfc-1123", + Hostname: "valid-name-1", + IP: "127.0.0.1", + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Machine{ + ID: tt.fields.ID, + Hostname: tt.fields.Hostname, + IP: tt.fields.IP, + RebootRequired: tt.fields.RebootRequired, + ReplacementRequired: tt.fields.ReplacementRequired, + } + if err := c.validate(); (err != nil) != tt.wantErr { + t.Errorf("validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/operator/orbiter/takeoff.go b/internal/operator/orbiter/takeoff.go index bd1883558..2668fafed 100644 --- a/internal/operator/orbiter/takeoff.go +++ b/internal/operator/orbiter/takeoff.go @@ -1,8 +1,12 @@ package orbiter import ( + "errors" "fmt" "net/http" + "time" + + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -10,7 +14,6 @@ import ( "github.com/caos/orbos/internal/api" "github.com/caos/orbos/internal/operator/common" - orbconfig "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/secret" @@ -29,9 +32,9 @@ type EnsureResult struct { Done bool } -type ConfigureFunc func(orb orbconfig.Orb) error +type ConfigureFunc func(orb orbcfg.Orb) error -func NoopConfigure(orb orbconfig.Orb) error { +func NoopConfigure(orb orbcfg.Orb) error { return nil } @@ -43,42 +46,53 @@ func NoopEnsure(_ api.PushDesiredFunc) *EnsureResult { return &EnsureResult{Done: true} } -type retQuery struct { - ensure EnsureFunc - err error -} - -func QueryFuncGoroutine(query func() (EnsureFunc, error)) (EnsureFunc, error) { - retChan := make(chan retQuery) - go func() { - ensure, err := query() - retChan <- retQuery{ensure, err} - }() - ret := <-retChan - return ret.ensure, ret.err -} - -func EnsureFuncGoroutine(ensure func() *EnsureResult) *EnsureResult { - retChan := make(chan *EnsureResult) - go func() { - retChan <- ensure() - }() - return <-retChan -} - type event struct { commit string files []git.File } -func Metrics() { +func Instrument(monitor mntr.Monitor, healthyChan chan bool) { + healthy := true + + prometheus.MustRegister(prometheus.NewBuildInfoCollector()) + http.Handle("/metrics", promhttp.Handler()) + http.HandleFunc("/health", func(writer http.ResponseWriter, request *http.Request) { + msg := "OK" + status := 200 + if !healthy { + msg = "ORBITER is not healthy. See the logs." + status = 404 + } + writer.WriteHeader(status) + writer.Write([]byte(msg)) + }) + go func() { - prometheus.MustRegister(prometheus.NewBuildInfoCollector()) - http.Handle("/metrics", promhttp.Handler()) - if err := http.ListenAndServe(":9000", nil); err != nil { - panic(err) + timeout := 10 * time.Minute + ticker := time.NewTimer(timeout) + for { + select { + case newHealthiness := <-healthyChan: + ticker.Reset(timeout) + if newHealthiness == healthy { + continue + } + healthy = newHealthiness + if !newHealthiness { + monitor.Error(errors.New("ORBITER is unhealthy now")) + continue + } + monitor.Info("ORBITER is healthy now") + case <-ticker.C: + monitor.Error(errors.New("ORBITER is unhealthy now as it did not report healthiness for 10 minutes")) + healthy = false + } } }() + + if err := http.ListenAndServe(":9000", nil); err != nil { + panic(err) + } } func Adapt(gitClient *git.Client, monitor mntr.Monitor, finished chan struct{}, adapt AdaptFunc) (QueryFunc, DestroyFunc, ConfigureFunc, bool, *tree.Tree, *tree.Tree, map[string]*secret.Secret, error) { @@ -89,17 +103,25 @@ func Adapt(gitClient *git.Client, monitor mntr.Monitor, finished chan struct{}, } treeCurrent := &tree.Tree{} - adaptFunc := func() (QueryFunc, DestroyFunc, ConfigureFunc, bool, map[string]*secret.Secret, error) { - return adapt(monitor, finished, treeDesired, treeCurrent) - } - query, destroy, configure, migrate, secrets, err := AdaptFuncGoroutine(adaptFunc) + query, destroy, configure, migrate, secrets, err := adapt(monitor, finished, treeDesired, treeCurrent) return query, destroy, configure, migrate, treeDesired, treeCurrent, secrets, err } -func Takeoff(monitor mntr.Monitor, conf *Config) func() { +func Takeoff(monitor mntr.Monitor, conf *Config, healthyChan chan bool) func() { return func() { + var err error + defer func() { + go func() { + if err != nil { + healthyChan <- false + return + } + healthyChan <- true + }() + }() + query, _, _, migrate, treeDesired, treeCurrent, _, err := Adapt(conf.GitClient, monitor, conf.FinishedChan, conf.Adapt) if err != nil { monitor.Error(err) @@ -125,7 +147,7 @@ func Takeoff(monitor mntr.Monitor, conf *Config) func() { } if migrate { - if err := api.PushOrbiterYml(monitor, "Desired state migrated", conf.GitClient, treeDesired); err != nil { + if err = api.PushOrbiterYml(monitor, "Desired state migrated", conf.GitClient, treeDesired); err != nil { monitor.Error(err) return } @@ -146,10 +168,7 @@ func Takeoff(monitor mntr.Monitor, conf *Config) func() { monitor.Error(conf.GitClient.Push()) } - queryFunc := func() (EnsureFunc, error) { - return query(¤tNodeAgents.Current, &desiredNodeAgents.Spec.NodeAgents, nil) - } - ensure, err := QueryFuncGoroutine(queryFunc) + ensure, err := query(¤tNodeAgents.Current, &desiredNodeAgents.Spec.NodeAgents, nil) if err != nil { handleAdapterError(err) return @@ -174,11 +193,7 @@ func Takeoff(monitor mntr.Monitor, conf *Config) func() { } } - ensureFunc := func() *EnsureResult { - return ensure(api.PushOrbiterDesiredFunc(conf.GitClient, treeDesired)) - } - - result := EnsureFuncGoroutine(ensureFunc) + result := ensure(api.PushOrbiterDesiredFunc(conf.GitClient, treeDesired)) if result.Err != nil { handleAdapterError(result.Err) return @@ -201,7 +216,11 @@ func Takeoff(monitor mntr.Monitor, conf *Config) func() { } if changed { - monitor.Error(conf.GitClient.Push()) + pushErr := conf.GitClient.Push() + if err == nil { + err = pushErr + } + monitor.Error(err) } } } diff --git a/internal/orb/orb.go b/internal/orb/orb.go deleted file mode 100644 index 37924eec4..000000000 --- a/internal/orb/orb.go +++ /dev/null @@ -1,82 +0,0 @@ -package orb - -import ( - "fmt" - secret2 "github.com/caos/orbos/pkg/secret" - "io/ioutil" - "os" - - "github.com/caos/orbos/internal/helpers" - - "github.com/pkg/errors" - "gopkg.in/yaml.v3" -) - -type Orb struct { - Path string `yaml:"-"` - URL string - Repokey string - Masterkey string -} - -func (o *Orb) IsConnectable() (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("repository is not connectable: %w", err) - } - }() - if o.URL == "" { - err = helpers.Concat(err, errors.New("repository url is missing")) - } - - if o.Repokey == "" { - err = helpers.Concat(err, errors.New("repository key is missing")) - } - return err -} - -func (o *Orb) IsComplete() (err error) { - - defer func() { - if err != nil { - err = fmt.Errorf("orbconfig is incomplete: %w", err) - } - }() - - if o.Masterkey == "" { - err = helpers.Concat(err, errors.New("master key is missing")) - } - - if o.Path == "" { - err = helpers.Concat(err, errors.New("file path is missing")) - } - - return helpers.Concat(err, o.IsConnectable()) -} - -func ParseOrbConfig(orbConfigPath string) (*Orb, error) { - - gitOrbConfig, err := ioutil.ReadFile(orbConfigPath) - - if err != nil { - return nil, errors.Wrap(err, "unable to read orbconfig") - } - - orb := &Orb{} - if err := yaml.Unmarshal(gitOrbConfig, orb); err != nil { - return nil, errors.Wrap(err, "unable to parse orbconfig") - } - - orb.Path = orbConfigPath - secret2.Masterkey = orb.Masterkey - return orb, nil -} - -func (o *Orb) WriteBackOrbConfig() error { - data, err := yaml.Marshal(o) - if err != nil { - return err - } - - return ioutil.WriteFile(o.Path, data, os.ModePerm) -} diff --git a/internal/secret/operators/operators.go b/internal/secret/operators/operators.go index 0517782e3..e94e4e17a 100644 --- a/internal/secret/operators/operators.go +++ b/internal/secret/operators/operators.go @@ -2,17 +2,23 @@ package operators import ( "errors" + "fmt" "strings" + "github.com/caos/orbos/internal/operator/boom/api/latest" + + orbiterOrb "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/internal/api" + boomcrd "github.com/caos/orbos/internal/api/boom" + nwcrd "github.com/caos/orbos/internal/api/networking" boomapi "github.com/caos/orbos/internal/operator/boom/api" nwOrb "github.com/caos/orbos/internal/operator/networking/kinds/orb" - orbiterOrb "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" - "github.com/caos/orbos/internal/orb" "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + orbcfg "github.com/caos/orbos/pkg/orb" "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" ) @@ -23,108 +29,189 @@ const ( networking string = "networking" ) -func GetAllSecretsFunc(orb *orb.Orb, binaryVersion *string) func(monitor mntr.Monitor, gitClient *git.Client) (map[string]*secret.Secret, map[string]*tree.Tree, error) { - return func(monitor mntr.Monitor, gitClient *git.Client) (map[string]*secret.Secret, map[string]*tree.Tree, error) { - allSecrets := make(map[string]*secret.Secret, 0) - allTrees := make(map[string]*tree.Tree, 0) - foundBoom, err := api.ExistsBoomYml(gitClient) - if err != nil { - return nil, nil, err - } - if foundBoom { - boomYML, err := api.ReadBoomYml(gitClient) - if err != nil { - return nil, nil, err - } - allTrees[boom] = boomYML - _, _, boomSecrets, _, _, err := boomapi.ParseToolset(boomYML) - if err != nil { - return nil, nil, err - } - - if boomSecrets != nil && len(boomSecrets) > 0 { - secret.AppendSecrets(boom, allSecrets, boomSecrets) - } - } +func GetAllSecretsFunc( + monitor mntr.Monitor, + printLogs, + gitops bool, + gitClient *git.Client, + k8sClient kubernetes.ClientInt, + orb *orbcfg.Orb, +) func() ( + map[string]*secret.Secret, + map[string]*secret.Existing, + map[string]*tree.Tree, + error, +) { + return func() ( + map[string]*secret.Secret, + map[string]*secret.Existing, + map[string]*tree.Tree, + error, + ) { + return getAllSecrets(monitor, printLogs, gitops, gitClient, k8sClient, orb) + } +} - foundOrbiter, err := api.ExistsOrbiterYml(gitClient) - if err != nil { - return nil, nil, err - } - if foundOrbiter { - orbiterYML, err := api.ReadOrbiterYml(gitClient) - if err != nil { - return nil, nil, err - } - allTrees[orbiter] = orbiterYML - - _, _, _, _, orbiterSecrets, err := orbiterOrb.AdaptFunc( - labels.NoopOperator("ORBOS"), - orb, - "", - true, - false, - gitClient, - )(monitor, make(chan struct{}), orbiterYML, &tree.Tree{}) +func getAllSecrets( + monitor mntr.Monitor, + printLogs, + gitops bool, + gitClient *git.Client, + k8sClient kubernetes.ClientInt, + orb *orbcfg.Orb, +) ( + map[string]*secret.Secret, + map[string]*secret.Existing, + map[string]*tree.Tree, + error, +) { + + allSecrets := make(map[string]*secret.Secret, 0) + allExisting := make(map[string]*secret.Existing, 0) + allTrees := make(map[string]*tree.Tree, 0) + + if err := secret.GetOperatorSecrets( + monitor, + printLogs, + gitops, + allTrees, + allSecrets, + allExisting, + boom, + func() (bool, error) { return api.ExistsBoomYml(gitClient) }, + func() (*tree.Tree, error) { return api.ReadBoomYml(gitClient) }, + func() (*tree.Tree, error) { return boomcrd.ReadCRD(k8sClient) }, + func(t *tree.Tree) (map[string]*secret.Secret, map[string]*secret.Existing, bool, error) { + toolset, migrate, _, _, err := boomapi.ParseToolset(t) if err != nil { - return nil, nil, err + return nil, nil, false, err } + boomSecrets, boomExistingSecrets := latest.GetSecretsMap(toolset) + return boomSecrets, boomExistingSecrets, migrate, nil + }, + ); err != nil { + return nil, nil, nil, err + } - if orbiterSecrets != nil && len(orbiterSecrets) > 0 { - secret.AppendSecrets(orbiter, allSecrets, orbiterSecrets) - } + if gitops { + if err := secret.GetOperatorSecrets( + monitor, + printLogs, + gitops, + allTrees, + allSecrets, + allExisting, + orbiter, + func() (bool, error) { return api.ExistsOrbiterYml(gitClient) }, + func() (*tree.Tree, error) { return api.ReadOrbiterYml(gitClient) }, + func() (*tree.Tree, error) { return nil, errors.New("ORBITER doesn't support crd mode") }, + func(t *tree.Tree) (map[string]*secret.Secret, map[string]*secret.Existing, bool, error) { + _, _, _, migrate, orbiterSecrets, err := orbiterOrb.AdaptFunc( + labels.NoopOperator("ORBOS"), + orb, + "", + true, + false, + gitClient, + )(monitor, make(chan struct{}), t, &tree.Tree{}) + return orbiterSecrets, nil, migrate, err + }, + ); err != nil { + return nil, nil, nil, err } + } - foundNW, err := api.ExistsNetworkingYml(gitClient) - if err != nil { - return nil, nil, err - } - if foundNW { - nwYML, err := api.ReadNetworkinglYml(gitClient) - if err != nil { - return nil, nil, err - } - allTrees[networking] = nwYML + if err := secret.GetOperatorSecrets( + monitor, + printLogs, + gitops, + allTrees, + allSecrets, + allExisting, + networking, + func() (bool, error) { return api.ExistsNetworkingYml(gitClient) }, + func() (*tree.Tree, error) { return api.ReadNetworkinglYml(gitClient) }, + func() (*tree.Tree, error) { return nwcrd.ReadCRD(k8sClient) }, + func(t *tree.Tree) (map[string]*secret.Secret, map[string]*secret.Existing, bool, error) { + _, _, nwSecrets, nwExisting, migrate, err := nwOrb.AdaptFunc("", nil, false)(monitor, t, nil) + return nwSecrets, nwExisting, migrate, err + }, + ); err != nil { + return nil, nil, nil, err + } - _, _, nwSecrets, err := nwOrb.AdaptFunc("", nil)(monitor, nwYML, nil) - if err != nil { - return nil, nil, err - } - if nwSecrets != nil && len(nwSecrets) > 0 { - secret.AppendSecrets(networking, allSecrets, nwSecrets) - } - } + if len(allSecrets) == 0 && len(allExisting) == 0 { + return nil, nil, nil, errors.New("couldn't find any secrets") + } + + return allSecrets, allExisting, allTrees, nil +} - return allSecrets, allTrees, nil +func PushFunc( + monitor mntr.Monitor, + gitops bool, + gitClient *git.Client, + k8sClient kubernetes.ClientInt, +) func( + trees map[string]*tree.Tree, + path string, +) error { + return func( + trees map[string]*tree.Tree, + path string, + ) error { + return push(monitor, gitops, gitClient, k8sClient, trees, path) } } -func PushFunc() func(monitor mntr.Monitor, gitClient *git.Client, trees map[string]*tree.Tree, path string) error { - return func(monitor mntr.Monitor, gitClient *git.Client, trees map[string]*tree.Tree, path string) error { - operator := "" - if strings.HasPrefix(path, orbiter) { - operator = orbiter - } else if strings.HasPrefix(path, boom) { - operator = boom - } else if strings.HasPrefix(path, networking) { - operator = networking - } else { - return errors.New("Operator unknown") +func push( + monitor mntr.Monitor, + gitops bool, + gitClient *git.Client, + k8sClient kubernetes.ClientInt, + trees map[string]*tree.Tree, + path string, +) error { + var ( + pushGitFunc func(*tree.Tree) error + applyCRDFunc func(*tree.Tree) error + operator string + ) + if strings.HasPrefix(path, orbiter) { + operator = orbiter + pushGitFunc = func(desired *tree.Tree) error { + return api.PushOrbiterDesiredFunc(gitClient, desired)(monitor) } - - desired, found := trees[operator] - if !found { - return errors.New("Operator file not found") + applyCRDFunc = func(t *tree.Tree) error { + panic(errors.New("ORBITER doesn't support CRD mode")) } - - if operator == orbiter { - return api.PushOrbiterDesiredFunc(gitClient, desired)(monitor) - } else if operator == boom { + } else if strings.HasPrefix(path, boom) { + operator = boom + pushGitFunc = func(desired *tree.Tree) error { return api.PushBoomDesiredFunc(gitClient, desired)(monitor) - } else if operator == networking { + } + applyCRDFunc = func(t *tree.Tree) error { + return boomcrd.WriteCrd(k8sClient, t) + } + } else if strings.HasPrefix(path, networking) { + operator = networking + pushGitFunc = func(desired *tree.Tree) error { return api.PushNetworkingDesiredFunc(gitClient, desired)(monitor) } + applyCRDFunc = func(t *tree.Tree) error { + return nwcrd.WriteCrd(k8sClient, t) + } + } else { + return errors.New("operator unknown") + } + + desired, found := trees[operator] + if !found { + return fmt.Errorf("desired state for %s not found", operator) + } - return errors.New("Operator push function unknown") + if gitops { + return pushGitFunc(desired) } + return applyCRDFunc(desired) } diff --git a/internal/ssh/ssh.go b/internal/ssh/ssh.go index 84d0dc4fe..cd4972688 100644 --- a/internal/ssh/ssh.go +++ b/internal/ssh/ssh.go @@ -47,19 +47,24 @@ func Generate() (private string, public string, err error) { func AuthMethodFromKeys(privKey ...[]byte) (method sshlib.AuthMethod, err error) { var signers []sshlib.Signer - for _, key := range privKey { + for _, copyKey := range privKey { + key := copyKey + cached := false for _, cachedKey := range cachedKeys { if string(cachedKey.private) == string(key) { + cached = true signers = append(signers, cachedKey.signer) break } } - signer, err := sshlib.ParsePrivateKey(key) - if err != nil { - return nil, errors.Wrap(err, "parsing private key failed") + if !cached { + signer, err := sshlib.ParsePrivateKey(key) + if err != nil { + return nil, errors.Wrap(err, "parsing private key failed") + } + cachedKeys = append(cachedKeys, pair{key, signer}) + signers = append(signers, signer) } - cachedKeys = append(cachedKeys, pair{key, signer}) - signers = append(signers, signer) } return sshlib.PublicKeys(signers...), nil diff --git a/internal/utils/clientgo/clientgo.go b/internal/utils/clientgo/clientgo.go index 1915fd026..29e5166f1 100644 --- a/internal/utils/clientgo/clientgo.go +++ b/internal/utils/clientgo/clientgo.go @@ -1,23 +1,46 @@ package clientgo import ( + "errors" + "fmt" "os" "path/filepath" - pkgerrors "github.com/pkg/errors" + "github.com/caos/orbos/mntr" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" ) -var InConfig = true +func GetClusterConfig(monitor mntr.Monitor, path string) (*rest.Config, error) { -func GetClusterConfig() (*rest.Config, error) { - if InConfig { - return getInClusterConfig() - } else { - return getOutClusterConfig() + monitor.Debug("trying to use in-cluster kube client") + if cfg, err := getInClusterConfig(); err == nil { + monitor.Debug("using in-cluster kube client") + return cfg, nil } + + if path != "" { + if cfg, err := getOutClusterConfigPath(path); err == nil { + return cfg, nil + } + monitor.Info(fmt.Sprintf("no kubeconfig found at path %s", path)) + } + + if cfg, err := getOutClusterConfig(); err == nil { + return cfg, nil + } + + monitor.Info(fmt.Sprintf("no kubeconfig found at path %s", "$HOME/.kube/config")) + + err := errors.New("no kubeconfig found") + monitor.Error(err) + return nil, err +} +func getOutClusterConfigPath(path string) (*rest.Config, error) { + // use the current context in kubeconfig + config, err := clientcmd.BuildConfigFromFlags("", path) + return config, nonNilErrorf("creating out-cluster config failed: %w", err) } func getOutClusterConfig() (*rest.Config, error) { @@ -25,7 +48,7 @@ func getOutClusterConfig() (*rest.Config, error) { // use the current context in kubeconfig config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) - return config, pkgerrors.Wrap(err, "Error while creating out-cluster config") + return config, nonNilErrorf("creating out-cluster config failed: %w", err) } func homeDir() string { @@ -38,11 +61,19 @@ func homeDir() string { func getInClusterConfig() (*rest.Config, error) { // creates the in-cluster config config, err := rest.InClusterConfig() - return config, pkgerrors.Wrap(err, "Error while creating in-cluster config") + return config, nonNilErrorf("creating in-cluster config failed: %w", err) } func getClientSet(config *rest.Config) (*kubernetes.Clientset, error) { // creates the clientset clientset, err := kubernetes.NewForConfig(config) - return clientset, pkgerrors.Wrap(err, "Error while creating clientset") + return clientset, nonNilErrorf("creating clientset failed: %w", err) +} + +func nonNilErrorf(format string, err error, val ...interface{}) error { + if err == nil { + return nil + } + + return fmt.Errorf(format, append([]interface{}{err}, val...)) } diff --git a/internal/utils/clientgo/resource.go b/internal/utils/clientgo/resource.go index 22ca1beb6..b4ce801f7 100644 --- a/internal/utils/clientgo/resource.go +++ b/internal/utils/clientgo/resource.go @@ -3,6 +3,8 @@ package clientgo import ( "context" "fmt" + "strings" + "github.com/caos/orbos/mntr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -10,7 +12,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" - "strings" ) var ( @@ -84,9 +85,10 @@ func (a ResourceSorter) Less(i, j int) bool { (a[i].Group == a[j].Group && a[i].Version == a[j].Version && a[i].Resource == a[j].Resource && a[i].Kind == a[j].Kind && a[i].Name == a[j].Name && a[i].Namespace < a[j].Namespace)) } -func GetResource(group, version, resource, namespace, name string) (*Resource, error) { +func GetResource(monitor mntr.Monitor, group, version, resource, namespace, name string) (*Resource, error) { res := schema.GroupVersionResource{Group: group, Version: version, Resource: resource} - conf, err := GetClusterConfig() + + conf, err := GetClusterConfig(monitor, "") if err != nil { return nil, err } @@ -109,9 +111,9 @@ func GetResource(group, version, resource, namespace, name string) (*Resource, e }, nil } -func DeleteResource(resource *Resource) error { +func DeleteResource(monitor mntr.Monitor, resource *Resource) error { res := schema.GroupVersionResource{Group: resource.Group, Version: resource.Version, Resource: resource.Resource} - conf, err := GetClusterConfig() + conf, err := GetClusterConfig(monitor, "") if err != nil { return err } @@ -141,26 +143,26 @@ func GetGroupVersionsResources(monitor mntr.Monitor, filtersResources []string) "action": "groupVersionResources", }) - conf, err := GetClusterConfig() + conf, err := GetClusterConfig(monitor, "") if err != nil { - return nil, err + return nil, fmt.Errorf("getting cluster config failed: %w", err) } client, err := discovery.NewDiscoveryClientForConfig(conf) if err != nil { - return nil, err + return nil, fmt.Errorf("creating discovery client failed: %w", err) } apiGroups, err := client.ServerGroups() if err != nil { - return nil, err + return nil, fmt.Errorf("getting supported groups and versions failed: %w", err) } resourceInfoList := make([]*ResourceInfo, 0) for _, apiGroup := range apiGroups.Groups { version := apiGroup.PreferredVersion apiResources, err := client.ServerResourcesForGroupVersion(version.GroupVersion) if err != nil { - return nil, err + return nil, fmt.Errorf("getting supported resources failed for %s: %w", version.GroupVersion, err) } for _, apiResource := range apiResources.APIResources { @@ -202,7 +204,7 @@ func ListResources(monitor mntr.Monitor, resourceInfoList []*ResourceInfo, label listMonitor := monitor.WithFields(map[string]interface{}{ "action": "listResources", }) - conf, err := GetClusterConfig() + conf, err := GetClusterConfig(monitor, "") if err != nil { return nil, err } diff --git a/internal/utils/clientgo/secret.go b/internal/utils/clientgo/secret.go index 64c0d6260..ab5f0a1c6 100644 --- a/internal/utils/clientgo/secret.go +++ b/internal/utils/clientgo/secret.go @@ -2,13 +2,14 @@ package clientgo import ( "context" + "github.com/caos/orbos/mntr" pkgerrors "github.com/pkg/errors" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func GetSecret(name, namespace string) (*v1.Secret, error) { - conf, err := GetClusterConfig() + conf, err := GetClusterConfig(mntr.Monitor{}, "") if err != nil { return nil, err } diff --git a/internal/utils/helper/secret.go b/internal/utils/helper/secret.go deleted file mode 100644 index 8eb4e9188..000000000 --- a/internal/utils/helper/secret.go +++ /dev/null @@ -1,42 +0,0 @@ -package helper - -import ( - "github.com/caos/orbos/internal/utils/clientgo" - secret2 "github.com/caos/orbos/pkg/secret" -) - -func IsExistentSecret(secret *secret2.Secret, existent *secret2.Existing) bool { - if (secret == nil || secret.Value == "") && existent != nil && (existent.Name != "" && existent.Key != "") { - return true - } - return false -} - -func IsExistentClientSecret(existent *secret2.ExistingIDSecret) bool { - if existent != nil && (existent.Name != "" && existent.IDKey != "" && existent.SecretKey != "") { - return true - } - return false -} - -func IsCrdSecret(secret *secret2.Secret, existent *secret2.Existing) bool { - if (secret != nil && secret.Value != "") && (existent == nil || (existent.Name == "" || existent.Key == "")) { - return true - } - return false -} - -func GetSecretValue(secret *secret2.Secret, existing *secret2.Existing) (string, error) { - if IsExistentSecret(secret, existing) { - secret, err := clientgo.GetSecret(existing.Name, "caos-system") - if err != nil { - return "", err - } - - return string(secret.Data[existing.Key]), nil - } else if IsCrdSecret(secret, existing) { - return secret.Value, nil - } - - return "", nil -} diff --git a/pkg/git/git.go b/pkg/git/git.go index 967529049..378b4dc58 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -11,23 +11,24 @@ import ( "strings" "time" - "gopkg.in/src-d/go-git.v4/config" + "github.com/go-git/go-git/v5/config" "gopkg.in/yaml.v3" "github.com/pkg/errors" "github.com/caos/orbos/mntr" + billy "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" + gogit "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" + gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh" + "github.com/go-git/go-git/v5/storage/memory" "golang.org/x/crypto/ssh" - "gopkg.in/src-d/go-billy.v4" - "gopkg.in/src-d/go-billy.v4/memfs" - gogit "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing/object" - gitssh "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh" - "gopkg.in/src-d/go-git.v4/storage/memory" ) const ( writeCheckTag = "writecheck" + branch = "master" ) type Client struct { @@ -38,6 +39,7 @@ type Client struct { auth *gitssh.PublicKeys repo *gogit.Repository fs billy.Filesystem + storage *memory.Storage workTree *gogit.Worktree progress io.Writer repoURL string @@ -50,6 +52,8 @@ func New(ctx context.Context, monitor mntr.Monitor, committer, email string) *Cl committer: committer, email: email, monitor: monitor, + storage: memory.NewStorage(), + fs: memfs.New(), } if monitor.IsVerbose() { @@ -68,7 +72,10 @@ func (g *Client) Configure(repoURL string, deploykey []byte) error { return errors.Wrap(err, "parsing deployment key failed") } - g.repoURL = repoURL + if repoURL != g.repoURL { + g.repoURL = repoURL + g.cloned = false + } g.monitor = g.monitor.WithField("repository", repoURL) g.auth = &gitssh.PublicKeys{ @@ -94,6 +101,7 @@ func (g *Client) Check() error { } func (g *Client) readCheck() error { + rem := gogit.NewRemote(memory.NewStorage(), &config.RemoteConfig{ Name: "origin", URLs: []string{g.repoURL}, @@ -172,7 +180,6 @@ func (g *Client) Clone() (err error) { } func (g *Client) clone() error { - g.fs = memfs.New() g.monitor.Debug("Cloning") diff --git a/pkg/helper/secret.go b/pkg/helper/secret.go new file mode 100644 index 000000000..ef8fca50f --- /dev/null +++ b/pkg/helper/secret.go @@ -0,0 +1,58 @@ +package helper + +import ( + "github.com/caos/orbos/internal/utils/clientgo" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/secret" +) + +func IsExistentSecret(secret *secret.Secret, existent *secret.Existing) bool { + if (secret == nil || secret.Value == "") && existent != nil && (existent.Name != "" && existent.Key != "") { + return true + } + return false +} + +func IsExistentClientSecret(existent *secret.ExistingIDSecret) bool { + if existent != nil && (existent.Name != "" && existent.IDKey != "" && existent.SecretKey != "") { + return true + } + return false +} + +func IsCrdSecret(secret *secret.Secret, existent *secret.Existing) bool { + if (secret != nil && secret.Value != "") && (existent == nil || (existent.Name == "" || existent.Key == "")) { + return true + } + return false +} + +func GetSecretValueOnlyIncluster(secret *secret.Secret, existing *secret.Existing) (string, error) { + if IsExistentSecret(secret, existing) { + secret, err := clientgo.GetSecret(existing.Name, "caos-system") + if err != nil { + return "", err + } + + return string(secret.Data[existing.Key]), nil + } else if IsCrdSecret(secret, existing) { + return secret.Value, nil + } + + return "", nil +} + +func GetSecretValue(k8sClient kubernetes.ClientInt, secret *secret.Secret, existing *secret.Existing) (string, error) { + if IsExistentSecret(secret, existing) { + secret, err := k8sClient.GetSecret("caos-system", existing.Name) + if err != nil { + return "", err + } + + return string(secret.Data[existing.Key]), nil + } else if IsCrdSecret(secret, existing) { + return secret.Value, nil + } + + return "", nil +} diff --git a/pkg/kubernetes/artifacts.go b/pkg/kubernetes/artifacts.go index a75253a3b..f50bca8a2 100644 --- a/pkg/kubernetes/artifacts.go +++ b/pkg/kubernetes/artifacts.go @@ -1,27 +1,15 @@ package kubernetes import ( - "fmt" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/internal/orb" - "github.com/caos/orbos/pkg/kubernetes/k8s" - - "k8s.io/apimachinery/pkg/util/intstr" - - "k8s.io/apimachinery/pkg/api/resource" - - "gopkg.in/yaml.v2" - apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" - rbac "k8s.io/api/rbac/v1" mach "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/caos/orbos/mntr" ) -func EnsureCommonArtifacts(monitor mntr.Monitor, client *Client) error { +func EnsureCaosSystemNamespace(monitor mntr.Monitor, client ClientInt) error { monitor.Debug("Ensuring common artifacts") @@ -36,14 +24,9 @@ func EnsureCommonArtifacts(monitor mntr.Monitor, client *Client) error { }) } -func EnsureConfigArtifacts(monitor mntr.Monitor, client *Client, orb *orb.Orb) error { +func EnsureOrbconfigSecret(monitor mntr.Monitor, client ClientInt, orbconfig []byte) error { monitor.Debug("Ensuring configuration artifacts") - orbfile, err := yaml.Marshal(orb) - if err != nil { - return err - } - if err := client.ApplySecret(&core.Secret{ ObjectMeta: mach.ObjectMeta{ Name: "caos", @@ -53,294 +36,12 @@ func EnsureConfigArtifacts(monitor mntr.Monitor, client *Client, orb *orb.Orb) e }, }, StringData: map[string]string{ - "orbconfig": string(orbfile), - }, - }); err != nil { - return err - } - - return nil -} - -func EnsureNetworkingArtifacts( - monitor mntr.Monitor, - apiLabels *labels.API, - client ClientInt, - version string, - nodeselector map[string]string, - tolerations []core.Toleration, - imageRegistry string) error { - - monitor.WithFields(map[string]interface{}{ - "networking": version, - }).Debug("Ensuring networking artifacts") - - if version == "" { - return nil - } - - nameLabels := toNameLabels(apiLabels, "networking-operator") - k8sNameLabels := labels.MustK8sMap(nameLabels) - - if err := client.ApplyServiceAccount(&core.ServiceAccount{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sNameLabels, - }, - }); err != nil { - return err - } - - if err := client.ApplyClusterRole(&rbac.ClusterRole{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - Rules: []rbac.PolicyRule{{ - APIGroups: []string{"*"}, - Resources: []string{"*"}, - Verbs: []string{"*"}, - }}, - }); err != nil { - return err - } - - if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - - RoleRef: rbac.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: nameLabels.Name(), + "orbconfig": string(orbconfig), }, - Subjects: []rbac.Subject{{ - Kind: "ServiceAccount", - Name: nameLabels.Name(), - Namespace: "caos-system", - }}, }); err != nil { return err } - deployment := &apps.Deployment{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sNameLabels, - }, - Spec: apps.DeploymentSpec{ - Replicas: int32Ptr(1), - Selector: &mach.LabelSelector{ - MatchLabels: labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)), - }, - Template: core.PodTemplateSpec{ - ObjectMeta: mach.ObjectMeta{ - Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), - }, - Spec: core.PodSpec{ - ServiceAccountName: nameLabels.Name(), - Containers: []core.Container{{ - Name: "networking", - ImagePullPolicy: core.PullIfNotPresent, - Image: fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, version), - Command: []string{"/orbctl", "takeoff", "networking", "-f", "/secrets/orbconfig"}, - Args: []string{}, - Ports: []core.ContainerPort{{ - Name: "metrics", - ContainerPort: 2112, - Protocol: "TCP", - }}, - VolumeMounts: []core.VolumeMount{{ - Name: "orbconfig", - ReadOnly: true, - MountPath: "/secrets", - }}, - Resources: core.ResourceRequirements{ - Limits: core.ResourceList{ - "cpu": resource.MustParse("500m"), - "memory": resource.MustParse("500Mi"), - }, - Requests: core.ResourceList{ - "cpu": resource.MustParse("250m"), - "memory": resource.MustParse("250Mi"), - }, - }, - }}, - NodeSelector: nodeselector, - Tolerations: tolerations, - Volumes: []core.Volume{{ - Name: "orbconfig", - VolumeSource: core.VolumeSource{ - Secret: &core.SecretVolumeSource{ - SecretName: "caos", - }, - }, - }}, - TerminationGracePeriodSeconds: int64Ptr(10), - }, - }, - }, - } - if err := client.ApplyDeployment(deployment, true); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": version, - }).Debug("Networking Operator deployment ensured") - - return nil -} - -func EnsureBoomArtifacts( - monitor mntr.Monitor, - apiLabels *labels.API, - client *Client, - version string, - tolerations k8s.Tolerations, - nodeselector map[string]string, - resources *k8s.Resources, - imageRegistry string) error { - - monitor.WithFields(map[string]interface{}{ - "boom": version, - }).Debug("Ensuring boom artifacts") - - if version == "" { - return nil - } - - nameLabels := toNameLabels(apiLabels, "boom") - k8sNameLabels := labels.MustK8sMap(nameLabels) - - if err := client.ApplyServiceAccount(&core.ServiceAccount{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sNameLabels, - }, - }); err != nil { - return err - } - - if err := client.ApplyClusterRole(&rbac.ClusterRole{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - Rules: []rbac.PolicyRule{{ - APIGroups: []string{"*"}, - Resources: []string{"*"}, - Verbs: []string{"*"}, - }}, - }); err != nil { - return err - } - - if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - - RoleRef: rbac.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: nameLabels.Name(), - }, - Subjects: []rbac.Subject{{ - Kind: "ServiceAccount", - Name: nameLabels.Name(), - Namespace: "caos-system", - }}, - }); err != nil { - return err - } - - k8sPodSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) - - deployment := &apps.Deployment{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sNameLabels, - }, - Spec: apps.DeploymentSpec{ - Replicas: int32Ptr(1), - Selector: &mach.LabelSelector{ - MatchLabels: k8sPodSelector, - }, - Template: core.PodTemplateSpec{ - ObjectMeta: mach.ObjectMeta{ - Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), - }, - Spec: core.PodSpec{ - ServiceAccountName: nameLabels.Name(), - Containers: []core.Container{{ - Name: "boom", - ImagePullPolicy: core.PullIfNotPresent, - Image: fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, version), - Command: []string{"/orbctl", "takeoff", "boom", "-f", "/secrets/orbconfig"}, - Args: []string{}, - Ports: []core.ContainerPort{{ - Name: "metrics", - ContainerPort: 2112, - Protocol: "TCP", - }}, - VolumeMounts: []core.VolumeMount{{ - Name: "orbconfig", - ReadOnly: true, - MountPath: "/secrets", - }}, - Resources: core.ResourceRequirements(*resources), - }}, - NodeSelector: nodeselector, - Tolerations: tolerations.K8s(), - Volumes: []core.Volume{{ - Name: "orbconfig", - VolumeSource: core.VolumeSource{ - Secret: &core.SecretVolumeSource{ - SecretName: "caos", - }, - }, - }}, - TerminationGracePeriodSeconds: int64Ptr(10), - }, - }, - }, - } - - if err := client.ApplyDeployment(deployment, true); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": version, - }).Debug("Boom deployment ensured") - - if err := client.ApplyService(&core.Service{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sPodSelector, - }, - Spec: core.ServiceSpec{ - Ports: []core.ServicePort{{ - Name: "metrics", - Protocol: "TCP", - Port: 2112, - TargetPort: intstr.FromInt(2112), - }}, - Selector: k8sPodSelector, - Type: core.ServiceTypeClusterIP, - }, - }); err != nil { - return err - } - monitor.Debug("Boom service ensured") - return nil } @@ -348,140 +49,6 @@ func toNameLabels(apiLabels *labels.API, operatorName string) *labels.Name { return labels.MustForName(labels.MustForComponent(apiLabels, "operator"), operatorName) } -func EnsureOrbiterArtifacts( - monitor mntr.Monitor, - apiLabels *labels.API, - client *Client, - orbiterversion string, - imageRegistry string) error { - - monitor.WithFields(map[string]interface{}{ - "orbiter": orbiterversion, - }).Debug("Ensuring orbiter artifacts") - - if orbiterversion == "" { - return nil - } - - nameLabels := toNameLabels(apiLabels, "orbiter") - k8sNameLabels := labels.MustK8sMap(nameLabels) - k8sPodSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) - - deployment := &apps.Deployment{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sNameLabels, - }, - Spec: apps.DeploymentSpec{ - Replicas: int32Ptr(1), - Selector: &mach.LabelSelector{ - MatchLabels: k8sPodSelector, - }, - Template: core.PodTemplateSpec{ - ObjectMeta: mach.ObjectMeta{ - Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), - }, - Spec: core.PodSpec{ - Containers: []core.Container{{ - Name: "orbiter", - ImagePullPolicy: core.PullIfNotPresent, - Image: fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, orbiterversion), - Command: []string{"/orbctl", "--orbconfig", "/etc/orbiter/orbconfig", "takeoff", "orbiter", "--recur", "--ingestion="}, - VolumeMounts: []core.VolumeMount{{ - Name: "keys", - ReadOnly: true, - MountPath: "/etc/orbiter", - }}, - Ports: []core.ContainerPort{{ - Name: "metrics", - ContainerPort: 9000, - }}, - Resources: core.ResourceRequirements{ - Limits: core.ResourceList{ - "cpu": resource.MustParse("500m"), - "memory": resource.MustParse("500Mi"), - }, - Requests: core.ResourceList{ - "cpu": resource.MustParse("250m"), - "memory": resource.MustParse("250Mi"), - }, - }, - }}, - Volumes: []core.Volume{{ - Name: "keys", - VolumeSource: core.VolumeSource{ - Secret: &core.SecretVolumeSource{ - SecretName: "caos", - Optional: boolPtr(false), - }, - }, - }}, - Tolerations: []core.Toleration{{ - Key: "node-role.kubernetes.io/master", - Effect: "NoSchedule", - Operator: "Exists", - }}, - }, - }, - }, - } - - if err := client.ApplyDeployment(deployment, true); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": orbiterversion, - }).Debug("Orbiter deployment ensured") - - if err := client.ApplyService(&core.Service{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: "caos-system", - Labels: k8sPodSelector, - }, - Spec: core.ServiceSpec{ - Ports: []core.ServicePort{{ - Name: "metrics", - Protocol: "TCP", - Port: 9000, - TargetPort: intstr.FromInt(9000), - }}, - Selector: k8sPodSelector, - Type: core.ServiceTypeClusterIP, - }, - }); err != nil { - return err - } - monitor.Debug("Orbiter service ensured") - - patch := ` -{ - "spec": { - "template": { - "spec": { - "affinity": { - "podAntiAffinity": { - "preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 100, - "podAffinityTerm": { - "topologyKey": "kubernetes.io/hostname" - } - }] - } - } - } - } - } -}` - if err := client.PatchDeployment("kube-system", "coredns", patch); err != nil { - return err - } - - monitor.Debug("CoreDNS deployment patched") - return nil -} - func int32Ptr(i int32) *int32 { return &i } func int64Ptr(i int64) *int64 { return &i } func boolPtr(b bool) *bool { return &b } diff --git a/pkg/kubernetes/boom.go b/pkg/kubernetes/boom.go new file mode 100644 index 000000000..1852d2bfe --- /dev/null +++ b/pkg/kubernetes/boom.go @@ -0,0 +1,249 @@ +package kubernetes + +import ( + "fmt" + + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes/k8s" + "github.com/caos/orbos/pkg/labels" + "gopkg.in/yaml.v3" + apps "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + mach "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func EnsureBoomArtifacts( + monitor mntr.Monitor, + apiLabels *labels.API, + client ClientInt, + version string, + tolerations k8s.Tolerations, + nodeselector map[string]string, + resources *k8s.Resources, + imageRegistry string, + gitops bool, +) error { + + monitor.WithFields(map[string]interface{}{ + "boom": version, + }).Debug("Ensuring boom artifacts") + + if version == "" { + return nil + } + + nameLabels := toNameLabels(apiLabels, "boom") + k8sNameLabels := labels.MustK8sMap(nameLabels) + + if err := client.ApplyServiceAccount(&core.ServiceAccount{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sNameLabels, + }, + }); err != nil { + return err + } + + if err := client.ApplyClusterRole(&rbac.ClusterRole{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Labels: k8sNameLabels, + }, + Rules: []rbac.PolicyRule{{ + APIGroups: []string{"*"}, + Resources: []string{"*"}, + Verbs: []string{"*"}, + }}, + }); err != nil { + return err + } + + if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Labels: k8sNameLabels, + }, + + RoleRef: rbac.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: nameLabels.Name(), + }, + Subjects: []rbac.Subject{{ + Kind: "ServiceAccount", + Name: nameLabels.Name(), + Namespace: "caos-system", + }}, + }); err != nil { + return err + } + + k8sPodSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) + + if !gitops { + crd := `apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.2 + creationTimestamp: null + name: booms.caos.ch +spec: + group: caos.ch + names: + kind: Boom + listKind: BoomList + plural: booms + singular: boom + scope: "" + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + type: object + status: + type: object + type: object + version: v1 + versions: + - name: v1 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + - name: v1beta2 + served: true + storage: false +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: []` + + crdDefinition := &unstructured.Unstructured{} + if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil { + return err + } + + if err := client.ApplyCRDResource( + crdDefinition, + ); err != nil { + return err + } + monitor.WithFields(map[string]interface{}{ + "version": version, + }).Debug("BOOM crd ensured") + } + + var ( + cmd = []string{"/orbctl", "takeoff", "boom"} + volumes []core.Volume + volumeMounts []core.VolumeMount + ) + if gitops { + cmd = append(cmd, "--gitops", "-f", "/secrets/orbconfig") + volumes = []core.Volume{{ + Name: "orbconfig", + VolumeSource: core.VolumeSource{ + Secret: &core.SecretVolumeSource{ + SecretName: "caos", + }, + }, + }} + volumeMounts = []core.VolumeMount{{ + Name: "orbconfig", + ReadOnly: true, + MountPath: "/secrets", + }} + } else { + cmd = append(cmd, "--kubeconfig", "") + } + + deployment := &apps.Deployment{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sNameLabels, + }, + Spec: apps.DeploymentSpec{ + Replicas: int32Ptr(1), + Selector: &mach.LabelSelector{ + MatchLabels: k8sPodSelector, + }, + Template: core.PodTemplateSpec{ + ObjectMeta: mach.ObjectMeta{ + Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), + }, + Spec: core.PodSpec{ + ServiceAccountName: nameLabels.Name(), + Containers: []core.Container{{ + Name: "boom", + ImagePullPolicy: core.PullIfNotPresent, + Image: fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, version), + Command: cmd, + Args: []string{}, + Ports: []core.ContainerPort{{ + Name: "metrics", + ContainerPort: 2112, + Protocol: "TCP", + }}, + VolumeMounts: volumeMounts, + Resources: core.ResourceRequirements(*resources), + }}, + NodeSelector: nodeselector, + Tolerations: tolerations.K8s(), + Volumes: volumes, + TerminationGracePeriodSeconds: int64Ptr(10), + }, + }, + }, + } + + if err := client.ApplyDeployment(deployment, true); err != nil { + return err + } + monitor.WithFields(map[string]interface{}{ + "version": version, + }).Debug("BOOM deployment ensured") + + if err := client.ApplyService(&core.Service{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sPodSelector, + }, + Spec: core.ServiceSpec{ + Ports: []core.ServicePort{{ + Name: "metrics", + Protocol: "TCP", + Port: 2112, + TargetPort: intstr.FromInt(2112), + }}, + Selector: k8sPodSelector, + Type: core.ServiceTypeClusterIP, + }, + }); err != nil { + return err + } + monitor.Debug("BOOM service ensured") + + return nil +} diff --git a/pkg/kubernetes/cli/client.go b/pkg/kubernetes/cli/client.go new file mode 100644 index 000000000..05ebf3f46 --- /dev/null +++ b/pkg/kubernetes/cli/client.go @@ -0,0 +1,90 @@ +package cli + +import ( + "fmt" + "io/ioutil" + "strings" + + "github.com/caos/orbos/internal/api" + orb2 "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" + "github.com/caos/orbos/internal/secret/operators" + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/pkg/secret" + "github.com/pkg/errors" +) + +func Client( + monitor mntr.Monitor, + orbConfig *orb.Orb, + gitClient *git.Client, + kubeconfig string, + gitops bool, +) (k8sClient *kubernetes.Client, fromOrbiter bool, err error) { + + orbConfigIsIncompleteErr := orb.IsComplete(orbConfig) + if orbConfigIsIncompleteErr != nil && gitops { + return nil, fromOrbiter, orbConfigIsIncompleteErr + } + + var kc string + if orbConfigIsIncompleteErr == nil && gitops { + if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { + return k8sClient, fromOrbiter, err + } + + if err := gitClient.Clone(); err != nil { + return k8sClient, fromOrbiter, err + } + var err error + fromOrbiter, err = api.ExistsOrbiterYml(gitClient) + if err != nil { + return k8sClient, fromOrbiter, err + } + + if fromOrbiter { + orbTree, err := api.ReadOrbiterYml(gitClient) + if err != nil { + return k8sClient, fromOrbiter, errors.New("failed to parse orbiter.yml") + } + + orbDef, err := orb2.ParseDesiredV0(orbTree) + if err != nil { + return k8sClient, fromOrbiter, errors.New("failed to parse orbiter.yml") + } + + for clustername, _ := range orbDef.Clusters { + path := strings.Join([]string{"orbiter", clustername, "kubeconfig", "encrypted"}, ".") + + kc, err = secret.Read( + nil, + path, + operators.GetAllSecretsFunc(monitor, false, gitops, gitClient, nil, orbConfig), + ) + if err != nil || kc == "" { + if kc == "" && err == nil { + err = errors.New("no kubeconfig found") + } + return nil, fromOrbiter, fmt.Errorf("failed to get kubeconfig: %w", err) + } + } + } + } + + if kc == "" { + value, err := ioutil.ReadFile(kubeconfig) + if err != nil { + return k8sClient, fromOrbiter, err + } + kc = string(value) + } + + k8sClient = kubernetes.NewK8sClient(monitor, &kc) + if !k8sClient.Available() { + return nil, fromOrbiter, errors.New("Kubernetes is not connectable") + } + + return k8sClient, fromOrbiter, nil +} diff --git a/pkg/kubernetes/client.go b/pkg/kubernetes/client.go index 0c26555a7..fd10dc67d 100644 --- a/pkg/kubernetes/client.go +++ b/pkg/kubernetes/client.go @@ -12,6 +12,8 @@ import ( "sync" "time" + extensions "k8s.io/api/extensions/v1beta1" + "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/kubernetes/drainreason" @@ -69,15 +71,16 @@ type ClientInt interface { GetJob(namespace, name string) (*batch.Job, error) ApplyJob(rsc *batch.Job) error + ApplyJobDryRun(rsc *batch.Job) error DeleteJob(namespace string, name string) error - WaitUntilJobCompleted(namespace string, name string, timeoutSeconds time.Duration) error + WaitUntilJobCompleted(namespace string, name string, timeout time.Duration) error ApplyServiceAccount(rsc *core.ServiceAccount) error DeleteServiceAccount(namespace, name string) error ApplyStatefulSet(rsc *apps.StatefulSet, force bool) error DeleteStatefulset(namespace, name string) error - WaitUntilStatefulsetIsReady(namespace string, name string, containerCheck, readyCheck bool, timeoutSeconds time.Duration) error + WaitUntilStatefulsetIsReady(namespace string, name string, containerCheck, readyCheck bool, timeout time.Duration) error ExecInPodWithOutput(namespace, name, container, command string) (string, error) ExecInPod(namespace, name, container, command string) error @@ -85,7 +88,7 @@ type ClientInt interface { ApplyDeployment(rsc *apps.Deployment, force bool) error DeleteDeployment(namespace, name string) error PatchDeployment(namespace, name string, data string) error - WaitUntilDeploymentReady(namespace string, name string, containerCheck, readyCheck bool, timeoutSeconds time.Duration) error + WaitUntilDeploymentReady(namespace string, name string, containerCheck, readyCheck bool, timeout time.Duration) error ScaleDeployment(namespace, name string, replicaCount int) error ExecInPodOfDeployment(namespace, name, container, command string) error @@ -93,19 +96,22 @@ type ClientInt interface { GetNamespacedCRDResource(group, version, kind, namespace, name string) (*unstructured.Unstructured, error) ApplyNamespacedCRDResource(group, version, kind, namespace, name string, crd *unstructured.Unstructured) error DeleteNamespacedCRDResource(group, version, kind, namespace, name string) error + ApplyCRDResource(crd *unstructured.Unstructured) error + DeleteCRDResource(group, version, kind, name string) error ApplyCronJob(rsc *v1beta1.CronJob) error DeleteCronJob(namespace string, name string) error ListSecrets(namespace string, labels map[string]string) (*core.SecretList, error) + GetSecret(namespace string, name string) (*core.Secret, error) ApplySecret(rsc *core.Secret) error DeleteSecret(namespace, name string) error - WaitForSecret(namespace string, name string, timeoutSeconds time.Duration) error + WaitForSecret(namespace string, name string, timeout time.Duration) error GetConfigMap(namespace, name string) (*core.ConfigMap, error) ApplyConfigmap(rsc *core.ConfigMap) error DeleteConfigmap(namespace, name string) error - WaitForConfigMap(namespace string, name string, timeoutSeconds time.Duration) error + WaitForConfigMap(namespace string, name string, timeout time.Duration) error ApplyRole(rsc *rbac.Role) error DeleteRole(namespace, name string) error @@ -113,6 +119,9 @@ type ClientInt interface { ApplyClusterRole(rsc *rbac.ClusterRole) error DeleteClusterRole(name string) error + ApplyIngress(rsc *extensions.Ingress) error + DeleteIngress(namespace, name string) error + ApplyRoleBinding(rsc *rbac.RoleBinding) error DeleteRoleBinding(namespace, name string) error @@ -142,7 +151,7 @@ type Client struct { func NewK8sClientWithPath(monitor mntr.Monitor, kubeconfigPath string) (*Client, error) { kubeconfigStr := "" if kubeconfigPath != "" { - value, err := ioutil.ReadFile(kubeconfigPath) + value, err := ioutil.ReadFile(helpers.PruneHome(kubeconfigPath)) if err != nil { monitor.Error(err) return nil, err @@ -162,8 +171,25 @@ func NewK8sClient(monitor mntr.Monitor, kubeconfig *string) *Client { return kc } +func NewK8sClientWithConfig(monitor mntr.Monitor, conf *rest.Config) *Client { + kc := &Client{monitor: monitor} + err := kc.RefreshConfig(conf) + if err != nil { + // do nothing + } + return kc +} + func (c *Client) Available() bool { - return c.set != nil + nodeApi, err := c.nodeApi() + if err != nil { + return false + } + + ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) + defer cancel() + _, err = nodeApi.List(ctx, mach.ListOptions{}) + return err == nil } func (c *Client) nodeApi() (clgocore.NodeInterface, error) { @@ -271,7 +297,7 @@ func (c *Client) PatchDeployment(namespace, name string, data string) error { return err } -func (c *Client) WaitUntilDeploymentReady(namespace string, name string, containerCheck, readyCheck bool, timeoutSeconds time.Duration) error { +func (c *Client) WaitUntilDeploymentReady(namespace string, name string, containerCheck, readyCheck bool, timeout time.Duration) error { returnChannel := make(chan error, 1) go func() { ctx := context.Background() @@ -299,7 +325,7 @@ func (c *Client) WaitUntilDeploymentReady(namespace string, name string, contain select { case res := <-returnChannel: return res - case <-time.After(timeoutSeconds * time.Second): + case <-time.After(timeout): return errors.New("timeout while waiting for deployment to be ready") } } @@ -329,6 +355,32 @@ func (c *Client) GetJob(namespace, name string) (*batch.Job, error) { return c.set.BatchV1().Jobs(namespace).Get(context.Background(), name, mach.GetOptions{}) } +func (c *Client) ApplyJobDryRun(rsc *batch.Job) error { + resources := c.set.BatchV1().Jobs(rsc.Namespace) + return c.applyResource("job", rsc.GetName(), func() error { + res, err := resources.Create(context.Background(), rsc, mach.CreateOptions{DryRun: []string{mach.DryRunAll}}) + if err != nil { + return err + } + *rsc = *res + return nil + }, func() error { + j, err := resources.Get(context.Background(), rsc.GetName(), mach.GetOptions{}) + if err != nil { + return err + } + if j.GetName() == rsc.GetName() && j.GetNamespace() == rsc.GetNamespace() { + res, err := resources.Update(context.Background(), rsc, mach.UpdateOptions{DryRun: []string{mach.DryRunAll}}) + if err != nil { + return err + } + *rsc = *res + return nil + } + return nil + }) +} + func (c *Client) ApplyJob(rsc *batch.Job) error { resources := c.set.BatchV1().Jobs(rsc.Namespace) return c.applyResource("job", rsc.GetName(), func() error { @@ -347,7 +399,7 @@ func (c *Client) ApplyJob(rsc *batch.Job) error { }) } -func (c *Client) WaitUntilJobCompleted(namespace string, name string, timeoutSeconds time.Duration) error { +func (c *Client) WaitUntilJobCompleted(namespace string, name string, timeout time.Duration) error { returnChannel := make(chan error, 1) go func() { ctx := context.Background() @@ -357,6 +409,11 @@ func (c *Client) WaitUntilJobCompleted(namespace string, name string, timeoutSec return } + if job.Status.Succeeded > 0 { + returnChannel <- nil + return + } + labelSelector := getLabelSelector(job.Spec.Selector.MatchLabels) watch, err := c.set.CoreV1().Pods(namespace).Watch(ctx, mach.ListOptions{ @@ -374,18 +431,8 @@ func (c *Client) WaitUntilJobCompleted(namespace string, name string, timeoutSec select { case res := <-returnChannel: return res - case <-time.After(timeoutSeconds * time.Second): - ctx := context.Background() - job, err := c.set.BatchV1().Jobs(namespace).Get(ctx, name, mach.GetOptions{}) - if err != nil { - return errors.New("timeout while waiting for job to complete, no job found") - } - - if job.Status.Succeeded > 0 { - c.monitor.Debug("no pods found for job, but job succeeded, so ignoring the timeout") - return nil - } - return errors.New("timeout while waiting for job to complete") + case <-time.After(timeout): + return fmt.Errorf("timeout after %s while waiting for job to complete", timeout) } } @@ -494,7 +541,7 @@ func (c *Client) DeleteStatefulset(namespace, name string) error { return c.set.AppsV1().StatefulSets(namespace).Delete(context.Background(), name, mach.DeleteOptions{}) } -func (c *Client) WaitUntilStatefulsetIsReady(namespace string, name string, containerCheck, readyCheck bool, timeoutSeconds time.Duration) error { +func (c *Client) WaitUntilStatefulsetIsReady(namespace string, name string, containerCheck, readyCheck bool, timeout time.Duration) error { returnChannel := make(chan error, 1) go func() { ctx := context.Background() @@ -522,7 +569,7 @@ func (c *Client) WaitUntilStatefulsetIsReady(namespace string, name string, cont select { case res := <-returnChannel: return res - case <-time.After(timeoutSeconds * time.Second): + case <-time.After(timeout): return errors.New("timeout while waiting for job to complete") } } @@ -537,29 +584,38 @@ func (c *Client) ApplySecret(rsc *core.Secret) error { return err }) } +func (c *Client) GetSecret(namespace string, name string) (*core.Secret, error) { + return c.set.CoreV1().Secrets(namespace).Get(context.Background(), name, mach.GetOptions{}) +} -func (c *Client) WaitForSecret(namespace string, name string, timeoutSeconds time.Duration) error { - returnChannel := make(chan error, 1) - go func() { - ctx := context.Background() - for i := 0; i < int(timeoutSeconds); i++ { - secret, err := c.set.CoreV1().Secrets(namespace).Get(ctx, name, mach.GetOptions{}) +func (c *Client) WaitForSecret(namespace string, name string, timeout time.Duration) error { + ctx := context.Background() + return await( + timeout, + func() (interface{}, error) { + return c.set.CoreV1().Secrets(namespace).Get(ctx, name, mach.GetOptions{}) + }, + ) +} + +func await(timeout time.Duration, getResource func() (interface{}, error)) error { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + timer := time.NewTimer(timeout) + defer timer.Stop() + for { + select { + case <-ticker.C: + resource, err := getResource() if err != nil && !macherrs.IsNotFound(err) { - returnChannel <- err - return - } else if secret != nil { - returnChannel <- nil - return + return err + } else if resource != nil { + return nil } - time.Sleep(1) - } - }() - select { - case res := <-returnChannel: - return res - case <-time.After(timeoutSeconds * time.Second): - return errors.New("timeout while waiting for secret to be created") + case <-timer.C: + return errors.New("timeout while waiting for secret to be created") + } } } @@ -586,31 +642,6 @@ func (c *Client) DeleteConfigmap(namespace, name string) error { return c.set.CoreV1().ConfigMaps(namespace).Delete(context.Background(), name, mach.DeleteOptions{}) } -func (c *Client) WaitForConfigMap(namespace string, name string, timeoutSeconds time.Duration) error { - returnChannel := make(chan error, 1) - go func() { - ctx := context.Background() - for i := 0; i < int(timeoutSeconds); i++ { - secret, err := c.set.CoreV1().ConfigMaps(namespace).Get(ctx, name, mach.GetOptions{}) - if err != nil && !macherrs.IsNotFound(err) { - returnChannel <- err - return - } else if secret != nil { - returnChannel <- nil - return - } - time.Sleep(1) - } - }() - - select { - case res := <-returnChannel: - return res - case <-time.After(timeoutSeconds * time.Second): - return errors.New("timeout while waiting for configmap to be created") - } -} - func (c *Client) ApplyServiceAccount(rsc *core.ServiceAccount) error { resources := c.set.CoreV1().ServiceAccounts(rsc.Namespace) return c.applyResource("serviceaccount", rsc.GetName(), func() error { @@ -641,10 +672,40 @@ func (c *Client) ApplyServiceAccount(rsc *core.ServiceAccount) error { }) } +func (c *Client) WaitForConfigMap(namespace string, name string, timeout time.Duration) error { + ctx := context.Background() + return await( + timeout, + func() (interface{}, error) { + return c.set.CoreV1().ConfigMaps(namespace).Get(ctx, name, mach.GetOptions{}) + }, + ) +} + func (c *Client) DeleteServiceAccount(namespace, name string) error { return c.set.CoreV1().ServiceAccounts(namespace).Delete(context.Background(), name, mach.DeleteOptions{}) } +func (c *Client) ApplyIngress(rsc *extensions.Ingress) error { + resources := c.set.ExtensionsV1beta1().Ingresses(rsc.GetNamespace()) + return c.applyResource("ingress", rsc.GetName(), func() error { + _, err := resources.Create(context.Background(), rsc, mach.CreateOptions{}) + return err + }, func() error { + svc, err := resources.Get(context.Background(), rsc.Name, mach.GetOptions{}) + if err != nil { + return err + } + rsc.ObjectMeta.ResourceVersion = svc.ObjectMeta.ResourceVersion + _, err = resources.Update(context.Background(), rsc, mach.UpdateOptions{}) + return err + }) +} + +func (c *Client) DeleteIngress(namespace, name string) error { + return c.set.ExtensionsV1beta1().Ingresses(namespace).Delete(context.Background(), name, mach.DeleteOptions{}) +} + func (c *Client) ApplyRole(rsc *rbac.Role) error { resources := c.set.RbacV1().Roles(rsc.Namespace) return c.applyResource("role", rsc.GetName(), func() error { @@ -1229,7 +1290,6 @@ func checkReady(containers []containerStatus) bool { func (c *Client) CheckCRD(name string) (*apixv1beta1.CustomResourceDefinition, error) { crds := c.apixv1beta1client.CustomResourceDefinitions() - return crds.Get(context.Background(), name, mach.GetOptions{}) } @@ -1245,6 +1305,7 @@ func (c *Client) GetNamespacedCRDResource(group, version, kind, namespace, name return resource.Get(context.Background(), name, mach.GetOptions{}) } + func (c *Client) ApplyNamespacedCRDResource(group, version, kind, namespace, name string, crd *unstructured.Unstructured) error { mapping, err := c.mapper.RESTMapping(schema.GroupKind{ Group: group, @@ -1288,6 +1349,51 @@ func (c *Client) DeleteNamespacedCRDResource(group, version, kind, namespace, na return c.dynamic.Resource(mapping.Resource).Namespace(namespace).Delete(context.Background(), name, mach.DeleteOptions{}) } +func (c *Client) ApplyCRDResource(crd *unstructured.Unstructured) error { + kind := crd.Object["kind"].(string) + apiVersion := strings.Split(crd.Object["apiVersion"].(string), "/") + metadata := crd.Object["metadata"].(map[string]interface{}) + name := metadata["name"].(string) + + mapping, err := c.mapper.RESTMapping(schema.GroupKind{ + Group: apiVersion[0], + Kind: kind, + }, apiVersion[1]) + if err != nil { + return err + } + + resources := c.dynamic.Resource(mapping.Resource) + existing, err := resources.Get(context.Background(), name, mach.GetOptions{}) + if err != nil && !macherrs.IsNotFound(err) { + return errors.Wrapf(err, "getting existing crd %s of kind %s failed", name, kind) + } + if err == nil { + crd.SetResourceVersion(existing.GetResourceVersion()) + } + err = nil + + return c.applyResource("crd", name, func() error { + _, err := resources.Create(context.Background(), crd, mach.CreateOptions{}) + return err + }, func() error { + _, err := resources.Update(context.Background(), crd, mach.UpdateOptions{}) + return err + }) +} + +func (c *Client) DeleteCRDResource(group, version, kind, name string) error { + mapping, err := c.mapper.RESTMapping(schema.GroupKind{ + Group: group, + Kind: kind, + }, version) + if err != nil { + return err + } + + return c.dynamic.Resource(mapping.Resource).Delete(context.Background(), name, mach.DeleteOptions{}) +} + func (c *Client) ExecInPodOfDeployment(namespace, name, container, command string) error { cmd := []string{ "sh", diff --git a/pkg/kubernetes/crds.go b/pkg/kubernetes/crds.go new file mode 100644 index 000000000..da00bad0d --- /dev/null +++ b/pkg/kubernetes/crds.go @@ -0,0 +1,190 @@ +package kubernetes + +import ( + "bytes" + "fmt" + "gopkg.in/yaml.v3" + "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/controller-tools/pkg/crd" + "sigs.k8s.io/controller-tools/pkg/deepcopy" + "sigs.k8s.io/controller-tools/pkg/genall" + "sigs.k8s.io/controller-tools/pkg/loader" + "sigs.k8s.io/controller-tools/pkg/markers" + "strings" +) + +var ( + buffer = bytes.Buffer{} + + allGenerators = map[string]genall.Generator{ + "crd": crd.Generator{}, + "object": deepcopy.Generator{}, + } + + allOutputRules = map[string]genall.OutputRule{ + "dir": genall.OutputToDirectory(""), + "none": genall.OutputToNothing, + "stdout": genall.OutputToStdout, + "buffer": outputToBuffer{}, + "artifacts": genall.OutputArtifacts{}, + } + + optionsRegistry = &markers.Registry{} +) + +func getYamlsFromBuffer() []string { + yamls := strings.Split(buffer.String(), "---") + buffer.Reset() + return yamls +} + +func GetCRDs(boilerplatePath, path string) ([]string, error) { + if err := generateDeepCopy(boilerplatePath, path); err != nil { + return nil, err + } + + if err := generateCrd(path); err != nil { + return nil, err + } + + return getYamlsFromBuffer(), nil +} + +func WriteCRDs(boilerplatePath, path, destinationFolder string) error { + if err := generateDeepCopy(boilerplatePath, path); err != nil { + return err + } + + return generateCrdToFolder(path, destinationFolder) +} + +func ApplyCRDs(boilerplatePath, path string, k8sClient ClientInt) error { + if err := generateDeepCopy(boilerplatePath, path); err != nil { + return err + } + + if err := generateCrd(path); err != nil { + return err + } + + for _, crd := range getYamlsFromBuffer() { + if crd == "" || crd == "\n" { + continue + } + + //crdDefinition := apixv1beta1.CustomResourceDefinition{} + crdDefinition := &unstructured.Unstructured{} + if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil { + return err + } + + if err := k8sClient.ApplyCRDResource( + crdDefinition, + ); err != nil { + return err + } + } + return nil +} + +type outputToBuffer struct{} + +func (o outputToBuffer) Open(_ *loader.Package, itemPath string) (io.WriteCloser, error) { + return nopCloser{&buffer}, nil +} + +type nopCloser struct { + io.Writer +} + +func (n nopCloser) Close() error { + return nil +} + +func init() { + for genName, gen := range allGenerators { + // make the generator options marker itself + defn := markers.Must(markers.MakeDefinition(genName, markers.DescribesPackage, gen)) + if err := optionsRegistry.Register(defn); err != nil { + panic(err) + } + if helpGiver, hasHelp := gen.(genall.HasHelp); hasHelp { + if help := helpGiver.Help(); help != nil { + optionsRegistry.AddHelp(defn, help) + } + } + + // make per-generation output rule markers + for ruleName, rule := range allOutputRules { + ruleMarker := markers.Must(markers.MakeDefinition(fmt.Sprintf("output:%s:%s", genName, ruleName), markers.DescribesPackage, rule)) + if err := optionsRegistry.Register(ruleMarker); err != nil { + panic(err) + } + if helpGiver, hasHelp := rule.(genall.HasHelp); hasHelp { + if help := helpGiver.Help(); help != nil { + optionsRegistry.AddHelp(ruleMarker, help) + } + } + } + } + + // make "default output" output rule markers + for ruleName, rule := range allOutputRules { + ruleMarker := markers.Must(markers.MakeDefinition("output:"+ruleName, markers.DescribesPackage, rule)) + if err := optionsRegistry.Register(ruleMarker); err != nil { + panic(err) + } + if helpGiver, hasHelp := rule.(genall.HasHelp); hasHelp { + if help := helpGiver.Help(); help != nil { + optionsRegistry.AddHelp(ruleMarker, help) + } + } + } + + // add in the common options markers + if err := genall.RegisterOptionsMarkers(optionsRegistry); err != nil { + panic(err) + } +} + +func generate(rawOpts []string) error { + rt, err := genall.FromOptions(optionsRegistry, rawOpts) + if err != nil { + panic(err) + } + if len(rt.Generators) == 0 { + return fmt.Errorf("no generators specified") + } + + if hadErrs := rt.Run(); hadErrs { + return fmt.Errorf("not all generators ran successfully") + } + + return nil +} + +func generateDeepCopy(boilerplatePath, path string) error { + return generate([]string{ + "object:headerFile=\"" + boilerplatePath + "\"", + "paths=\"" + path + "\"", + }) +} + +func generateCrd(path string) error { + return generate([]string{ + "crd:trivialVersions=true", + "crd", + "paths=\"" + path + "\"", + "output:crd:buffer", + }) +} + +func generateCrdToFolder(path, folder string) error { + return generate([]string{ + "crd:trivialVersions=true", + "crd", + "paths=\"" + path + "\"", + "output:crd:artifacts:config=\"" + folder + "\"", + }) +} diff --git a/pkg/kubernetes/mock/client.mock.go b/pkg/kubernetes/mock/client.mock.go index 54bfb7b42..40ba1a6b9 100644 --- a/pkg/kubernetes/mock/client.mock.go +++ b/pkg/kubernetes/mock/client.mock.go @@ -11,9 +11,10 @@ import ( v10 "k8s.io/api/batch/v1" v1beta1 "k8s.io/api/batch/v1beta1" v11 "k8s.io/api/core/v1" - v1beta10 "k8s.io/api/policy/v1beta1" + v1beta10 "k8s.io/api/extensions/v1beta1" + v1beta11 "k8s.io/api/policy/v1beta1" v12 "k8s.io/api/rbac/v1" - v1beta11 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + v1beta12 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" reflect "reflect" time "time" @@ -137,6 +138,20 @@ func (mr *MockClientIntMockRecorder) ApplyJob(rsc interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyJob", reflect.TypeOf((*MockClientInt)(nil).ApplyJob), rsc) } +// ApplyJobDryRun mocks base method +func (m *MockClientInt) ApplyJobDryRun(rsc *v10.Job) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ApplyJobDryRun", rsc) + ret0, _ := ret[0].(error) + return ret0 +} + +// ApplyJobDryRun indicates an expected call of ApplyJobDryRun +func (mr *MockClientIntMockRecorder) ApplyJobDryRun(rsc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyJobDryRun", reflect.TypeOf((*MockClientInt)(nil).ApplyJobDryRun), rsc) +} + // DeleteJob mocks base method func (m *MockClientInt) DeleteJob(namespace, name string) error { m.ctrl.T.Helper() @@ -349,10 +364,10 @@ func (mr *MockClientIntMockRecorder) ExecInPodOfDeployment(namespace, name, cont } // CheckCRD mocks base method -func (m *MockClientInt) CheckCRD(name string) (*v1beta11.CustomResourceDefinition, error) { +func (m *MockClientInt) CheckCRD(name string) (*v1beta12.CustomResourceDefinition, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CheckCRD", name) - ret0, _ := ret[0].(*v1beta11.CustomResourceDefinition) + ret0, _ := ret[0].(*v1beta12.CustomResourceDefinition) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -406,6 +421,34 @@ func (mr *MockClientIntMockRecorder) DeleteNamespacedCRDResource(group, version, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNamespacedCRDResource", reflect.TypeOf((*MockClientInt)(nil).DeleteNamespacedCRDResource), group, version, kind, namespace, name) } +// ApplyCRDResource mocks base method +func (m *MockClientInt) ApplyCRDResource(crd *unstructured.Unstructured) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ApplyCRDResource", crd) + ret0, _ := ret[0].(error) + return ret0 +} + +// ApplyCRDResource indicates an expected call of ApplyCRDResource +func (mr *MockClientIntMockRecorder) ApplyCRDResource(crd interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyCRDResource", reflect.TypeOf((*MockClientInt)(nil).ApplyCRDResource), crd) +} + +// DeleteCRDResource mocks base method +func (m *MockClientInt) DeleteCRDResource(group, version, kind, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteCRDResource", group, version, kind, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteCRDResource indicates an expected call of DeleteCRDResource +func (mr *MockClientIntMockRecorder) DeleteCRDResource(group, version, kind, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCRDResource", reflect.TypeOf((*MockClientInt)(nil).DeleteCRDResource), group, version, kind, name) +} + // ApplyCronJob mocks base method func (m *MockClientInt) ApplyCronJob(rsc *v1beta1.CronJob) error { m.ctrl.T.Helper() @@ -449,6 +492,21 @@ func (mr *MockClientIntMockRecorder) ListSecrets(namespace, labels interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListSecrets", reflect.TypeOf((*MockClientInt)(nil).ListSecrets), namespace, labels) } +// GetSecret mocks base method +func (m *MockClientInt) GetSecret(namespace, name string) (*v11.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecret", namespace, name) + ret0, _ := ret[0].(*v11.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecret indicates an expected call of GetSecret +func (mr *MockClientIntMockRecorder) GetSecret(namespace, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecret", reflect.TypeOf((*MockClientInt)(nil).GetSecret), namespace, name) +} + // ApplySecret mocks base method func (m *MockClientInt) ApplySecret(rsc *v11.Secret) error { m.ctrl.T.Helper() @@ -604,6 +662,34 @@ func (mr *MockClientIntMockRecorder) DeleteClusterRole(name interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteClusterRole", reflect.TypeOf((*MockClientInt)(nil).DeleteClusterRole), name) } +// ApplyIngress mocks base method +func (m *MockClientInt) ApplyIngress(rsc *v1beta10.Ingress) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ApplyIngress", rsc) + ret0, _ := ret[0].(error) + return ret0 +} + +// ApplyIngress indicates an expected call of ApplyIngress +func (mr *MockClientIntMockRecorder) ApplyIngress(rsc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyIngress", reflect.TypeOf((*MockClientInt)(nil).ApplyIngress), rsc) +} + +// DeleteIngress mocks base method +func (m *MockClientInt) DeleteIngress(namespace, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteIngress", namespace, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteIngress indicates an expected call of DeleteIngress +func (mr *MockClientIntMockRecorder) DeleteIngress(namespace, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteIngress", reflect.TypeOf((*MockClientInt)(nil).DeleteIngress), namespace, name) +} + // ApplyRoleBinding mocks base method func (m *MockClientInt) ApplyRoleBinding(rsc *v12.RoleBinding) error { m.ctrl.T.Helper() @@ -661,7 +747,7 @@ func (mr *MockClientIntMockRecorder) DeleteClusterRoleBinding(name interface{}) } // ApplyPodDisruptionBudget mocks base method -func (m *MockClientInt) ApplyPodDisruptionBudget(rsc *v1beta10.PodDisruptionBudget) error { +func (m *MockClientInt) ApplyPodDisruptionBudget(rsc *v1beta11.PodDisruptionBudget) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ApplyPodDisruptionBudget", rsc) ret0, _ := ret[0].(error) diff --git a/pkg/kubernetes/networking.go b/pkg/kubernetes/networking.go new file mode 100644 index 000000000..16f766bd8 --- /dev/null +++ b/pkg/kubernetes/networking.go @@ -0,0 +1,299 @@ +package kubernetes + +import ( + "fmt" + + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/labels" + "gopkg.in/yaml.v3" + apps "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/resource" + mach "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func EnsureNetworkingArtifacts( + monitor mntr.Monitor, + apiLabels *labels.API, + client ClientInt, + version string, + nodeselector map[string]string, + tolerations []core.Toleration, + imageRegistry string, + gitops bool, +) error { + + monitor.WithFields(map[string]interface{}{ + "networking": version, + }).Debug("Ensuring networking artifacts") + + if version == "" { + return nil + } + + nameLabels := toNameLabels(apiLabels, "networking-operator") + k8sNameLabels := labels.MustK8sMap(nameLabels) + + if err := client.ApplyServiceAccount(&core.ServiceAccount{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sNameLabels, + }, + }); err != nil { + return err + } + + if err := client.ApplyClusterRole(&rbac.ClusterRole{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Labels: k8sNameLabels, + }, + Rules: []rbac.PolicyRule{{ + APIGroups: []string{"*"}, + Resources: []string{"*"}, + Verbs: []string{"*"}, + }}, + }); err != nil { + return err + } + + if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Labels: k8sNameLabels, + }, + + RoleRef: rbac.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: nameLabels.Name(), + }, + Subjects: []rbac.Subject{{ + Kind: "ServiceAccount", + Name: nameLabels.Name(), + Namespace: "caos-system", + }}, + }); err != nil { + return err + } + + if !gitops { + crd := `apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.2 + creationTimestamp: null + name: networkings.caos.ch +spec: + group: caos.ch + names: + kind: Networking + listKind: NetworkingList + plural: networkings + singular: networking + scope: "" + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + kind: + type: string + networking: + type: object + spec: + properties: + customImageRegistry: + description: 'Use this registry to pull the Networking-operator + image from @default: ghcr.io' + type: string + gitOps: + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + selfReconciling: + type: boolean + tolerations: + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using the + matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to + Equal. Exists is equivalent to wildcard for value, so that + a pod can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do + not evict). Zero and negative values will be treated as + 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + verbose: + type: boolean + version: + type: string + required: + - selfReconciling + - verbose + type: object + version: + type: string + required: + - kind + - networking + - spec + - version + type: object + status: + type: object + type: object + version: v1 + versions: + - name: v1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: []` + + crdDefinition := &unstructured.Unstructured{} + if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil { + return err + } + + if err := client.ApplyCRDResource( + crdDefinition, + ); err != nil { + return err + } + monitor.WithFields(map[string]interface{}{ + "version": version, + }).Debug("Networking Operator crd ensured") + } + + var ( + cmd = []string{"/orbctl", "takeoff", "networking"} + volumes []core.Volume + volumeMounts []core.VolumeMount + ) + if gitops { + cmd = append(cmd, "--gitops", "-f", "/secrets/orbconfig") + volumes = []core.Volume{{ + Name: "orbconfig", + VolumeSource: core.VolumeSource{ + Secret: &core.SecretVolumeSource{ + SecretName: "caos", + }, + }, + }} + volumeMounts = []core.VolumeMount{{ + Name: "orbconfig", + ReadOnly: true, + MountPath: "/secrets", + }} + } else { + cmd = append(cmd, "--kubeconfig", "") + } + + deployment := &apps.Deployment{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sNameLabels, + }, + Spec: apps.DeploymentSpec{ + Replicas: int32Ptr(1), + Selector: &mach.LabelSelector{ + MatchLabels: labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)), + }, + Template: core.PodTemplateSpec{ + ObjectMeta: mach.ObjectMeta{ + Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), + }, + Spec: core.PodSpec{ + ServiceAccountName: nameLabels.Name(), + Containers: []core.Container{{ + Name: "networking", + ImagePullPolicy: core.PullIfNotPresent, + Image: fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, version), + Command: cmd, + Args: []string{}, + Ports: []core.ContainerPort{{ + Name: "metrics", + ContainerPort: 2112, + Protocol: "TCP", + }}, + Resources: core.ResourceRequirements{ + Limits: core.ResourceList{ + "cpu": resource.MustParse("500m"), + "memory": resource.MustParse("500Mi"), + }, + Requests: core.ResourceList{ + "cpu": resource.MustParse("250m"), + "memory": resource.MustParse("250Mi"), + }, + }, + VolumeMounts: volumeMounts, + }}, + NodeSelector: nodeselector, + Tolerations: tolerations, + Volumes: volumes, + TerminationGracePeriodSeconds: int64Ptr(10), + }, + }, + }, + } + if err := client.ApplyDeployment(deployment, true); err != nil { + return err + } + monitor.WithFields(map[string]interface{}{ + "version": version, + }).Debug("Networking Operator deployment ensured") + + return nil +} diff --git a/pkg/kubernetes/orbiter.go b/pkg/kubernetes/orbiter.go new file mode 100644 index 000000000..4b31886bf --- /dev/null +++ b/pkg/kubernetes/orbiter.go @@ -0,0 +1,171 @@ +package kubernetes + +import ( + "fmt" + + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/labels" + apps "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + mach "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func EnsureOrbiterArtifacts( + monitor mntr.Monitor, + apiLabels *labels.API, + client *Client, + pprof bool, + orbiterversion string, + imageRegistry string) error { + + monitor.WithFields(map[string]interface{}{ + "orbiter": orbiterversion, + }).Debug("Ensuring orbiter artifacts") + + if orbiterversion == "" { + return nil + } + + nameLabels := toNameLabels(apiLabels, "orbiter") + k8sNameLabels := labels.MustK8sMap(nameLabels) + k8sPodSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) + + cmd := []string{"/orbctl", "--gitops", "--orbconfig", "/etc/orbiter/orbconfig", "takeoff", "orbiter", "--recur", "--ingestion="} + if pprof { + cmd = append(cmd, "--pprof") + } + + deployment := &apps.Deployment{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sNameLabels, + }, + Spec: apps.DeploymentSpec{ + Replicas: int32Ptr(1), + Selector: &mach.LabelSelector{ + MatchLabels: k8sPodSelector, + }, + Template: core.PodTemplateSpec{ + ObjectMeta: mach.ObjectMeta{ + Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), + }, + Spec: core.PodSpec{ + Containers: []core.Container{{ + Name: "orbiter", + ImagePullPolicy: core.PullIfNotPresent, + Image: fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, orbiterversion), + Command: cmd, + VolumeMounts: []core.VolumeMount{{ + Name: "keys", + ReadOnly: true, + MountPath: "/etc/orbiter", + }}, + Ports: []core.ContainerPort{{ + Name: "metrics", + ContainerPort: 9000, + }}, + Resources: core.ResourceRequirements{ + Limits: core.ResourceList{ + "cpu": resource.MustParse("500m"), + "memory": resource.MustParse("500Mi"), + }, + Requests: core.ResourceList{ + "cpu": resource.MustParse("250m"), + "memory": resource.MustParse("250Mi"), + }, + }, + LivenessProbe: &core.Probe{ + Handler: core.Handler{ + HTTPGet: &core.HTTPGetAction{ + Path: "/health", + Port: intstr.FromInt(9000), + Scheme: core.URISchemeHTTP, + HTTPHeaders: make([]core.HTTPHeader, 0, 0), + }, + }, + InitialDelaySeconds: 10, + TimeoutSeconds: 1, + PeriodSeconds: 20, + SuccessThreshold: 1, + FailureThreshold: 3 * 5, + }, + }}, + Volumes: []core.Volume{{ + Name: "keys", + VolumeSource: core.VolumeSource{ + Secret: &core.SecretVolumeSource{ + SecretName: "caos", + Optional: boolPtr(false), + }, + }, + }}, + NodeSelector: map[string]string{ + "node-role.kubernetes.io/master": "", + }, + Tolerations: []core.Toleration{{ + Key: "node-role.kubernetes.io/master", + Effect: "NoSchedule", + Operator: "Exists", + }}, + }, + }, + }, + } + + if err := client.ApplyDeployment(deployment, true); err != nil { + return err + } + monitor.WithFields(map[string]interface{}{ + "version": orbiterversion, + }).Debug("Orbiter deployment ensured") + + if err := client.ApplyService(&core.Service{ + ObjectMeta: mach.ObjectMeta{ + Name: nameLabels.Name(), + Namespace: "caos-system", + Labels: k8sPodSelector, + }, + Spec: core.ServiceSpec{ + Ports: []core.ServicePort{{ + Name: "metrics", + Protocol: "TCP", + Port: 9000, + TargetPort: intstr.FromInt(9000), + }}, + Selector: k8sPodSelector, + Type: core.ServiceTypeClusterIP, + }, + }); err != nil { + return err + } + monitor.Debug("Orbiter service ensured") + + patch := ` +{ + "spec": { + "template": { + "spec": { + "affinity": { + "podAntiAffinity": { + "preferredDuringSchedulingIgnoredDuringExecution": [{ + "weight": 100, + "podAffinityTerm": { + "topologyKey": "kubernetes.io/hostname" + } + }] + } + } + } + } + } +}` + if err := client.PatchDeployment("kube-system", "coredns", patch); err != nil { + return err + } + + monitor.Debug("CoreDNS deployment patched") + return nil +} diff --git a/pkg/kubernetes/resources/ambassador/host/adapt.go b/pkg/kubernetes/resources/ambassador/host/adapt.go index 3d27f180a..b84668206 100644 --- a/pkg/kubernetes/resources/ambassador/host/adapt.go +++ b/pkg/kubernetes/resources/ambassador/host/adapt.go @@ -41,7 +41,7 @@ func AdaptFuncToEnsure(namespace, name string, labels map[string]string, hostnam "spec": map[string]interface{}{ "hostname": hostname, "acmeProvider": acme, - "ambassadorId": []string{ + "ambassador_id": []string{ "default", }, "selector": map[string]interface{}{ diff --git a/pkg/kubernetes/resources/ambassador/mapping/adapt.go b/pkg/kubernetes/resources/ambassador/mapping/adapt.go index 203146fda..d7d72fcc0 100644 --- a/pkg/kubernetes/resources/ambassador/mapping/adapt.go +++ b/pkg/kubernetes/resources/ambassador/mapping/adapt.go @@ -1,13 +1,18 @@ package mapping import ( - "strconv" - "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/kubernetes/resources" + "github.com/caos/orbos/pkg/labels" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) +const ( + group = "getambassador.io" + version = "v2" + kind = "Mapping" +) + type CORS struct { Origins string Methods string @@ -17,13 +22,17 @@ type CORS struct { MaxAge string } -const ( - group = "getambassador.io" - version = "v2" - kind = "Mapping" -) - -func AdaptFuncToEnsure(namespace, name string, labels map[string]string, grpc bool, host, prefix, rewrite, service, timeoutMS, connectTimeoutMS string, cors *CORS) (resources.QueryFunc, error) { +func AdaptFuncToEnsure( + namespace string, + id labels.IDLabels, + grpc bool, + host, + prefix, + rewrite, + service string, + timeoutMS, + connectTimeoutMS int, + cors *CORS) (resources.QueryFunc, error) { spec := map[string]interface{}{ "host": host, @@ -34,23 +43,11 @@ func AdaptFuncToEnsure(namespace, name string, labels map[string]string, grpc bo spec["prefix"] = prefix } - if timeoutMS != "" { - toMSint, err := strconv.Atoi(timeoutMS) - if err != nil { - return nil, err - } - if timeoutMS != "" { - spec["timeout_ms"] = toMSint - } + if timeoutMS != 0 { + spec["timeout_ms"] = timeoutMS } - if connectTimeoutMS != "" { - ctoMSint, err := strconv.Atoi(connectTimeoutMS) - if err != nil { - return nil, err - } - if connectTimeoutMS != "" { - spec["connect_timeout_ms"] = ctoMSint - } + if connectTimeoutMS != 0 { + spec["connect_timeout_ms"] = connectTimeoutMS } if grpc { spec["grpc"] = grpc @@ -73,16 +70,16 @@ func AdaptFuncToEnsure(namespace, name string, labels map[string]string, grpc bo "kind": kind, "apiVersion": group + "/" + version, "metadata": map[string]interface{}{ - "name": name, + "name": id.Name(), "namespace": namespace, - "labels": labels, + "labels": labels.MustK8sMap(id), }, "spec": spec, }} return func(k8sClient kubernetes.ClientInt) (resources.EnsureFunc, error) { return func(k8sClient kubernetes.ClientInt) error { - return k8sClient.ApplyNamespacedCRDResource(group, version, kind, namespace, name, crd) + return k8sClient.ApplyNamespacedCRDResource(group, version, kind, namespace, id.Name(), crd) }, nil }, nil } diff --git a/pkg/kubernetes/resources/ambassador/module/adapt.go b/pkg/kubernetes/resources/ambassador/module/adapt.go index cf9005dfa..e1a9d3439 100644 --- a/pkg/kubernetes/resources/ambassador/module/adapt.go +++ b/pkg/kubernetes/resources/ambassador/module/adapt.go @@ -1,7 +1,7 @@ package module import ( - kubernetes2 "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/kubernetes/resources" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -38,15 +38,15 @@ func AdaptFuncToEnsure(namespace, name string, labels map[string]string, config "spec": spec, }} - return func(k8sClient *kubernetes2.Client) (resources.EnsureFunc, error) { - return func(k8sClient *kubernetes2.Client) error { + return func(k8sClient kubernetes.ClientInt) (resources.EnsureFunc, error) { + return func(k8sClient kubernetes.ClientInt) error { return k8sClient.ApplyNamespacedCRDResource(group, version, kind, namespace, name, crd) }, nil }, nil } func AdaptFuncToDestroy(namespace, name string) (resources.DestroyFunc, error) { - return func(client *kubernetes2.Client) error { + return func(client kubernetes.ClientInt) error { return client.DeleteNamespacedCRDResource(group, version, kind, namespace, name) }, nil } diff --git a/pkg/kubernetes/resources/ingress/adapt.go b/pkg/kubernetes/resources/ingress/adapt.go new file mode 100644 index 000000000..5b9ca776c --- /dev/null +++ b/pkg/kubernetes/resources/ingress/adapt.go @@ -0,0 +1,59 @@ +package ingress + +import ( + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/kubernetes/resources" + "github.com/caos/orbos/pkg/labels" + "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func AdaptFuncToEnsure( + namespace string, + id labels.IDLabels, + host, + prefix, + service string, + servicePort uint16, + annotations map[string]string, +) (resources.QueryFunc, error) { + + ingress := &v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: id.Name(), + Namespace: namespace, + Labels: labels.MustK8sMap(id), + Annotations: annotations, + }, + Spec: v1beta1.IngressSpec{ + Rules: []v1beta1.IngressRule{{ + Host: host, + IngressRuleValue: v1beta1.IngressRuleValue{HTTP: &v1beta1.HTTPIngressRuleValue{Paths: []v1beta1.HTTPIngressPath{{ + Path: prefix, + PathType: pathTypePtr(v1beta1.PathTypePrefix), + Backend: v1beta1.IngressBackend{ + ServiceName: service, + ServicePort: intstr.FromInt(int(servicePort)), + Resource: nil, + }, + }}}}, + }}, + }, + } + return func(_ kubernetes.ClientInt) (resources.EnsureFunc, error) { + return func(k8sClient kubernetes.ClientInt) error { + return k8sClient.ApplyIngress(ingress) + }, nil + }, nil +} + +func pathTypePtr(pathType v1beta1.PathType) *v1beta1.PathType { + return &pathType +} + +func AdaptFuncToDestroy(namespace, name string) (resources.DestroyFunc, error) { + return func(k8sClient kubernetes.ClientInt) error { + return k8sClient.DeleteIngress(namespace, name) + }, nil +} diff --git a/pkg/kubernetes/resources/job/adapt.go b/pkg/kubernetes/resources/job/adapt.go index c32fe1583..139ee777b 100644 --- a/pkg/kubernetes/resources/job/adapt.go +++ b/pkg/kubernetes/resources/job/adapt.go @@ -1,12 +1,16 @@ package job import ( + "fmt" + "reflect" + "strings" + "time" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/kubernetes/resources" batch "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" macherrs "k8s.io/apimachinery/pkg/api/errors" - "reflect" - "time" ) func AdaptFuncToEnsure(job *batch.Job) (resources.QueryFunc, error) { @@ -21,45 +25,39 @@ func AdaptFuncToEnsure(job *batch.Job) (resources.QueryFunc, error) { }, nil } - //check if any immutable fields were changed - changedImmutable := false - if !reflect.DeepEqual(job.GetAnnotations(), jobDef.GetAnnotations()) { - changedImmutable = true + jobDry := *job + if job.Spec.Selector == nil { + jobDry.Spec.Selector = jobDef.Spec.Selector } - if job.Spec.Selector != nil && !reflect.DeepEqual(job.Spec.Selector, jobDef.Spec.Selector) { - changedImmutable = true + if job.Spec.Template.Labels == nil { + jobDry.Spec.Template.Labels = jobDef.Spec.Template.Labels } - if job.Spec.Template.ObjectMeta.Labels != nil && !reflect.DeepEqual(job.Spec.Template.ObjectMeta.Labels, jobDef.Spec.Template.ObjectMeta.Labels) { - changedImmutable = true + if err := k8sClient.ApplyJobDryRun(&jobDry); err != nil && !strings.Contains(err.Error(), "field is immutable") { + return nil, err } - if !reflect.DeepEqual(job.Spec.Template.Spec, jobDef.Spec.Template.Spec) && - //workaround as securitycontext is a pointer to ensure that it only triggers if the values are different - !reflect.DeepEqual(*job.Spec.Template.Spec.SecurityContext, *jobDef.Spec.Template.Spec.SecurityContext) { - changedImmutable = true + + if jobDef.Spec.Template.Spec.SecurityContext != nil && jobDry.Spec.Template.Spec.SecurityContext == nil { + jobDry.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{} } - if changedImmutable { + if reflect.DeepEqual(jobDry.Spec.Template.Spec, jobDef.Spec.Template.Spec) && + fmt.Sprint(jobDry.Labels) == fmt.Sprint(jobDef.Labels) && + fmt.Sprint(jobDry.Annotations) == fmt.Sprint(jobDef.Annotations) { return func(k8sClient kubernetes.ClientInt) error { + return nil + }, nil + } + + return func(k8sClient kubernetes.ClientInt) error { + if err := k8sClient.ApplyJob(job); err != nil && strings.Contains(err.Error(), "field is immutable") { if err := k8sClient.DeleteJob(job.GetNamespace(), job.GetName()); err != nil { return err } time.Sleep(1 * time.Second) return k8sClient.ApplyJob(job) - }, nil - } - - //check if selector or the labels are empty, as this have default values - if job.Spec.Selector == nil { - job.Spec.Selector = jobDef.Spec.Selector - } - if job.Spec.Template.ObjectMeta.Labels == nil { - job.Spec.Template.ObjectMeta.Labels = jobDef.Spec.Template.ObjectMeta.Labels - } - - return func(k8sClient kubernetes.ClientInt) error { - return k8sClient.ApplyJob(job) + } + return err }, nil - }, nil } diff --git a/pkg/kubernetes/resources/service/service.go b/pkg/kubernetes/resources/service/service.go index 037f21a3b..99eed7cc9 100644 --- a/pkg/kubernetes/resources/service/service.go +++ b/pkg/kubernetes/resources/service/service.go @@ -10,10 +10,10 @@ import ( ) type Port struct { - Port int + Port uint16 Protocol string TargetPort string - NodePort int + NodePort uint16 Name string } diff --git a/pkg/labels/mocklabels/mock.go b/pkg/labels/mocklabels/mock.go index 9e98deed6..26cf815a9 100644 --- a/pkg/labels/mocklabels/mock.go +++ b/pkg/labels/mocklabels/mock.go @@ -20,9 +20,9 @@ var ( selectableKey = "orbos.ch/selectable" selectableVal = "yes" - operator = labels.MustForOperator(productVal, operatorVal, operatorVersionVal) - api = labels.MustForAPI(operator, apiKindVal, apiVersionVal) - Component = labels.MustForComponent(api, componentVal) + Operator = labels.MustForOperator(productVal, operatorVal, operatorVersionVal) + Api = labels.MustForAPI(Operator, apiKindVal, apiVersionVal) + Component = labels.MustForComponent(Api, componentVal) Name = labels.MustForName(Component, NameVal) ClosedNameSelector = labels.DeriveNameSelector(Name, false) Selectable = labels.AsSelectable(Name) diff --git a/pkg/orb/orb.go b/pkg/orb/orb.go index e7a5b08af..946d6b0cc 100644 --- a/pkg/orb/orb.go +++ b/pkg/orb/orb.go @@ -1,18 +1,87 @@ package orb -import "github.com/caos/orbos/internal/orb" +import ( + "fmt" + "io/ioutil" + "os" -type Orb orb.Orb + secret2 "github.com/caos/orbos/pkg/secret" + + "github.com/caos/orbos/internal/helpers" + + "github.com/pkg/errors" + "gopkg.in/yaml.v3" +) + +type Orb struct { + Path string `yaml:"-"` + URL string + Repokey string + Masterkey string +} + +func (o *Orb) IsConnectable() (err error) { + defer func() { + if err != nil { + err = fmt.Errorf("repository is not connectable: %w", err) + } + }() + if o.URL == "" { + err = helpers.Concat(err, errors.New("repository url is missing")) + } + + if o.Repokey == "" { + err = helpers.Concat(err, errors.New("repository key is missing")) + } + return err +} + +func IsComplete(o *Orb) (err error) { + + defer func() { + if err != nil { + err = fmt.Errorf("orbconfig is incomplete: %w", err) + } + }() + + if o == nil { + return errors.New("path not provided") + } + + if o.Masterkey == "" { + err = helpers.Concat(err, errors.New("master key is missing")) + } + + if o.Path == "" { + err = helpers.Concat(err, errors.New("file path is missing")) + } + + return helpers.Concat(err, o.IsConnectable()) +} func ParseOrbConfig(orbConfigPath string) (*Orb, error) { - orbConfig, err := orb.ParseOrbConfig(orbConfigPath) + + gitOrbConfig, err := ioutil.ReadFile(orbConfigPath) + if err != nil { - return nil, err - } - return &Orb{ - Repokey: orbConfig.Repokey, - Masterkey: orbConfig.Masterkey, - URL: orbConfig.URL, - Path: orbConfig.Path, - }, nil + return nil, errors.Wrap(err, "unable to read orbconfig") + } + + orb := &Orb{} + if err := yaml.Unmarshal(gitOrbConfig, orb); err != nil { + return nil, errors.Wrap(err, "unable to parse orbconfig") + } + + orb.Path = orbConfigPath + secret2.Masterkey = orb.Masterkey + return orb, nil +} + +func (o *Orb) WriteBackOrbConfig() error { + data, err := yaml.Marshal(o) + if err != nil { + return err + } + + return ioutil.WriteFile(o.Path, data, os.ModePerm) } diff --git a/pkg/secret/rwsecret.go b/pkg/secret/rwsecret.go index ce7461060..4d85195ac 100644 --- a/pkg/secret/rwsecret.go +++ b/pkg/secret/rwsecret.go @@ -1,11 +1,17 @@ package secret import ( - "errors" "fmt" "sort" "strings" + v1 "k8s.io/api/core/v1" + mach "k8s.io/apimachinery/pkg/apis/meta/v1" + + macherrs "k8s.io/apimachinery/pkg/api/errors" + + "github.com/caos/orbos/pkg/kubernetes" + "github.com/AlecAivazis/survey/v2" "github.com/caos/orbos/internal/api" @@ -17,31 +23,76 @@ import ( ) type PushFunc func(gitClient *git.Client, desired *tree.Tree) api.PushDesiredFunc -type PushFuncs func(monitor mntr.Monitor, gitClient *git.Client, trees map[string]*tree.Tree, path string) error -type GetFuncs func(monitor mntr.Monitor, gitClient *git.Client) (map[string]*Secret, map[string]*tree.Tree, error) +type PushFuncs func(trees map[string]*tree.Tree, path string) error +type GetFuncs func() (map[string]*Secret, map[string]*Existing, map[string]*tree.Tree, error) + +func Read( + k8sClient kubernetes.ClientInt, + path string, + getFunc GetFuncs, +) ( + val string, + err error, +) { + + defer func() { + if err != nil { + err = fmt.Errorf("reading secret failed: %w", err) + } + }() -func Read(monitor mntr.Monitor, gitClient *git.Client, path string, getFunc GetFuncs) (string, error) { - allSecrets, _, err := getFunc(monitor, gitClient) + allSecrets, allExisting, _, err := getFunc() if err != nil { return "", err } - if allSecrets == nil || len(allSecrets) == 0 { - return "", errors.New("no secrets found") + if k8sClient == nil { + allExisting = make(map[string]*Existing) } - secret, err := findSecret(allSecrets, &path, false) + /* + if allSecrets == nil || len(allSecrets) == 0 { + return "", errors.New("no secrets found") + } + */ + + secret, err := findSecret(allSecrets, allExisting, &path, false) if err != nil { return "", err } - if secret.Value == "" { - return "", fmt.Errorf("Secret %s is empty", path) + switch secretType := secret.(type) { + case *Secret: + if secretType.Value == "" { + return "", fmt.Errorf("secret %s is empty", path) + } + return secretType.Value, nil + case *Existing: + if secretType.Name == "" { + return "", fmt.Errorf("secret %s has no name specified", path) + } + if secretType.Key == "" { + return "", fmt.Errorf("secret %s has no key specified", path) + } + k8sSecret, err := k8sClient.GetSecret(existingSecretsNamespace, secretType.Name) + if err != nil { + return "", err + } + bytes, ok := k8sSecret.Data[secretType.Key] + if !ok || len(bytes) == 0 { + return "", fmt.Errorf("Kubernetes secret is empty at key %s", secretType.Key) + } + return string(bytes), nil } - - return secret.Value, nil + panic(fmt.Errorf("unknown secret of type %T", secret)) } -func Rewrite(monitor mntr.Monitor, gitClient *git.Client, newMasterKey string, desired *tree.Tree, pushFunc PushFunc) error { +func Rewrite( + monitor mntr.Monitor, + gitClient *git.Client, + newMasterKey string, + desired *tree.Tree, + pushFunc PushFunc, +) error { oldMasterKey := Masterkey Masterkey = newMasterKey defer func() { @@ -51,38 +102,184 @@ func Rewrite(monitor mntr.Monitor, gitClient *git.Client, newMasterKey string, d return pushFunc(gitClient, desired)(monitor) } -func Write(monitor mntr.Monitor, gitClient *git.Client, path, value string, getFunc GetFuncs, pushFunc PushFuncs) error { - allSecrets, allTrees, err := getFunc(monitor, gitClient) +func Write( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + path, + value, + writtenByCLI, + writtenByVersion string, + getFunc GetFuncs, + pushFunc PushFuncs, +) error { + allSecrets, allExisting, allTrees, err := getFunc() + if err != nil { + return err + } + + if k8sClient == nil { + allExisting = make(map[string]*Existing) + } + + secret, err := findSecret(allSecrets, allExisting, &path, true) if err != nil { return err } - secret, err := findSecret(allSecrets, &path, true) + switch secretType := secret.(type) { + case *Secret: + if secretType.Value == value { + monitor.Info("Value is unchanged") + return nil + } + secretType.Value = value + case *Existing: + var refChanged bool + if secretType.Name == "" { + secretType.Name = strings.ReplaceAll(path, ".", "-") + refChanged = true + } + + if secretType.Key == "" { + secretType.Key = "default" + refChanged = true + } + + k8sSecret, err := k8sClient.GetSecret(existingSecretsNamespace, secretType.Name) + if macherrs.IsNotFound(err) { + err = nil + k8sSecret = &v1.Secret{ + ObjectMeta: mach.ObjectMeta{ + Name: secretType.Name, + Namespace: existingSecretsNamespace, + Labels: map[string]string{ + "cli": writtenByCLI, + "version": writtenByVersion, + }, + }, + Immutable: boolPtr(false), + Type: v1.SecretTypeOpaque, + } + } + if err != nil { + return err + } + + if k8sSecret.Data == nil { + k8sSecret.Data = make(map[string][]byte) + } + k8sSecret.Data[secretType.Key] = []byte(value) + if err := k8sClient.ApplySecret(k8sSecret); err != nil { + return err + } + if !refChanged { + return nil + } + } + + return pushFunc(allTrees, path) +} + +func GetOperatorSecrets( + monitor mntr.Monitor, + printLogs, + gitops bool, + allTrees map[string]*tree.Tree, + allSecrets map[string]*Secret, + allExistingSecrets map[string]*Existing, + operator string, + yamlExistsInGit func() (bool, error), + treeFromGit, + treeFromCRD func() (*tree.Tree, error), + getOperatorSpecifics func(*tree.Tree) (map[string]*Secret, map[string]*Existing, bool, error), +) error { + + if gitops { + foundGitYAML, err := yamlExistsInGit() + if err != nil { + return err + } + + if !foundGitYAML { + if printLogs { + monitor.Info(fmt.Sprintf("no file for %s found", operator)) + } + return nil + } + + operatorTree, err := treeFromGit() + if err != nil { + return err + } + allTrees[operator] = operatorTree + } else { + operatorTree, err := treeFromCRD() + if operatorTree == nil { + return err + } + allTrees[operator] = operatorTree + } + + secrets, existing, migrate, err := getOperatorSpecifics(allTrees[operator]) if err != nil { return err } - secret.Value = value + if migrate { + return fmt.Errorf("please use the api command to migrate to the latest %s api first", operator) + } + + if !gitops { + secrets = nil + } + + suffixedSecrets := make(map[string]*Secret, len(secrets)) + suffixedExisting := make(map[string]*Existing, len(existing)) + for k, v := range secrets { + suffixedSecrets[k+".encrypted"] = v + } + for k, v := range existing { + suffixedExisting[k+".existing"] = v + } + + AppendSecrets(operator, allSecrets, suffixedSecrets, allExistingSecrets, suffixedExisting) - return pushFunc(monitor, gitClient, allTrees, path) + return nil } -func secretsListToSlice(secrets map[string]*Secret, includeEmpty bool) []string { - items := make([]string, 0, len(secrets)) +func secretsListToSlice( + secrets map[string]*Secret, + existing map[string]*Existing, + includeEmpty bool, +) []string { + items := make([]string, 0, len(secrets)+len(existing)) for key, value := range secrets { if includeEmpty || (value != nil && value.Value != "") { items = append(items, key) } } + for key, value := range existing { + if includeEmpty || (value != nil && value.Name != "" && value.Key != "") { + items = append(items, key) + } + } return items } -func findSecret(allSecrets map[string]*Secret, path *string, includeEmpty bool) (*Secret, error) { +func findSecret( + allSecrets map[string]*Secret, + allExisting map[string]*Existing, + path *string, + includeEmpty bool, +) ( + interface{}, + error, +) { if *path != "" { - return exactSecret(allSecrets, *path) + return exactSecret(allSecrets, allExisting, *path) } - selectItems := secretsListToSlice(allSecrets, includeEmpty) + selectItems := secretsListToSlice(allSecrets, allExisting, includeEmpty) sort.Slice(selectItems, func(i, j int) bool { iDots := strings.Count(selectItems[i], ".") @@ -99,13 +296,28 @@ func findSecret(allSecrets map[string]*Secret, path *string, includeEmpty bool) } *path = result - return exactSecret(allSecrets, *path) + return exactSecret(allSecrets, allExisting, *path) } -func exactSecret(secrets map[string]*Secret, path string) (*Secret, error) { +func exactSecret( + secrets map[string]*Secret, + existings map[string]*Existing, + path string, +) ( + interface{}, + error, +) { secret, ok := secrets[path] - if !ok { - return nil, fmt.Errorf("Secret %s not found", path) + if ok { + return secret, nil } - return secret, nil + + existing, ok := existings[path] + if ok { + return existing, nil + } + + return nil, fmt.Errorf("no secret found at %s", path) } + +func boolPtr(b bool) *bool { return &b } diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index 6d725fedc..907d04da5 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -27,6 +27,8 @@ type Secret struct { } type secretAlias Secret +const existingSecretsNamespace = "caos-system" + // Existing: Used secret that has to be already existing in the cluster type Existing struct { //Name of the Secret @@ -37,6 +39,13 @@ type Existing struct { InternalName string `json:"internalName,omitempty" yaml:"internalName,omitempty"` } +func (s *Existing) IsZero() bool { + if s.Name == "" && s.Key == "" { + return true + } + return false +} + // Existing: Used secret that has to be already existing in the cluster and should contain id/username and secret/password type ExistingIDSecret struct { //Name of the Secret @@ -204,12 +213,30 @@ func InitIfNil(sec *Secret) *Secret { return sec } -func AppendSecrets(prefix string, into, add map[string]*Secret) { - for key, secret := range add { +func AppendSecrets(prefix string, intoSecrets, addSecrets map[string]*Secret, intoExisting, addExisting map[string]*Existing) { + for key, secret := range addSecrets { name := key if prefix != "" { name = prefix + "." + name } - into[name] = secret + intoSecrets[name] = secret } + for key, existing := range addExisting { + name := key + if prefix != "" { + name = prefix + "." + name + } + intoExisting[name] = existing + } +} + +func ValidateSecret(secret *Secret, existing *Existing) error { + if secret == nil || existing == nil { + return errors.New("secret not specified") + } + + if secret.Value == "" && (existing.Name == "" || existing.Key == "") { + return errors.New("secret has no encrypted value or no valid reference") + } + return nil } diff --git a/pkg/tree/tree.go b/pkg/tree/tree.go index 166846f8a..889da398f 100644 --- a/pkg/tree/tree.go +++ b/pkg/tree/tree.go @@ -9,8 +9,8 @@ type Tree struct { } type Common struct { - Kind string - Version string `yaml:"version" yaml:"apiVersion"` + Kind string `json:"kind"` + Version string `json:"version" yaml:"version" yaml:"apiVersion"` } func (c *Tree) UnmarshalYAML(node *yaml.Node) error { diff --git a/scripts/cs_get_pprof_profile_from_na.sh b/scripts/cs_get_pprof_profile_from_na.sh new file mode 100755 index 000000000..49ff66e50 --- /dev/null +++ b/scripts/cs_get_pprof_profile_from_na.sh @@ -0,0 +1,12 @@ +SSHKEYFILE=$1 +IP=$2 +PROFILE=$3 +OUTPUT=$4 + +TMPFILENAME=tmp_profile + +ssh -i ${SSHKEYFILE} orbiter@${IP} "wget http://localhost:6060/debug/pprof/${PROFILE} -O ${TMPFILENAME}" + +scp -i ${SSHKEYFILE} orbiter@${IP}:/home/orbiter/${TMPFILENAME} ${OUTPUT} + +ssh -i ${SSHKEYFILE} orbiter@${IP} "rm -f ${TMPFILENAME}" ${INSTANCE} \ No newline at end of file diff --git a/scripts/gce_get_pprof_profile_from_na.sh b/scripts/gce_get_pprof_profile_from_na.sh new file mode 100755 index 000000000..0d71ca689 --- /dev/null +++ b/scripts/gce_get_pprof_profile_from_na.sh @@ -0,0 +1,11 @@ +INSTANCE=orbiter@$1 +PROFILE=$2 +OUTPUT=$3 + +TMPFILENAME=tmp_profile + +gcloud compute ssh ${INSTANCE} --command="wget http://localhost:6060/debug/pprof/${PROFILE} -O ${TMPFILENAME}" + +gcloud compute scp ${INSTANCE}:/home/orbiter/${TMPFILENAME} ${OUTPUT} + +gcloud compute ssh ${INSTANCE} --command="rm -f ${TMPFILENAME}" \ No newline at end of file diff --git a/scripts/generateCrd.sh b/scripts/generateCrd.sh new file mode 100755 index 000000000..1c14a569c --- /dev/null +++ b/scripts/generateCrd.sh @@ -0,0 +1,3 @@ +controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..." + +controller-gen "crd:trivialVersions=true" crd paths="./..." output:crd:artifacts:config=test diff --git a/scripts/orbctl.sh b/scripts/orbctl.sh index 8abbb6150..a3cdbd17d 100755 --- a/scripts/orbctl.sh +++ b/scripts/orbctl.sh @@ -3,7 +3,7 @@ set -e go run -race ./cmd/gen-executables/*.go \ - --version $(git rev-parse --abbrev-ref HEAD | sed -e "s/heads\///") \ + --version $(git rev-parse --abbrev-ref HEAD | sed -e "s/heads\///")-dev \ --commit $(git rev-parse HEAD) \ --githubclientid "${ORBOS_GITHUBOAUTHCLIENTID}" \ --githubclientsecret "${ORBOS_GITHUBOAUTHCLIENTSECRET}" \ From c3eb6db534b54d35286c37d37e6af3bbdc6c32b5 Mon Sep 17 00:00:00 2001 From: Stefan Benz Date: Fri, 10 Dec 2021 15:11:32 +0100 Subject: [PATCH 8/8] fix(networking): multiple load-balancers possibility --- go.mod | 3 +- go.sum | 301 +----------------- .../kinds/networking/legacycf/adapt.go | 2 +- .../kinds/networking/legacycf/app/app.go | 88 +++-- .../networking/legacycf/app/loadbalancers.go | 28 +- .../kinds/networking/legacycf/app/pools.go | 4 +- .../networking/legacycf/config/external.go | 89 +++--- .../networking/legacycf/config/internal.go | 20 +- .../networking/legacycf/legacyadapter.go | 3 +- 9 files changed, 135 insertions(+), 403 deletions(-) diff --git a/go.mod b/go.mod index 50dbadfe5..4bc3aa6af 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c github.com/aws/aws-sdk-go v1.40.45 github.com/caos/oidc v1.0.0 - github.com/cloudflare/cloudflare-go v0.23.0 + github.com/cloudflare/cloudflare-go v0.28.0 github.com/cloudscale-ch/cloudscale-go-sdk v1.7.1 github.com/getsentry/sentry-go v0.11.0 github.com/ghodss/yaml v1.0.0 @@ -17,7 +17,6 @@ require ( github.com/golang/mock v1.6.0 github.com/google/go-github/v31 v31.0.0 github.com/google/uuid v1.3.0 - github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23 github.com/kr/pty v1.1.8 // indirect github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1 diff --git a/go.sum b/go.sum index 4d12d1c1b..9fa1c8a34 100644 --- a/go.sum +++ b/go.sum @@ -30,186 +30,122 @@ cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0 h1:9x7Bx0A9R5/M9jibeJeZWqjeVEIxYW9fZYqB9a70/bY= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8= github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AppsFlyer/go-sundheit v0.2.0 h1:FArqX+HbqZ6U32RC3giEAWRUpkggqxHj91KIvxNgwjU= github.com/AppsFlyer/go-sundheit v0.2.0/go.mod h1:rCRkVTMQo7/krF7xQ9X0XEF1an68viFR6/Gy02q+4ds= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0 h1:1PwO5w5VCtlUUl+KTOBsTGZlhjWkcybsGaAau52tOy8= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= -github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 h1:WDC6ySpJzbxGWFh4aMxFFC28wwGp5pEuoTtvA4q/qQ4= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c h1:AMDVOKGaiqse4qiRXSzRgpC9DCNTHCx6zpzdtXXrKM4= github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c/go.mod h1:p/7Wos+jcfrnwLqqzJMZ0s323kfVtJPW+HUvAANklVQ= -github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI= github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo= github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/caos/oidc v1.0.0 h1:3sHkYf8zsuARR89qO9CyvfYhHGdliWPcou4glzGMXmQ= github.com/caos/oidc v1.0.0/go.mod h1:4l0PPwdc6BbrdCFhNrRTUddsG292uHGa7gE2DSEIqoU= -github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.23.0 h1:ePPZC8wLgtwz5itvgnDFFPPEku0G1a2tVKl5D69k3ac= -github.com/cloudflare/cloudflare-go v0.23.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI= +github.com/cloudflare/cloudflare-go v0.28.0 h1:KeQUizmDATYI9j+imMG1lJ1EMl7upcsKanSvNYHpNuc= +github.com/cloudflare/cloudflare-go v0.28.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI= github.com/cloudscale-ch/cloudscale-go-sdk v1.7.1 h1:DC+0N1zX1Bb1RvBp3tHHYy1mQ3pGyHUP+BGxRUs59YQ= github.com/cloudscale-ch/cloudscale-go-sdk v1.7.1/go.mod h1:FhOTOCgKAVvRRMQc1mC0D7xK/3zYnmcZBWFXNkacvMc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -219,28 +155,19 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd h1:uVsMphB1eRx7xB1njzL3fuMdWRN8HtVzoUOItHMwv5c= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/dgraph-io/badger v1.6.0 h1:DshxFxZWXUcO0xX476VJC07Xsr6ZCBVRHKZ93Oh7Evo= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= @@ -250,57 +177,39 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 h1:DddqAaWDpywytcG8w/qoQ5sAN8X12d3Z3koB0C3Rxsc= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.11.0 h1:qro8uttJGvNAMr5CLcFI9CHR0aDzXl0Vs3Pmw/oTPg8= github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -320,19 +229,14 @@ github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2Jg github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -341,37 +245,26 @@ github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/flect v0.2.3 h1:f/ZukRnSNA/DUpSNDadko7Qc0PhGvsew35p/2tu+CRY= github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -410,13 +303,10 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e h1:KhcknUwkWHKZPbFy2P7jH5LKJ3La+0ZeknkkmrSgqb0= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38 h1:y0Wmhvml7cGnzPa9nocn/fMraMH/lMDdeG+rkx4VgYY= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -439,11 +329,9 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -458,11 +346,8 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -475,11 +360,8 @@ github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pf github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= @@ -487,99 +369,62 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/iris-contrib/blackfriday v2.0.0+incompatible h1:o5sHQHHm0ToHUlAJSTjW9UWicjJSDDauOOQ2AHuIVp4= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible h1:XZubAYg61/JwnJNbZilGjf3b3pB80+OQg2qf6c8BfWE= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3 h1:p7J/50I0cjo0wq/VWVCDFd8taPJbuFC+bq23SniRFX0= github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to= github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1 h1:10g/WnoRR+U+XXHWKBHeNy/+tZmM2kcAVGLOsz+yaDA= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -588,24 +433,15 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kataras/golog v0.0.10 h1:vRDRUmwacco/pmBAm8geLn8rHEdc+9Z4NAr5Sh7TG/4= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8 h1:O3gJasjm7ZxpxwTH8tApZsvf274scSGQAUpNe47c37U= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14 h1:pdJaTvUG3NQfeMbbVCI8JT2T5goPldyyfUB2PJfh1Bs= github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2 h1:6NAi+uPJ/Zuid6mrAKlgpbI11/zK/lV4B2rxWaJN98Y= github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5 h1:4HCONX5RLgVy6G4RkYOV3vKNcma9p236LdGOipJsaFE= github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23 h1:M8exrBzuhWcU6aoHJlHWPe4qFjVKzkMGRal78f5jRRU= github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23/go.mod h1:kBSna6b0/RzsOcOZf515vAXwSsXYusl2U7SA0XP09yI= @@ -615,25 +451,17 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug26aA= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -643,24 +471,18 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.1.11 h1:z0BZoArY4FqdpUEl+wlHp4hnr/oSR6MTmQmv8OHSoww= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= -github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1 h1:xUwSaTDYl+Ib5OoFxWJnqYFG9N31++qfeNXzTZ1cc8o= github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1/go.mod h1:f0X1c0za3TbET/rl5ThtCSel0+G3/yZ8iuU9BxnyVK0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -675,37 +497,28 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 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/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/radix/v3 v3.4.2 h1:galbPBjIwmyREgwGCfQEN4X8lxbJnKBYurgz+VfcStA= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= @@ -717,25 +530,16 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -744,10 +548,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= -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/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -765,16 +567,11 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= @@ -786,13 +583,10 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -820,52 +614,36 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -874,7 +652,6 @@ github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSW github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -883,14 +660,11 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -900,76 +674,47 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0 h1:uWF8lgKmeaIewWVPwi4GRq2P6+R46IgYZdxWtM+GtEY= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= -github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -980,31 +725,18 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= @@ -1046,10 +778,8 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1065,7 +795,6 @@ golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= @@ -1159,7 +888,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1461,7 +1189,6 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1479,7 +1206,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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= @@ -1488,27 +1214,19 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/raintank/schema.v1 v1.0.0 h1:9KsXuASUJARgrgKiCmlaY7RmeBOAtIB00e6YW3G79sM= gopkg.in/raintank/schema.v1 v1.0.0/go.mod h1:mx46t/rI5UA/b+WtF5ThX+qFJ7P7MOmE3ZMR12Wfr8c= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= @@ -1544,7 +1262,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= @@ -1552,21 +1269,16 @@ k8s.io/apiextensions-apiserver v0.22.2 h1:zK7qI8Ery7j2CaN23UCFaC1hj7dMiI87n01+nK k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apiserver v0.22.2 h1:TdIfZJc6YNhu2WxeAOWq1TvukHF0Sfx0+ln4XK9qnL4= k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= -k8s.io/cli-runtime v0.22.2 h1:fsd9rFk9FSaVq4SUq1fM27c8CFGsYZUJ/3BkgmjYWuY= k8s.io/cli-runtime v0.22.2/go.mod h1:tkm2YeORFpbgQHEK/igqttvPTRIHFRz5kATlw53zlMI= k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= -k8s.io/code-generator v0.22.2 h1:+bUv9lpTnAWABtPkvO4x0kfz7j/kDEchVt0P/wXU3jQ= k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/component-base v0.22.2 h1:vNIvE0AIrLhjX8drH0BgCNJcR4QZxMXcJzBsDplDx9M= k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= -k8s.io/component-helpers v0.22.2 h1:guQ9oYclE5LMydWFfAFA+u7SQgQzz2g+YgpJ5QooSyY= k8s.io/component-helpers v0.22.2/go.mod h1:+N61JAR9aKYSWbnLA88YcFr9K/6ISYvRNybX7QW7Rs8= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= @@ -1578,29 +1290,20 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kubectl v0.22.2 h1:KMyYNZoBshaL3XKx04X07DtpoD4vMrdkfiN/G2Qx/PU= k8s.io/kubectl v0.22.2/go.mod h1:BApg2j0edxLArCOfO0ievI27EeTQqBDMNU9VQH734iQ= -k8s.io/metrics v0.22.2 h1:ZQbsg2ENzp+JyhQMp3tsFZK9i5KxvSTDrdkgoWRL568= k8s.io/metrics v0.22.2/go.mod h1:GUcsBtpsqQD1tKFS/2wCKu4ZBowwRncLOJH1rgWs3uw= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 h1:fmRfl9WJ4ApJn7LxNuED4m0t18qivVQOxP6aAYG9J6c= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.10.1 h1:+eLHgY/VrJWnfg6iXUqhCUqNXgPH1NZeP9drNAAgWlg= sigs.k8s.io/controller-runtime v0.10.1/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY= sigs.k8s.io/controller-tools v0.7.0 h1:iZIz1vEcavyEfxjcTLs1WH/MPf4vhPCtTKhoHqV8/G0= sigs.k8s.io/controller-tools v0.7.0/go.mod h1:bpBAo0VcSDDLuWt47evLhMLPxRPxMDInTEH/YbdeMK0= -sigs.k8s.io/kustomize/api v0.8.11 h1:LzQzlq6Z023b+mBtc6v72N2mSHYmN8x7ssgbf/hv0H8= sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g= -sigs.k8s.io/kustomize/cmd/config v0.9.13 h1:lqOf0QcFhNvgZkgrPINNRs7TxEO7IGVtLMyUJId3oRE= sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs= -sigs.k8s.io/kustomize/kustomize/v4 v4.2.0 h1:RKgbyHgzuHQZ35sBDzWcbnR3HBlJSYdSN0H+sx3tUkk= sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go= -sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA= sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= diff --git a/internal/operator/networking/kinds/networking/legacycf/adapt.go b/internal/operator/networking/kinds/networking/legacycf/adapt.go index d2d58c472..8a1f2652a 100644 --- a/internal/operator/networking/kinds/networking/legacycf/adapt.go +++ b/internal/operator/networking/kinds/networking/legacycf/adapt.go @@ -50,7 +50,7 @@ func AdaptFunc( return nil, nil, nil, nil, false, errors.New("No specs found") } - if err := desiredKind.Spec.Validate(id); err != nil { + if err := desiredKind.Spec.Validate(); err != nil { return nil, nil, nil, nil, false, err } diff --git a/internal/operator/networking/kinds/networking/legacycf/app/app.go b/internal/operator/networking/kinds/networking/legacycf/app/app.go index e1471dc21..654d128a1 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/app.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/app.go @@ -39,6 +39,13 @@ func (a *App) AddInternalPrefix(desc string) string { return strings.Join([]string{a.internalPrefix, desc}, " ") } +type additionalInfos struct { + name string + subdomain string + clusterID string + region string +} + func (a *App) Ensure( ctx context.Context, id string, @@ -48,28 +55,31 @@ func (a *App) Ensure( subdomains []*config.Subdomain, rules []*config.Rule, originCALabels *labels.Name, - lbs *config.LoadBalancer, - floatingIP string, + lbs []*config.LoadBalancer, ) error { firewallRulesInt := make([]*cloudflare.FirewallRule, 0) filtersInt := make([]*cloudflare.Filter, 0) recordsInt := make([]*cloudflare.DNSRecord, 0) poolsInt := make([]*cloudflare.LoadBalancerPool, 0) lbsInt := make([]*cloudflare.LoadBalancer, 0) - - if lbs != nil && lbs.Create { - originsInt := []*cloudflare.LoadBalancerOrigin{{ - Name: getPoolName(domain, lbs.Region, lbs.ClusterID), - Address: floatingIP, - Enabled: true, - }} - - poolsInt = append(poolsInt, &cloudflare.LoadBalancerPool{ - Name: getPoolName(domain, lbs.Region, lbs.ClusterID), - Description: id, - Enabled: lbs.Enabled, - Origins: originsInt, - }) + lbsAdditionalInt := make([]*additionalInfos, 0) + + if lbs != nil { + for _, lb := range lbs { + for name, ip := range lb.Pool { + originsInt := []*cloudflare.LoadBalancerOrigin{{ + Name: name, + Address: ip, + Enabled: true, + }} + poolsInt = append(poolsInt, &cloudflare.LoadBalancerPool{ + Name: getPoolName(lb.Subdomain, domain, lb.Region, lb.ClusterID), + Description: id, + Enabled: true, + Origins: originsInt, + }) + } + } } destroyPools, err := a.EnsureLoadBalancerPools(ctx, id, poolsInt) @@ -77,28 +87,38 @@ func (a *App) Ensure( return err } - if lbs != nil && lbs.Create { - //ids get filled in the EnsureLoadBalancerPools-function - poolNames := []string{} - if poolsInt != nil { - for _, poolInt := range poolsInt { - poolNames = append(poolNames, poolInt.ID) + if lbs != nil { + for _, lb := range lbs { + //ids get filled in the EnsureLoadBalancerPools-function + poolNames := []string{} + if poolsInt != nil { + for _, poolInt := range poolsInt { + if poolInt.Name == getPoolName(lb.Subdomain, domain, lb.Region, lb.ClusterID) { + poolNames = append(poolNames, poolInt.ID) + } + } } - } - enabled := true - lbsInt = append(lbsInt, &cloudflare.LoadBalancer{ - Name: config.GetLBName(domain), - DefaultPools: poolNames, - //the first pool is fallback pool for now - FallbackPool: poolNames[0], - Enabled: &enabled, - Proxied: true, - SteeringPolicy: "random", - }) + enabled := lb.Enabled + lbsInt = append(lbsInt, &cloudflare.LoadBalancer{ + Name: config.GetLBName(lb.Subdomain, domain), + DefaultPools: poolNames, + //the first pool is fallback pool for now + FallbackPool: poolNames[0], + Enabled: &enabled, + Proxied: true, + SteeringPolicy: "random", + }) + lbsAdditionalInt = append(lbsAdditionalInt, &additionalInfos{ + name: config.GetLBName(lb.Subdomain, domain), + clusterID: lb.ClusterID, + region: lb.Region, + subdomain: lb.Subdomain, + }) + } } - if err := a.EnsureLoadBalancers(ctx, id, lbs.ClusterID, lbs.Region, domain, lbsInt); err != nil { + if err := a.EnsureLoadBalancers(ctx, id, domain, lbsInt, lbsAdditionalInt); err != nil { return err } diff --git a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go index 12d0fbd12..cb5796d92 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/loadbalancers.go @@ -3,10 +3,15 @@ package app import ( "context" "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/cloudflare" - "github.com/caos/orbos/internal/operator/networking/kinds/networking/legacycf/config" ) -func (a *App) EnsureLoadBalancers(ctx context.Context, id string, clusterID, region, domain string, lbs []*cloudflare.LoadBalancer) error { +func (a *App) EnsureLoadBalancers( + ctx context.Context, + id string, + domain string, + lbs []*cloudflare.LoadBalancer, + lbsAdditional []*additionalInfos, +) error { currentLbs, err := a.cloudflare.ListLoadBalancers(ctx, domain) if err != nil { return err @@ -40,7 +45,7 @@ func (a *App) EnsureLoadBalancers(ctx context.Context, id string, clusterID, reg } } - updateLbs = append(updateLbs, getLoadBalancerToUpdate(ctx, a.cloudflare, id, clusterID, region, domain, currentLbs, lbs)...) + updateLbs = append(updateLbs, getLoadBalancerToUpdate(ctx, a.cloudflare, id, domain, currentLbs, lbs, lbsAdditional)...) if updateLbs != nil && len(updateLbs) > 0 { for _, lb := range updateLbs { _, err := a.cloudflare.UpdateLoadBalancer(ctx, domain, lb) @@ -121,11 +126,10 @@ func getLoadBalancerToUpdate( ctx context.Context, cf *cloudflare.Cloudflare, id, - clusterID, - region, domain string, currentLbs []*cloudflare.LoadBalancer, lbs []*cloudflare.LoadBalancer, + infos []*additionalInfos, ) []*cloudflare.LoadBalancer { updateLbs := make([]*cloudflare.LoadBalancer, 0) @@ -133,11 +137,17 @@ func getLoadBalancerToUpdate( return updateLbs } - poolName := getPoolName(domain, region, clusterID) - for _, lb := range lbs { + additional := &additionalInfos{} + for _, add := range infos { + if add.name == lb.Name { + additional = add + } + } + poolName := getPoolName(additional.subdomain, domain, additional.region, additional.clusterID) + for _, currentLb := range currentLbs { - if currentLb.Name == config.GetLBName(domain) { + if currentLb.Name == lb.Name { containedRegion := false containedDefault := false for _, currentPool := range currentLb.DefaultPools { @@ -149,7 +159,7 @@ func getLoadBalancerToUpdate( regionPoolsLoop: for currentRegion, currentPools := range currentLb.RegionPools { - if currentRegion == region { + if currentRegion == additional.region { for _, currentPool := range currentPools { if currentPool == poolName { containedRegion = true diff --git a/internal/operator/networking/kinds/networking/legacycf/app/pools.go b/internal/operator/networking/kinds/networking/legacycf/app/pools.go index f08cc7913..6f2d2b0ed 100644 --- a/internal/operator/networking/kinds/networking/legacycf/app/pools.go +++ b/internal/operator/networking/kinds/networking/legacycf/app/pools.go @@ -7,8 +7,8 @@ import ( "strings" ) -func getPoolName(domain, region, clusterID string) string { - return strings.Join([]string{clusterID, region, strings.ReplaceAll(domain, ".", "-")}, "-") +func getPoolName(subdomain, domain, region, clusterID string) string { + return strings.Join([]string{clusterID, region, subdomain, strings.ReplaceAll(domain, ".", "-")}, "-") } func (a *App) EnsureLoadBalancerPools(ctx context.Context, id string, pools []*cloudflare.LoadBalancerPool) (func() error, error) { diff --git a/internal/operator/networking/kinds/networking/legacycf/config/external.go b/internal/operator/networking/kinds/networking/legacycf/config/external.go index 396dbeb33..c3595d01b 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/external.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/external.go @@ -3,7 +3,6 @@ package config import ( "errors" "fmt" - "net" "strings" "github.com/caos/orbos/mntr" @@ -19,20 +18,18 @@ type ExternalConfig struct { AccountName string `yaml:"accountName"` Verbose bool Domain string - IP string Rules []*Rule - Groups []*Group `yaml:"groups"` - Credentials *Credentials `yaml:"credentials"` - Prefix string `yaml:"prefix"` - AdditionalDNS []*Subdomain `yaml:"additionalSubdomains,omitempty"` - LoadBalancer *LoadBalancer `yaml:"loadBalancer,omitempty"` + Groups []*Group `yaml:"groups"` + Credentials *Credentials `yaml:"credentials"` + Prefix string `yaml:"prefix"` + AdditionalDNS []*Subdomain `yaml:"additionalSubdomains,omitempty"` + LoadBalancers []*LoadBalancer `yaml:"loadBalancers,omitempty"` } func (i *ExternalConfig) IsZero() bool { if (i.Credentials == nil || i.Credentials.IsZero()) && !i.Verbose && i.Domain == "" && - i.IP == "" && i.Groups == nil && i.Prefix == "" && i.Rules == nil && @@ -58,8 +55,9 @@ func (e *ExternalConfig) Internal(id, namespace string, apiLabels *labels.API) ( } var ErrNoLBID = errors.New("no loadbalancer identifier provided") +var ErrDoubleLBID = errors.New("loadbalancer identifier doublicate") -func (e *ExternalConfig) Validate(lbID string) (err error) { +func (e *ExternalConfig) Validate() (err error) { defer func() { err = mntr.ToUserError(err) }() @@ -69,12 +67,23 @@ func (e *ExternalConfig) Validate(lbID string) (err error) { if e.Domain == "" { return errors.New("No domain configured") } - if net.ParseIP(e.IP) == nil { - return fmt.Errorf("%s is not a valid ip address", e.IP) - } - if e.LoadBalancer != nil && lbID == "" { - return ErrNoLBID + identifiers := []string{} + for _, loadbalancer := range e.LoadBalancers { + if loadbalancer == nil { + continue + } + + if loadbalancer.Subdomain == "" { + return ErrNoLBID + } + + for _, id := range identifiers { + if id == loadbalancer.Subdomain { + return ErrDoubleLBID + } + } + identifiers = append(identifiers, loadbalancer.Subdomain) } return nil @@ -103,41 +112,33 @@ func (e *ExternalConfig) ValidateSecrets() (err error) { func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { subdomains := []*Subdomain{} - // TODO: Remove - if e.LoadBalancer != nil && e.LoadBalancer.Enabled { - lbName := GetLBName(e.Domain) - subdomains = append(subdomains, - subdomain("accounts", lbName, "CNAME"), - subdomain("api", lbName, "CNAME"), - subdomain("console", lbName, "CNAME"), - subdomain("issuer", lbName, "CNAME"), - ) - } else { - subdomains = append(subdomains, - subdomain("accounts", string(e.IP), "A"), - subdomain("api", string(e.IP), "A"), - subdomain("console", string(e.IP), "A"), - subdomain("issuer", string(e.IP), "A"), - ) - } for _, sd := range e.AdditionalDNS { subdomains = append(subdomains, sd) } - lb := &LoadBalancer{} - if e.LoadBalancer != nil { - lb.Enabled = e.LoadBalancer.Enabled - lb.Create = e.LoadBalancer.Create - lb.Region = e.LoadBalancer.Region - lb.ClusterID = e.LoadBalancer.ClusterID + lbs := make([]*LoadBalancer, 0) + if e.LoadBalancers != nil { + for _, lb := range e.LoadBalancers { + pool := map[string]string{} + for k, v := range lb.Pool { + pool[k] = v + } + + lbs = append(lbs, &LoadBalancer{ + Subdomain: lb.Subdomain, + ClusterID: lb.ClusterID, + Region: lb.Region, + Enabled: lb.Enabled, + Pool: pool, + }) + } } return &InternalDomain{ - FloatingIP: string(e.IP), - Domain: e.Domain, - Subdomains: subdomains, - Rules: e.Rules, - LoadBalancer: lb, + Domain: e.Domain, + Subdomains: subdomains, + Rules: e.Rules, + LoadBalancers: lbs, }, ¤t{ domain: e.Domain, @@ -148,8 +149,8 @@ func (e *ExternalConfig) internalDomain() (*InternalDomain, *current) { tlsCertName: "tls-cert-wildcard", } } -func GetLBName(domain string) string { - return strings.Join([]string{"lb", domain}, ".") +func GetLBName(subdomain, domain string) string { + return strings.Join([]string{subdomain, domain}, ".") } func subdomain(subdomain string, target string, ty string) *Subdomain { diff --git a/internal/operator/networking/kinds/networking/legacycf/config/internal.go b/internal/operator/networking/kinds/networking/legacycf/config/internal.go index ba1fd9c9a..07c81b83d 100644 --- a/internal/operator/networking/kinds/networking/legacycf/config/internal.go +++ b/internal/operator/networking/kinds/networking/legacycf/config/internal.go @@ -41,19 +41,19 @@ type Group struct { } type InternalDomain struct { - FloatingIP string - Domain string `yaml:"domain"` - Origin *Origin `yaml:"origin"` - Subdomains []*Subdomain `yaml:"subdomains"` - Rules []*Rule `yaml:"rules"` - LoadBalancer *LoadBalancer `yaml:"loadbalancer"` + Domain string `yaml:"domain"` + Origin *Origin `yaml:"origin"` + Subdomains []*Subdomain `yaml:"subdomains"` + Rules []*Rule `yaml:"rules"` + LoadBalancers []*LoadBalancer `yaml:"loadbalancers"` } type LoadBalancer struct { - Create bool `yaml:"create"` - ClusterID string `yaml:"clusterid"` - Region string `yaml:"region"` - Enabled bool `yaml:"enabled"` + Subdomain string `yaml:"subdomain"` + ClusterID string `yaml:"clusterid"` + Region string `yaml:"region"` + Enabled bool `yaml:"enabled"` + Pool map[string]string `yaml:"pool"` } type Origin struct { diff --git a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go index f6578bd0e..be648f774 100644 --- a/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go +++ b/internal/operator/networking/kinds/networking/legacycf/legacyadapter.go @@ -63,8 +63,7 @@ func adaptFunc( domain.Subdomains, domain.Rules, caSecretLabels, - domain.LoadBalancer, - domain.FloatingIP, + domain.LoadBalancers, ) if err != nil { return err