mirror of
https://github.com/openziti/ziti.git
synced 2026-10-12 15:28:05 +00:00
Merge pull request #1906 from openziti/ctrl-load-test
Load test for controller with links, terminators, clients and traffic
This commit is contained in:
@@ -383,29 +383,3 @@ func (self *testConfig) GetVersionProvider() versions.VersionProvider {
|
||||
func (self *testConfig) GetCloseNotify() <-chan struct{} {
|
||||
return self.closeNotify
|
||||
}
|
||||
|
||||
//
|
||||
//type testDbProvider struct {
|
||||
// ctx *TestContext
|
||||
//}
|
||||
//
|
||||
//func (p *testDbProvider) GetDb() boltz.Db {
|
||||
// return p.ctx.GetDb()
|
||||
//}
|
||||
//
|
||||
//func (p *testDbProvider) GetStores() *Stores {
|
||||
// return p.ctx.n.GetStores()
|
||||
//}
|
||||
//
|
||||
//func (p *testDbProvider) GetServiceCache() network.Cache {
|
||||
// return p
|
||||
//}
|
||||
//
|
||||
//func (p *testDbProvider) NotifyRouterRenamed(_, _ string) {}
|
||||
//
|
||||
//func (p *testDbProvider) RemoveFromCache(_ string) {
|
||||
//}
|
||||
//
|
||||
//func (p *testDbProvider) GetManagers() *network.Managers {
|
||||
// return p.ctx.n.Managers
|
||||
//}
|
||||
|
||||
+2
-2
@@ -15,13 +15,14 @@ require (
|
||||
github.com/openziti/agent v1.0.16
|
||||
github.com/openziti/channel/v2 v2.0.125
|
||||
github.com/openziti/edge-api v0.26.14
|
||||
github.com/openziti/fablab v0.5.42
|
||||
github.com/openziti/fablab v0.5.49
|
||||
github.com/openziti/foundation/v2 v2.0.42
|
||||
github.com/openziti/identity v1.0.74
|
||||
github.com/openziti/sdk-golang v0.23.15
|
||||
github.com/openziti/storage v0.2.34
|
||||
github.com/openziti/transport/v2 v2.0.128
|
||||
github.com/openziti/ziti v0.28.3
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
@@ -143,7 +144,6 @@ require (
|
||||
github.com/openziti/x509-claims v1.0.3 // indirect
|
||||
github.com/openziti/xweb/v2 v2.1.0 // indirect
|
||||
github.com/openziti/ziti-db-explorer v1.1.3 // indirect
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
|
||||
github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pkg/sftp v1.13.6 // indirect
|
||||
|
||||
+2
-2
@@ -596,8 +596,8 @@ github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAP
|
||||
github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo=
|
||||
github.com/openziti/edge-api v0.26.14 h1:BpxKavDVdykOY7GSdKXi7klv9Im4vw7bTMujz3wFE1Q=
|
||||
github.com/openziti/edge-api v0.26.14/go.mod h1:aTRqB9J/6ISbw9+YWjzD0tvWAXY98m8yWcbiGNqAQTU=
|
||||
github.com/openziti/fablab v0.5.42 h1:vENJKfEba2T4sSLwlKDL/IzBYfY8iHnhc4umf6IESiY=
|
||||
github.com/openziti/fablab v0.5.42/go.mod h1:HDT06y1QX8kO8ZQrgHvZmJsvc8iRybESGtlDLDII4ks=
|
||||
github.com/openziti/fablab v0.5.49 h1:uYmBQBS7auPeUlQBpnrU+ktDFhUTOklwwftBBqXcaDk=
|
||||
github.com/openziti/fablab v0.5.49/go.mod h1:TAXN6lhTnmjL4nwkio3Ql96Lf5gnyeSbm7uV+CilsPo=
|
||||
github.com/openziti/foundation/v2 v2.0.42 h1:cXZFql3xY92AHPCk/wqIoSUX9EHgegwPrs5bhFE2jNg=
|
||||
github.com/openziti/foundation/v2 v2.0.42/go.mod h1:a+REYnK9bZ2cvmOiuBLp57MjQqn3U5cHhJcDMLMO8rE=
|
||||
github.com/openziti/identity v1.0.74 h1:BUCKjGXIdoEHLL1+kO/smitZvGwP9dOUpjVEJFtSSBc=
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
v: 3
|
||||
|
||||
db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/ctrl.db
|
||||
|
||||
identity:
|
||||
cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}-server.chain.pem
|
||||
key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}-server.key
|
||||
ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.chain.pem
|
||||
|
||||
network:
|
||||
enableLegacyLinkMgmt: true
|
||||
|
||||
tls:
|
||||
handshakeTimeout: 30s
|
||||
|
||||
# the endpoint that routers will connect to the controller over.
|
||||
ctrl:
|
||||
listener: tls:0.0.0.0:6262
|
||||
options:
|
||||
advertiseAddress: tls:{{ .Host.PublicIp }}:6262
|
||||
# (optional) settings
|
||||
# set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000)
|
||||
#maxQueuedConnects: 50
|
||||
|
||||
# the maximum number of connects that have begun hello synchronization (1 to 1000, default 16)
|
||||
#maxOutstandingConnects: 100
|
||||
|
||||
# the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms)
|
||||
#connectTimeoutMs: 3000
|
||||
|
||||
# Sets the control channel write timeout. A write timeout will close the control channel, so the router will reconnect
|
||||
#writeTimeout: 15s
|
||||
|
||||
# A listener address which will be sent to connecting routers in order to change their configured controller
|
||||
# address. If defined, routers will update address configuration to immediately use the new address for future
|
||||
# connections. The value of newListener must be resolvable both via DNS and validate via certificates
|
||||
#newListener: tls:localhost:6262
|
||||
|
||||
events:
|
||||
jsonLogger:
|
||||
subscriptions:
|
||||
# - type: fabric.routers
|
||||
# - type: fabric.terminators
|
||||
# - type: metrics
|
||||
# sourceFilter: .*
|
||||
# metricFilter: .*egress.*m1_rate*
|
||||
# - type: fabric.circuits
|
||||
# include:
|
||||
# - created
|
||||
# - type: edge.sessions
|
||||
# include:
|
||||
# - created
|
||||
# - type: edge.apiSessions
|
||||
# - type: fabric.usage
|
||||
# - type: services
|
||||
# - type: fabric.usage
|
||||
- type: edge.entityCounts
|
||||
interval: 1m
|
||||
handler:
|
||||
type: file
|
||||
format: json
|
||||
path: /home/ubuntu/logs/events.json
|
||||
|
||||
healthChecks:
|
||||
boltCheck:
|
||||
# How often to try entering a bolt read tx. Defaults to 30 seconds
|
||||
interval: 30s
|
||||
# When to timeout the check. Defaults to 15 seconds
|
||||
timeout: 15s
|
||||
# How long to wait before starting the check. Defaults to 15 seconds
|
||||
initialDelay: 15s
|
||||
|
||||
# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this
|
||||
# section, commenting out, or altering the name of the section will cause the edge to not run.
|
||||
edge:
|
||||
# This section represents the configuration of the Edge API that is served over HTTPS
|
||||
api:
|
||||
#(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted
|
||||
# activityUpdateInterval: 90s
|
||||
#(optional, default 250) The number of API Sessions updated for last activity per transaction
|
||||
# activityUpdateBatchSize: 250
|
||||
# sessionTimeout - optional, default 10m
|
||||
# The number of minutes before an Edge API session will timeout. Timeouts are reset by
|
||||
# API requests and connections that are maintained to Edge Routers
|
||||
sessionTimeout: 30m
|
||||
# address - required
|
||||
# The default address (host:port) to use for enrollment for the Client API. This value must match one of the addresses
|
||||
# defined in a bind point's address field for the `edge-client` API in the web section.
|
||||
address: {{ .Host.PublicIp }}:1280
|
||||
# enrollment - required
|
||||
# A section containing settings pertaining to enrollment.
|
||||
enrollment:
|
||||
# signingCert - required
|
||||
# A Ziti Identity configuration section that specifically makes use of the cert and key fields to define
|
||||
# a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert
|
||||
# will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller.
|
||||
signingCert:
|
||||
cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.cert
|
||||
key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}.key
|
||||
|
||||
# edgeIdentity - optional
|
||||
# A section for identity enrollment specific settings
|
||||
edgeIdentity:
|
||||
# duration - optional, default 5m
|
||||
# The length of time that a Ziti Edge Identity enrollment should remain valid. After
|
||||
# this duration, the enrollment will expire and not longer be usable.
|
||||
duration: 1h
|
||||
# edgeRouter - Optional
|
||||
# A section for edge router enrollment specific settings.
|
||||
edgeRouter:
|
||||
# duration - optional, default 5m
|
||||
# The length of time that a Ziti Edge Router enrollment should remain valid. After
|
||||
# this duration, the enrollment will expire and not longer be usable.
|
||||
duration: 1h
|
||||
|
||||
|
||||
# web - optional
|
||||
# Defines webListeners that will be hosted by the controller. Each webListener can host many APIs and be bound to many
|
||||
# bind points.
|
||||
web:
|
||||
# name - required
|
||||
# Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested.
|
||||
- name: all-apis-localhost
|
||||
# bindPoints - required
|
||||
# One or more bind points are required. A bind point specifies an interface (interface:port string) that defines
|
||||
# where on the host machine the webListener will listen and the address (host:port) that should be used to
|
||||
# publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for
|
||||
# incoming address resolution as well as used in responses in the API.
|
||||
bindPoints:
|
||||
#interface - required
|
||||
# A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces
|
||||
- interface: 0.0.0.0:1280
|
||||
|
||||
# address - required
|
||||
# The public address that external incoming requests will be able to resolve. Used in request processing and
|
||||
# response content that requires full host:port/path addresses.
|
||||
address: {{ .Host.PublicIp }}:1280
|
||||
|
||||
# newAddress - optional
|
||||
# A host:port string which will be sent out as an HTTP header "ziti-new-address" if specified. If the header
|
||||
# is present, clients should update location configuration to immediately use the new address for future
|
||||
# connections. The value of newAddress must be resolvable both via DNS and validate via certificates
|
||||
#newAddress: localhost:1280
|
||||
# identity - optional
|
||||
# Allows the webListener to have a specific identity instead of defaulting to the root `identity` section.
|
||||
# identity:
|
||||
# cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-client.cert.pem
|
||||
# server_cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-server.cert.pem
|
||||
# key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/ctrl.key.pem
|
||||
# ca: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ca-chain.cert.pem
|
||||
# options - optional
|
||||
# Allows the specification of webListener level options - mainly dealing with HTTP/TLS settings. These options are
|
||||
# used for all http servers started by the current webListener.
|
||||
options:
|
||||
# idleTimeout - optional, default 5000ms
|
||||
# The maximum amount of idle time in milliseconds allowed for pipelined HTTP requests. Setting this too high
|
||||
# can cause resources on the host to be consumed as clients remain connected and idle. Lowering this value
|
||||
# will cause clients to reconnect on subsequent HTTPs requests.
|
||||
idleTimeout: 5000ms #http timeouts, new
|
||||
|
||||
# readTimeout - optional, default 5000ms
|
||||
# The maximum amount of time in milliseconds http servers will wait to read the first incoming requests. A higher
|
||||
# value risks consuming resources on the host with clients that are acting bad faith or suffering from high latency
|
||||
# or packet loss. A lower value can risk losing connections to high latency/packet loss clients.
|
||||
|
||||
readTimeout: 5000ms
|
||||
# writeTimeout - optional, default 10000ms
|
||||
# The total maximum time in milliseconds that the http server will wait for a single requests to be received and
|
||||
# responded too. A higher value can allow long running requests to consume resources on the host. A lower value
|
||||
# can risk ending requests before the server has a chance to respond.
|
||||
|
||||
writeTimeout: 100000ms
|
||||
# minTLSVersion - optional, default TSL1.2
|
||||
# The minimum version of TSL to support
|
||||
|
||||
minTLSVersion: TLS1.2
|
||||
# maxTLSVersion - optional, default TSL1.3
|
||||
# The maximum version of TSL to support
|
||||
|
||||
maxTLSVersion: TLS1.3
|
||||
# apis - required
|
||||
# Allows one or more APIs to be bound to this webListener
|
||||
apis:
|
||||
# binding - required
|
||||
# Specifies an API to bind to this webListener. Built-in APIs are
|
||||
# - health-checks
|
||||
# - edge-management
|
||||
# - edge-client
|
||||
# - fabric-management
|
||||
- binding: health-checks
|
||||
- binding: fabric
|
||||
- binding: edge-management
|
||||
- binding: edge-client
|
||||
- binding: edge-oidc
|
||||
@@ -0,0 +1,78 @@
|
||||
{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}}
|
||||
{{$identity := .Component.Id}}
|
||||
{{$router_ip := .Host.PublicIp}}
|
||||
|
||||
v: 3
|
||||
|
||||
enableDebugOps: true
|
||||
|
||||
identity:
|
||||
cert: /home/{{$ssh_username}}/router-pki/{{$identity}}-client.cert
|
||||
server_cert: /home/{{$ssh_username}}/router-pki/{{$identity}}-server.cert
|
||||
key: /home/{{$ssh_username}}/router-pki/{{$identity}}.key
|
||||
ca: /home/{{$ssh_username}}/router-pki/{{$identity}}-server.chain.pem
|
||||
|
||||
tls:
|
||||
handshakeTimeout: 30s
|
||||
|
||||
ctrl:
|
||||
endpoints: {{ range $host := .Model.MustSelectHosts "component.ctrl" 1 }}
|
||||
- tls:{{ $host.PublicIp }}:6262{{end}}
|
||||
startupTimeout: 5m
|
||||
|
||||
healthChecks:
|
||||
ctrlPingCheck:
|
||||
# How often to ping the controller over the control channel. Defaults to 30 seconds
|
||||
interval: 30s
|
||||
# When to timeout the ping. Defaults to 15 seconds
|
||||
timeout: 15s
|
||||
# How long to wait before pinging the controller. Defaults to 15 seconds
|
||||
initialDelay: 15s
|
||||
|
||||
metrics:
|
||||
reportInterval: 15s
|
||||
messageQueueSize: 10
|
||||
|
||||
link:
|
||||
{{if .Component.HasTag "public"}}
|
||||
listeners:
|
||||
- binding: transport
|
||||
bind: tls:0.0.0.0:60{{printf "%02d" .Component.ScaleIndex }}
|
||||
advertise: tls:{{$router_ip}}:60{{printf "%02d" .Component.ScaleIndex }}
|
||||
{{end}}
|
||||
dialers:
|
||||
- binding: transport
|
||||
options:
|
||||
connectTimeout: 30s
|
||||
|
||||
listeners:
|
||||
{{if .Component.HasTag "tunneler"}}
|
||||
- binding: tunnel
|
||||
options:
|
||||
mode: host
|
||||
{{end}}
|
||||
- binding: edge
|
||||
address: tls:0.0.0.0:62{{printf "%02d" .Component.ScaleIndex }}
|
||||
options:
|
||||
# (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section.
|
||||
advertise: {{ .Host.PublicIp }}:62{{printf "%02d" .Component.ScaleIndex }}
|
||||
|
||||
# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this
|
||||
# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge
|
||||
# Router.
|
||||
edge:
|
||||
# (required) Information used to generate the initial registration CSR. For documentation on these fields please
|
||||
# refer to the openssl documentation. These values MUST be supplied and have no defaults.
|
||||
csr:
|
||||
country: US
|
||||
province: NC
|
||||
locality: Charlotte
|
||||
organization: NetFoundry
|
||||
organizationalUnit: Ziti
|
||||
|
||||
# (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches
|
||||
# the edge listeners "advertise" value from the "listeners" section.
|
||||
sans:
|
||||
ip:
|
||||
- {{ .Host.PublicIp }}
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
Copyright 2019 NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"embed"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"github.com/openziti/fablab"
|
||||
"github.com/openziti/fablab/kernel/lib/actions"
|
||||
"github.com/openziti/fablab/kernel/lib/actions/component"
|
||||
"github.com/openziti/fablab/kernel/lib/actions/host"
|
||||
"github.com/openziti/fablab/kernel/lib/actions/semaphore"
|
||||
"github.com/openziti/fablab/kernel/lib/binding"
|
||||
"github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key"
|
||||
"github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore"
|
||||
"github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform"
|
||||
distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution"
|
||||
"github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync"
|
||||
aws_ssh_key2 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key"
|
||||
"github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform"
|
||||
"github.com/openziti/fablab/kernel/model"
|
||||
"github.com/openziti/fablab/resources"
|
||||
"github.com/openziti/foundation/v2/stringz"
|
||||
"github.com/openziti/ziti/zititest/models/test_resources"
|
||||
"github.com/openziti/ziti/zititest/zitilab"
|
||||
"github.com/openziti/ziti/zititest/zitilab/actions/edge"
|
||||
"github.com/openziti/ziti/zititest/zitilab/models"
|
||||
"go.etcd.io/bbolt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
EnrollIdentitiesAction = "enrollIdentities"
|
||||
)
|
||||
|
||||
const (
|
||||
useLatestZitiOnRouters = true
|
||||
)
|
||||
|
||||
//go:embed configs
|
||||
var configResource embed.FS
|
||||
|
||||
var dbStrategyInstance = &dbStrategy{
|
||||
routerMappings: map[string]string{},
|
||||
}
|
||||
|
||||
type dbStrategy struct {
|
||||
routerMappings map[string]string
|
||||
}
|
||||
|
||||
func (self *dbStrategy) ProcessDbModel(tx *bbolt.Tx, m *model.Model, builder *models.ZitiDbBuilder) error {
|
||||
dbFile := self.GetDbFile(m)
|
||||
dbDir := path.Dir(dbFile)
|
||||
mapFile := path.Join(dbDir, "edge-router-mapping.csv")
|
||||
mapContents, err := os.ReadFile(mapFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read edge router mapping file (%w)", err)
|
||||
}
|
||||
|
||||
if err = self.loadErMap(string(mapContents)); err != nil {
|
||||
return fmt.Errorf("unable to parse router mapping file (%w)", err)
|
||||
}
|
||||
|
||||
if err = self.ProcessEdgeRouters(tx, m, builder); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = self.CreateEnrollIdentitiesAction(tx, m, builder); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *dbStrategy) loadErMap(csv string) error {
|
||||
sc := bufio.NewScanner(strings.NewReader(csv))
|
||||
for sc.Scan() {
|
||||
parts := strings.Split(sc.Text(), ",")
|
||||
if len(parts) >= 2 {
|
||||
routerId := parts[0]
|
||||
nfVersion := parts[1]
|
||||
zitiVersion := nfZitiVersionMap[nfVersion]
|
||||
self.routerMappings[routerId] = zitiVersion
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *dbStrategy) GetDbFile(m *model.Model) string {
|
||||
return m.MustStringVariable("db_file")
|
||||
}
|
||||
|
||||
func (self *dbStrategy) ProcessEdgeRouters(tx *bbolt.Tx, m *model.Model, builder *models.ZitiDbBuilder) error {
|
||||
ids, _, err := builder.GetStores().EdgeRouter.QueryIds(tx, "true limit none")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
versions := map[string]int{}
|
||||
hostsPerRegion := ((len(ids) / len(sites)) / 20) + 1
|
||||
|
||||
hostIdF := func(regionId string, idx int) string {
|
||||
return fmt.Sprintf("%s-r%d", regionId[:len(regionId)-2], idx)
|
||||
}
|
||||
|
||||
echoServerIdF := func(regionId string, idx int) string {
|
||||
return fmt.Sprintf("%s-echo%d", regionId[:len(regionId)-2], idx)
|
||||
}
|
||||
|
||||
simCount := 0
|
||||
|
||||
for _, site := range sites {
|
||||
regionId := site[:len(site)-1]
|
||||
region := m.Regions[regionId]
|
||||
|
||||
if region != nil && region.Site != site {
|
||||
return fmt.Errorf("trying to add region for site %v, but one exists, with different site", site)
|
||||
}
|
||||
|
||||
if region == nil {
|
||||
region = &model.Region{
|
||||
Id: regionId,
|
||||
Scope: model.Scope{Tags: model.Tags{}},
|
||||
Region: regionId,
|
||||
Site: site,
|
||||
Hosts: model.Hosts{},
|
||||
}
|
||||
m.Regions[regionId] = region
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
simCount++
|
||||
simId := fmt.Sprintf("sim%02d", simCount)
|
||||
region.Hosts[simId] = &model.Host{
|
||||
InstanceType: "t3.small",
|
||||
Components: model.Components{
|
||||
simId: {
|
||||
Scope: model.Scope{Tags: model.Tags{"sim"}},
|
||||
Type: &zitilab.SimpleSimType{
|
||||
ConfigPath: "identities",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < hostsPerRegion; i++ {
|
||||
hostId := hostIdF(regionId, i)
|
||||
routerHost := &model.Host{
|
||||
Id: hostId,
|
||||
Scope: model.Scope{Tags: model.Tags{}},
|
||||
Region: region,
|
||||
Components: model.Components{
|
||||
echoServerIdF(regionId, i): {
|
||||
Scope: model.Scope{Tags: model.Tags{"server"}},
|
||||
Type: &zitilab.EchoServerType{
|
||||
Port: 8888,
|
||||
},
|
||||
},
|
||||
},
|
||||
InstanceType: "t3.large",
|
||||
ScaleIndex: uint32(i),
|
||||
}
|
||||
region.Hosts[hostId] = routerHost
|
||||
}
|
||||
}
|
||||
|
||||
siteIdx := 0
|
||||
hostIdx := 0
|
||||
|
||||
for _, id := range ids {
|
||||
er, err := builder.GetStores().EdgeRouter.LoadById(tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if siteIdx >= len(sites) {
|
||||
siteIdx = 0
|
||||
hostIdx++
|
||||
if hostIdx >= hostsPerRegion {
|
||||
hostIdx = 0
|
||||
}
|
||||
}
|
||||
|
||||
site := sites[siteIdx]
|
||||
regionId := site[:len(site)-1]
|
||||
region := m.Regions[regionId]
|
||||
hostId := hostIdF(regionId, hostIdx)
|
||||
routerHost := region.Hosts[hostId]
|
||||
|
||||
siteIdx++
|
||||
|
||||
version := ""
|
||||
if !useLatestZitiOnRouters {
|
||||
version = self.routerMappings[id]
|
||||
if replacement, found := versionMapping[version]; found {
|
||||
version = replacement
|
||||
}
|
||||
versions[version] = versions[version] + 1
|
||||
}
|
||||
|
||||
routerComponent := &model.Component{
|
||||
Scope: model.Scope{Tags: model.Tags{"router", "pre-created"}},
|
||||
Type: &zitilab.RouterType{
|
||||
Version: version,
|
||||
},
|
||||
Host: routerHost,
|
||||
ScaleIndex: uint32(len(routerHost.Components)),
|
||||
}
|
||||
|
||||
routerHost.Components[er.Id] = routerComponent
|
||||
|
||||
if er.IsTunnelerEnabled {
|
||||
routerComponent.Scope.Tags = append(routerComponent.Scope.Tags, "tunneler")
|
||||
}
|
||||
|
||||
if stringz.Contains(er.RoleAttributes, "public") {
|
||||
routerComponent.Scope.Tags = append(routerComponent.Scope.Tags, "public")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *dbStrategy) CreateEnrollIdentitiesAction(tx *bbolt.Tx, m *model.Model, builder *models.ZitiDbBuilder) error {
|
||||
ids, _, err := builder.GetStores().Identity.QueryIds(tx, `type != "Router" limit none`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Actions[EnrollIdentitiesAction] = func(m *model.Model) model.Action {
|
||||
return model.ActionFunc(func(run model.Run) error {
|
||||
return provisionIdentities(ids, run)
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var m = &model.Model{
|
||||
Id: "db-ctrl-test",
|
||||
Scope: model.Scope{
|
||||
Defaults: model.Variables{
|
||||
"environment": "ctrl-test",
|
||||
"credentials": model.Variables{
|
||||
"aws": model.Variables{
|
||||
"managed_key": true,
|
||||
},
|
||||
"ssh": model.Variables{
|
||||
"username": "ubuntu",
|
||||
},
|
||||
"edge": model.Variables{
|
||||
"username": "admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
StructureFactories: []model.Factory{
|
||||
&models.ZitiDbBuilder{Strategy: dbStrategyInstance},
|
||||
},
|
||||
Resources: model.Resources{
|
||||
resources.Configs: resources.SubFolder(configResource, "configs"),
|
||||
resources.Binaries: os.DirFS(path.Join(os.Getenv("GOPATH"), "bin")),
|
||||
resources.Terraform: test_resources.TerraformResources(),
|
||||
},
|
||||
Regions: model.Regions{
|
||||
"us-east-1": {
|
||||
Region: "us-east-1",
|
||||
Site: "us-east-1c",
|
||||
Hosts: model.Hosts{
|
||||
"ctrl": {
|
||||
InstanceType: "c5.9xlarge",
|
||||
InstanceResourceType: "ondemand_iops",
|
||||
EC2: model.EC2Host{
|
||||
Volume: model.EC2Volume{
|
||||
Type: "gp3",
|
||||
SizeGB: 16,
|
||||
IOPS: 3000,
|
||||
},
|
||||
},
|
||||
Components: model.Components{
|
||||
"ctrl": {
|
||||
Scope: model.Scope{Tags: model.Tags{"ctrl"}},
|
||||
Type: &zitilab.ControllerType{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Actions: model.ActionBinders{
|
||||
"bootstrap": model.ActionBinder(func(m *model.Model) model.Action {
|
||||
workflow := actions.Workflow()
|
||||
|
||||
workflow.AddAction(component.StopInParallel("*", 200))
|
||||
workflow.AddAction(host.GroupExec("*", 25, "rm -f logs/*"))
|
||||
|
||||
workflow.AddAction(component.Start("#ctrl"))
|
||||
workflow.AddAction(semaphore.Sleep(2 * time.Second))
|
||||
|
||||
workflow.AddAction(edge.Login("#ctrl"))
|
||||
|
||||
workflow.AddAction(model.ActionFunc(provisionRouters))
|
||||
workflow.AddAction(m.ExecuteAction("syncRouterJwts"))
|
||||
workflow.AddAction(model.ActionFunc(enrollRouters))
|
||||
|
||||
workflow.AddAction(m.ExecuteAction(EnrollIdentitiesAction))
|
||||
workflow.AddAction(model.ActionFunc(func(run model.Run) error {
|
||||
src := model.MakeBuildPath("identities")
|
||||
return rsync.RsyncSelected("component.sim", src, "identities").Execute(run)
|
||||
}))
|
||||
return workflow
|
||||
}),
|
||||
"syncRouterJwts": model.Bind(model.ActionFunc(func(run model.Run) error {
|
||||
src := model.MakeBuildPath("router-jwts")
|
||||
return rsync.RsyncSelected("component.router", src, "router-jwts").Execute(run)
|
||||
})),
|
||||
"stop": model.Bind(component.StopInParallel("*", 200)),
|
||||
"clean": model.Bind(actions.Workflow(
|
||||
component.StopInParallel("*", 200),
|
||||
host.GroupExec("*", 25, "rm -f logs/*"),
|
||||
)),
|
||||
"login": model.Bind(edge.Login("#ctrl")),
|
||||
},
|
||||
|
||||
Infrastructure: model.Stages{
|
||||
aws_ssh_key.Express(),
|
||||
terraform_0.Express(),
|
||||
semaphore_0.Ready(90 * time.Second),
|
||||
},
|
||||
|
||||
Distribution: model.Stages{
|
||||
distribution.DistributeSshKey("*"),
|
||||
rsync.RsyncStaged(),
|
||||
model.StageActionF(func(run model.Run) error {
|
||||
quickRun, _ := run.GetModel().GetBoolVariable("quick_run")
|
||||
_, targetedSync := run.GetModel().Scope.GetVariable("sync.target")
|
||||
|
||||
if !quickRun && !targetedSync {
|
||||
dbFile := dbStrategyInstance.GetDbFile(run.GetModel())
|
||||
deferred := rsync.NewRsyncHost("#ctrl", dbFile, "/home/ubuntu/ctrl.db")
|
||||
return deferred.Execute(run)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
|
||||
Disposal: model.Stages{
|
||||
terraform.Dispose(),
|
||||
aws_ssh_key2.Dispose(),
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
m.AddActivationActions("bootstrap")
|
||||
|
||||
model.AddBootstrapExtension(binding.AwsCredentialsLoader)
|
||||
model.AddBootstrapExtension(aws_ssh_key.KeyManager)
|
||||
|
||||
fablab.InitModel(m)
|
||||
fablab.Run()
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright 2019 NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
var versionMapping = map[string]string{
|
||||
"": "0.31.4",
|
||||
"0.30.4": "0.30.5",
|
||||
"0.31.0": "0.31.4",
|
||||
"0.29.0": "0.28.1",
|
||||
"0.25.2": "0.28.1",
|
||||
"0.26.10": "0.28.1",
|
||||
}
|
||||
|
||||
var sites = []string{
|
||||
"us-east-1c",
|
||||
"us-west-2b",
|
||||
"eu-west-2a",
|
||||
"eu-central-1a",
|
||||
"ap-southeast-2a",
|
||||
}
|
||||
|
||||
var nfZitiVersionMap = map[string]string{
|
||||
"7.3.54": "0.24.3",
|
||||
"7.3.77": "0.26.7",
|
||||
"7.3.36": "0.20.13",
|
||||
"7.3.45": "0.22.7",
|
||||
"7.3.91": "0.28.1",
|
||||
"7.3.58": "0.24.8",
|
||||
"8.0.96": "0.31.0",
|
||||
"7.3.32": "0.20.9",
|
||||
"8.0.95": "0.30.5",
|
||||
"7.3.92": "0.28.4",
|
||||
"7.3.69": "0.25.13",
|
||||
"7.3.57": "0.24.7",
|
||||
"7.3.98": "0.31.4",
|
||||
"7.3.71": "0.26.1",
|
||||
"7.3.93": "0.29.0",
|
||||
"7.3.22": "0.19.8",
|
||||
"7.3.43": "0.22.4",
|
||||
"7.3.31": "0.20.8",
|
||||
"7.3.24": "0.19.10",
|
||||
"7.3.87": "0.27.7",
|
||||
"7.3.55": "0.24.4",
|
||||
"7.3.86": "0.27.6",
|
||||
"7.3.4": "0.17.5",
|
||||
"7.3.25": "0.19.11",
|
||||
"7.3.74": "0.26.4",
|
||||
"7.3.81": "0.27.0",
|
||||
"7.3.12": "0.18.9",
|
||||
"8.0.98": "0.31.4",
|
||||
"7.3.7": "0.18.3",
|
||||
"7.3.51": "0.23.1",
|
||||
"7.3.13": "0.18.10",
|
||||
"7.3.5": "0.18.0",
|
||||
"7.3.48": "0.22.10",
|
||||
"7.3.30": "0.20.3",
|
||||
"7.3.9": "0.18.5",
|
||||
"7.3.94": "0.30.4",
|
||||
"7.3.23": "0.19.9",
|
||||
"7.3.89": "0.27.9",
|
||||
"7.3.41": "0.22.2",
|
||||
"8.0.94": "0.30.4",
|
||||
"7.3.62": "0.25.2",
|
||||
"7.3.19": "0.19.5",
|
||||
"7.3.65": "0.25.5",
|
||||
"7.3.67": "0.25.8",
|
||||
"7.3.11": "0.18.8",
|
||||
"7.3.73": "0.26.3",
|
||||
"7.3.61": "0.24.13",
|
||||
"7.3.14": "0.19.0",
|
||||
"7.3.96": "0.31.0",
|
||||
"7.3.82": "0.27.2",
|
||||
"7.3.34": "0.20.11",
|
||||
"7.3.78": "0.26.8",
|
||||
"7.3.50": "0.23.0",
|
||||
"7.3.90": "0.28.0",
|
||||
"7.3.44": "0.22.6",
|
||||
"7.3.56": "0.24.6",
|
||||
"7.3.35": "0.20.12",
|
||||
"7.3.64": "0.25.4",
|
||||
"8.0.99": "0.32.2",
|
||||
"7.3.49": "0.22.11",
|
||||
"7.3.59": "0.24.9",
|
||||
"7.3.88": "0.27.8",
|
||||
"7.3.97": "0.31.2",
|
||||
"7.3.52": "0.24.1",
|
||||
"7.3.99": "0.32.2",
|
||||
"7.3.29": "0.20.2",
|
||||
"7.3.72": "0.26.2",
|
||||
"7.3.37": "0.20.14",
|
||||
"7.3.53": "0.24.2",
|
||||
"7.3.10": "0.18.7",
|
||||
"7.3.33": "0.20.10",
|
||||
"7.3.26": "0.19.12",
|
||||
"7.3.15": "0.19.1",
|
||||
"7.3.38": "0.21.0",
|
||||
"7.3.63": "0.25.3",
|
||||
"7.3.46": "0.22.8",
|
||||
"7.3.28": "0.20.1",
|
||||
"7.3.75": "0.26.5",
|
||||
"7.3.39": "0.22.0",
|
||||
"8.0.100": "0.33.1",
|
||||
"7.3.60": "0.24.12",
|
||||
"7.3.95": "0.30.5",
|
||||
"7.3.21": "0.19.7",
|
||||
"8.0.85": "0.27.5",
|
||||
"7.3.18": "0.19.4",
|
||||
"7.3.6": "0.18.2",
|
||||
"7.3.76": "0.26.6",
|
||||
"7.3.42": "0.22.3",
|
||||
"7.3.16": "0.19.2",
|
||||
"7.3.20": "0.19.6",
|
||||
"8.0.97": "0.31.2",
|
||||
"7.3.70": "0.26.0",
|
||||
"7.3.68": "0.25.10",
|
||||
"7.3.66": "0.25.6",
|
||||
"7.3.84": "0.27.4",
|
||||
"7.3.8": "0.18.4",
|
||||
"7.3.27": "0.19.13",
|
||||
"8.0.93": "0.29.0",
|
||||
"7.3.85": "0.27.5",
|
||||
"7.3.17": "0.19.3",
|
||||
"7.3.80": "0.26.11",
|
||||
"7.3.100": "0.33.1",
|
||||
"7.3.79": "0.26.10",
|
||||
"7.3.40": "0.22.1",
|
||||
"8.0.92": "0.28.4",
|
||||
"7.3.83": "0.27.3",
|
||||
"8.0.91": "0.28.1",
|
||||
"7.3.47": "0.22.9",
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright 2019 NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/fablab/kernel/lib/parallel"
|
||||
"github.com/openziti/fablab/kernel/model"
|
||||
"github.com/openziti/ziti/zititest/zitilab"
|
||||
zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions"
|
||||
"github.com/openziti/ziti/zititest/zitilab/cli"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func provisionIdentities(identities []string, run model.Run) error {
|
||||
var tasks []parallel.Task
|
||||
|
||||
identitiesDir := model.MakeBuildPath("identities")
|
||||
_ = os.MkdirAll(identitiesDir, 0770)
|
||||
for _, v := range identities {
|
||||
id := v
|
||||
task := func() error {
|
||||
jwtFileName := filepath.Join(identitiesDir, id+".jwt")
|
||||
args := []string{"create", "enrollment", "ott", "--jwt-output-file", jwtFileName, "--", id}
|
||||
|
||||
if err := zitilib_actions.EdgeExec(run.GetModel(), args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := cli.Exec(m, "edge", "enroll", "--", jwtFileName); err != nil {
|
||||
return fmt.Errorf("failed to enroll %s (%w)", id, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
tasks = append(tasks, task)
|
||||
}
|
||||
|
||||
if err := parallel.Execute(tasks, 10); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func provisionRouters(run model.Run) error {
|
||||
routerPkiDir := model.MakeBuildPath("router-jwts")
|
||||
_ = os.MkdirAll(routerPkiDir, 0770)
|
||||
|
||||
return run.GetModel().ForEachComponent(".router.pre-created", 15, func(c *model.Component) error {
|
||||
jwtFileName := filepath.Join(routerPkiDir, c.Id+".jwt")
|
||||
args := []string{"re-enroll", "edge-router", "-j", "--jwt-output-file", jwtFileName, "--", c.Id}
|
||||
return zitilib_actions.EdgeExec(c.GetModel(), args...)
|
||||
})
|
||||
}
|
||||
|
||||
func enrollRouters(run model.Run) error {
|
||||
zitiVersion := ""
|
||||
ctrls := run.GetModel().SelectComponents(".ctrl")
|
||||
for _, ctrl := range ctrls {
|
||||
if ctrl.Type != nil {
|
||||
zitiVersion = ctrl.Type.GetVersion()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return run.GetModel().ForEachHost("component.router", 15, func(h *model.Host) error {
|
||||
var cmds []string
|
||||
cmds = append(cmds, "mkdir -p /home/ubuntu/router-pki/")
|
||||
hostUser := h.GetSshUser()
|
||||
for _, c := range h.Components {
|
||||
var routerType *zitilab.RouterType
|
||||
var ok bool
|
||||
if routerType, ok = c.Type.(*zitilab.RouterType); !ok || !c.HasTag("pre-created") {
|
||||
continue
|
||||
}
|
||||
|
||||
remoteJwt := fmt.Sprintf("/home/%s/router-jwts/%s.jwt", hostUser, c.Id)
|
||||
tmpl := "set -o pipefail; %s router enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log "
|
||||
cmd := fmt.Sprintf(tmpl, zitilab.GetZitiBinaryPath(c, zitiVersion), routerType.GetConfigName(c), remoteJwt, c.Id)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
return h.ExecLogOnlyOnError(cmds...)
|
||||
})
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (d dbStrategy) PostProcess(router *db.EdgeRouter, c *model.Component) {
|
||||
}
|
||||
|
||||
func (d dbStrategy) ProcessDbModel(tx *bbolt.Tx, m *model.Model, builder *models.ZitiDbBuilder) error {
|
||||
if err := builder.CreateEdgeRouterHosts(tx, m); err != nil {
|
||||
if err := builder.CreateEdgeRouterHosts(tx, m, d); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.CreateIdentityHosts(tx, m, builder)
|
||||
|
||||
@@ -100,7 +100,7 @@ var m = &model.Model{
|
||||
}),
|
||||
model.FactoryFunc(func(m *model.Model) error {
|
||||
return m.ForEachHost("component.router", 1, func(host *model.Host) error {
|
||||
host.InstanceType = "c5.xlarge"
|
||||
host.InstanceType = "t3.large"
|
||||
return nil
|
||||
})
|
||||
}),
|
||||
|
||||
@@ -58,7 +58,7 @@ func (self scaleStrategy) GetEntityCount(entity model.Entity) uint32 {
|
||||
type dbStrategy struct{}
|
||||
|
||||
func (d dbStrategy) ProcessDbModel(tx *bbolt.Tx, m *model.Model, builder *models.ZitiDbBuilder) error {
|
||||
return builder.CreateEdgeRouterHosts(tx, m)
|
||||
return builder.CreateEdgeRouterHosts(tx, m, d)
|
||||
}
|
||||
|
||||
func (d dbStrategy) GetDbFile(*model.Model) string {
|
||||
|
||||
@@ -68,7 +68,7 @@ func (self *stageFactory) Build(m *model.Model) error {
|
||||
distribution.Locations(models.HasRouterComponent, "logs"),
|
||||
distribution.Locations(models.LoopListenerTag, "logs"),
|
||||
distribution.Locations(models.LoopDialerTag, "logs"),
|
||||
rsync.Rsync(1),
|
||||
rsync.RsyncStaged(),
|
||||
}
|
||||
|
||||
// Run the bootstrap and start actions
|
||||
|
||||
@@ -208,7 +208,9 @@ var Model = &model.Model{
|
||||
},
|
||||
"echo-server": {
|
||||
Scope: model.Scope{Tags: model.Tags{"sdk-app", "service"}},
|
||||
Type: &zitilab.EchoServerType{},
|
||||
Type: &zitilab.EchoServerType{
|
||||
BindService: "echo",
|
||||
},
|
||||
},
|
||||
"iperf-server-ert": {
|
||||
Scope: model.Scope{Tags: model.Tags{"iperf", "service"}},
|
||||
|
||||
@@ -34,6 +34,11 @@ module "{{ $regionId }}_host_{{ $hostId }}" {
|
||||
spot_price = "{{ $host.SpotPrice }}"
|
||||
spot_type = "{{ $host.SpotType }}"
|
||||
name = "{{ $region.Model.MustVariable "environment" }}.{{ $host.Id }}"
|
||||
{{ if not (eq $host.EC2.Volume.Type "") }}
|
||||
volume_type = "{{ $host.EC2.Volume.Type }}"
|
||||
volume_size = "{{ $host.EC2.Volume.SizeGB }}"
|
||||
volume_iops = "{{ $host.EC2.Volume.IOPS }}"
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
output "{{ $regionId }}_host_{{ $hostId }}_public_ip" { value = module.{{ $regionId }}_host_{{ $hostId }}.public_ip }
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
variable "name" {}
|
||||
variable "access_key" {}
|
||||
variable "secret_key" {}
|
||||
variable "environment_tag" { default = "" }
|
||||
variable "instance_type" {}
|
||||
variable "key_name" {}
|
||||
variable "key_path" {}
|
||||
variable "region" {}
|
||||
variable "security_group_id" {}
|
||||
variable "ssh_user" { default = "ubuntu" }
|
||||
variable "subnet_id" {}
|
||||
variable "spot_price" {}
|
||||
variable "spot_type" {}
|
||||
variable "volume_type" { default = "gp2" }
|
||||
variable "volume_size" { default = 4 }
|
||||
variable "volume_iops" {}
|
||||
|
||||
output "public_ip" { value = aws_instance.fablab.public_ip }
|
||||
output "private_ip" { value = aws_instance.fablab.private_ip }
|
||||
|
||||
provider "aws" {
|
||||
access_key = var.access_key
|
||||
secret_key = var.secret_key
|
||||
region = var.region
|
||||
}
|
||||
|
||||
data "aws_ami" "ami" {
|
||||
most_recent = true
|
||||
owners = ["self"]
|
||||
|
||||
filter {
|
||||
name = "name"
|
||||
values = ["ziti-tests-*"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "fablab" {
|
||||
ami = data.aws_ami.ami.id
|
||||
instance_type = var.instance_type
|
||||
key_name = var.key_name
|
||||
vpc_security_group_ids = [var.security_group_id]
|
||||
subnet_id = var.subnet_id
|
||||
associate_public_ip_address = true
|
||||
|
||||
root_block_device {
|
||||
volume_type = var.volume_type
|
||||
volume_size = var.volume_size
|
||||
iops = var.volume_iops
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = var.name
|
||||
cost_environment = "non-production"
|
||||
cost_category = "CICD"
|
||||
cost_team_owner = "ADVDEV"
|
||||
source = "fablab"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
Copyright NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/edge-api/rest_model"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/ziti/common/eid"
|
||||
cmap "github.com/orcaman/concurrent-map/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"time"
|
||||
)
|
||||
|
||||
type simpleSimAction struct {
|
||||
verbose bool
|
||||
logFormatter string
|
||||
configFile string
|
||||
|
||||
authenticated cmap.ConcurrentMap[string, time.Time]
|
||||
}
|
||||
|
||||
func newSimpleSimCmd() *cobra.Command {
|
||||
action := &simpleSimAction{
|
||||
authenticated: cmap.New[time.Time](),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "simple-sim <config file or directory>",
|
||||
Short: "Generates traffic to one more ziti identities",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: action.run,
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().BoolVarP(&action.verbose, "verbose", "v", false, "Enable verbose logging")
|
||||
cmd.Flags().StringVar(&action.logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]")
|
||||
cmd.Flags().StringVarP(&action.configFile, "identity", "i", "", "Specify the Ziti identity to use. If not specified the Ziti listener won't be started")
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *simpleSimAction) initLogging() {
|
||||
logLevel := logrus.InfoLevel
|
||||
if self.verbose {
|
||||
logLevel = logrus.DebugLevel
|
||||
}
|
||||
|
||||
options := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor()
|
||||
pfxlog.GlobalInit(logLevel, options)
|
||||
|
||||
switch self.logFormatter {
|
||||
case "pfxlog":
|
||||
pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday()))
|
||||
case "json":
|
||||
pfxlog.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02T15:04:05.000Z"})
|
||||
case "text":
|
||||
pfxlog.SetFormatter(&logrus.TextFormatter{})
|
||||
default:
|
||||
// let logrus do its own thing
|
||||
}
|
||||
}
|
||||
|
||||
func (self *simpleSimAction) run(_ *cobra.Command, args []string) {
|
||||
self.initLogging()
|
||||
|
||||
log := pfxlog.Logger()
|
||||
|
||||
fsInfo, err := os.Stat(args[0])
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("unable to stat config file/dir %s", args[0])
|
||||
return
|
||||
}
|
||||
|
||||
simCount := 0
|
||||
if fsInfo.IsDir() {
|
||||
files, err := os.ReadDir(args[0])
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("failed to scan directory %s:", args[0])
|
||||
return
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) == ".json" {
|
||||
fn, err := filepath.Abs(filepath.Join(args[0], file.Name()))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listing file %s: %v", file.Name(), err)
|
||||
}
|
||||
self.startSimForIdentity(fn)
|
||||
simCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
time.Sleep(time.Second * 5)
|
||||
pfxlog.Logger().Infof("%d/%d identities authenticated", self.authenticated.Count(), simCount)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *simpleSimAction) startSimForIdentity(path string) {
|
||||
log := pfxlog.Logger().WithField("config", path)
|
||||
|
||||
zitiConfig, err := ziti.NewConfigFromFile(path)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("unable to load ziti identity")
|
||||
return
|
||||
}
|
||||
|
||||
zitiContext, err := ziti.NewContext(zitiConfig)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("could not create sdk context from config")
|
||||
}
|
||||
|
||||
go self.runSim(path, zitiContext)
|
||||
}
|
||||
|
||||
func (self *simpleSimAction) runSim(path string, ctx ziti.Context) {
|
||||
log := pfxlog.Logger().WithField("config", path)
|
||||
|
||||
var lastLog time.Time
|
||||
cycle := 0
|
||||
|
||||
for {
|
||||
cycle++
|
||||
validServices := 0
|
||||
dialSuccesses := 0
|
||||
services, err := ctx.GetServices()
|
||||
if err != nil {
|
||||
self.authenticated.Remove(ctx.GetId())
|
||||
log.WithField("cycle", cycle).WithError(err).Error("unable to list services")
|
||||
time.Sleep(time.Second * 5)
|
||||
continue
|
||||
} else {
|
||||
self.authenticated.Set(ctx.GetId(), time.Now())
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
if !slices.Contains(service.Permissions, rest_model.DialBindDial) {
|
||||
continue
|
||||
}
|
||||
validServices++
|
||||
|
||||
svcLog := log.WithField("svc", *service.Name).WithField("cycle", cycle)
|
||||
conn, err := ctx.Dial(*service.Name)
|
||||
if err != nil {
|
||||
svcLog.WithError(err).Error("unable to dial service")
|
||||
} else {
|
||||
randomString := eid.New()
|
||||
if _, err = conn.Write([]byte(randomString)); err != nil {
|
||||
svcLog.WithError(err).Error("unable to write")
|
||||
} else {
|
||||
result := make([]byte, len(randomString))
|
||||
n, err := conn.Read(result)
|
||||
if err != nil {
|
||||
svcLog.WithError(err).Error("unable to read")
|
||||
} else {
|
||||
result = result[:n]
|
||||
if string(result) != randomString {
|
||||
svcLog.WithError(err).Error("%s != %s", randomString, result)
|
||||
} else {
|
||||
dialSuccesses++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if conn != nil {
|
||||
if err = conn.Close(); err != nil {
|
||||
svcLog.WithError(err).Error("error closing conn")
|
||||
}
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
}
|
||||
}
|
||||
|
||||
if time.Since(lastLog) > time.Minute {
|
||||
log.WithField("serviceCount", len(services)).
|
||||
WithField("cycle", cycle).
|
||||
WithField("successfulDials", fmt.Sprintf("%d/%d", dialSuccesses, validServices)).
|
||||
Info("completed")
|
||||
lastLog = time.Now()
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(500+rand.Intn(1000)) * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
cli := newSimpleSimCmd()
|
||||
if err := cli.Execute(); err != nil {
|
||||
pfxlog.Logger().Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/transport/v2"
|
||||
"github.com/openziti/transport/v2/tcp"
|
||||
@@ -28,7 +26,6 @@ import (
|
||||
"github.com/openziti/transport/v2/transwarp"
|
||||
"github.com/openziti/transport/v2/transwarptls"
|
||||
"github.com/openziti/transport/v2/wss"
|
||||
"github.com/openziti/foundation/v2/info"
|
||||
"github.com/openziti/ziti/zititest/ziti-fabric-test/subcmd"
|
||||
_ "github.com/openziti/ziti/zititest/ziti-fabric-test/subcmd/client"
|
||||
_ "github.com/openziti/ziti/zititest/ziti-fabric-test/subcmd/loop2"
|
||||
@@ -46,6 +43,5 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(info.NowInMilliseconds())
|
||||
subcmd.Execute()
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func Exec(m *model.Model, args ...string) (string, error) {
|
||||
ziticli.SetArgs(args)
|
||||
logrus.Infof("executing: %s", strings.Join(args, " "))
|
||||
if err := ziticli.Execute(); err != nil {
|
||||
logrus.Errorf("err executing command, err:[%e]", err)
|
||||
logrus.WithError(err).Error("err executing command")
|
||||
}
|
||||
|
||||
return cliOut.String(), nil
|
||||
|
||||
@@ -38,7 +38,7 @@ func getZitiProcessFilter(c *model.Component, zitiType string) func(string) bool
|
||||
func startZitiComponent(c *model.Component, zitiType string, version string, configName string) error {
|
||||
user := c.GetHost().GetSshUser()
|
||||
|
||||
binaryPath := getZitiBinaryPath(c, version)
|
||||
binaryPath := GetZitiBinaryPath(c, version)
|
||||
configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s", user, configName)
|
||||
logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
|
||||
|
||||
@@ -74,7 +74,7 @@ func canonicalizeGoAppVersion(version *string) {
|
||||
}
|
||||
}
|
||||
|
||||
func getZitiBinaryPath(c *model.Component, version string) string {
|
||||
func GetZitiBinaryPath(c *model.Component, version string) string {
|
||||
return getBinaryPath(c, "ziti", version)
|
||||
}
|
||||
|
||||
@@ -114,3 +114,19 @@ func reEnrollIdentity(run model.Run, c *model.Component, zitiBinaryPath string,
|
||||
|
||||
return c.GetHost().ExecLogOnlyOnError(cmd)
|
||||
}
|
||||
|
||||
func setupDnsForTunneler(c *model.Component) error {
|
||||
key := "ziti_tunnel.resolve_setup_done"
|
||||
if _, found := c.Host.Data[key]; !found {
|
||||
cmds := []string{
|
||||
"sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf",
|
||||
"sudo systemctl restart systemd-resolved",
|
||||
}
|
||||
if err := c.Host.ExecLogOnlyOnError(cmds...); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Host.Data[key] = true
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -45,6 +45,14 @@ type ControllerType struct {
|
||||
DNSNames []string
|
||||
}
|
||||
|
||||
func (self *ControllerType) Label() string {
|
||||
return "ziti-controller"
|
||||
}
|
||||
|
||||
func (self *ControllerType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ControllerType) InitType(*model.Component) {
|
||||
canonicalizeGoAppVersion(&self.Version)
|
||||
}
|
||||
@@ -104,7 +112,15 @@ func (self *ControllerType) IsRunning(_ model.Run, c *model.Component) (bool, er
|
||||
return len(pids) > 0, nil
|
||||
}
|
||||
|
||||
func (self *ControllerType) Start(_ model.Run, c *model.Component) error {
|
||||
func (self *ControllerType) Start(r model.Run, c *model.Component) error {
|
||||
isRunninng, err := self.IsRunning(r, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isRunninng {
|
||||
fmt.Printf("controller %s already started\n", c.Id)
|
||||
return nil
|
||||
}
|
||||
return startZitiComponent(c, "controller", self.Version, self.getConfigName(c))
|
||||
}
|
||||
|
||||
@@ -113,7 +129,7 @@ func (self *ControllerType) Stop(_ model.Run, c *model.Component) error {
|
||||
}
|
||||
|
||||
func (self *ControllerType) GetBinaryPath(c *model.Component) string {
|
||||
return getZitiBinaryPath(c, self.Version)
|
||||
return GetZitiBinaryPath(c, self.Version)
|
||||
}
|
||||
|
||||
func (self *ControllerType) InitStandalone(run model.Run, c *model.Component) error {
|
||||
@@ -130,7 +146,7 @@ func (self *ControllerType) InitStandalone(run model.Run, c *model.Component) er
|
||||
|
||||
factory := c.GetHost().NewSshConfigFactory()
|
||||
|
||||
binaryPath := getZitiBinaryPath(c, self.Version)
|
||||
binaryPath := GetZitiBinaryPath(c, self.Version)
|
||||
configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s", factory.User(), self.getConfigName(c))
|
||||
|
||||
tmpl := "rm -f /home/%v/fablab/ctrl.db && set -o pipefail; %s controller --log-formatter pfxlog edge init %s -u %s -p %s 2>&1 | tee logs/controller.edge.init.log"
|
||||
@@ -142,7 +158,7 @@ func (self *ControllerType) InitRaft(run model.Run, c *model.Component) error {
|
||||
count := 0
|
||||
err := run.GetModel().ForEachComponent("*", 1, func(other *model.Component) error {
|
||||
if _, ok := c.Type.(*ControllerType); ok {
|
||||
binaryPath := getZitiBinaryPath(c, self.Version)
|
||||
binaryPath := GetZitiBinaryPath(c, self.Version)
|
||||
tmpl := "%s agent cluster add %v --id %v"
|
||||
cmd := fmt.Sprintf(tmpl, binaryPath, "tls:"+other.Host.PublicIp+":6262", other.Id)
|
||||
count++
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright 2019 NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package zitilab
|
||||
|
||||
import (
|
||||
@@ -13,8 +29,18 @@ var _ model.ComponentType = (*EchoServerType)(nil)
|
||||
type EchoServerMode int
|
||||
|
||||
type EchoServerType struct {
|
||||
Version string
|
||||
LocalPath string
|
||||
Version string
|
||||
LocalPath string
|
||||
Port uint16
|
||||
BindService string
|
||||
}
|
||||
|
||||
func (self *EchoServerType) Label() string {
|
||||
return "echo-server"
|
||||
}
|
||||
|
||||
func (self *EchoServerType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *EchoServerType) InitType(*model.Component) {
|
||||
@@ -48,7 +74,7 @@ func (self *EchoServerType) IsRunning(_ model.Run, c *model.Component) (bool, er
|
||||
func (self *EchoServerType) Start(run model.Run, c *model.Component) error {
|
||||
user := c.GetHost().GetSshUser()
|
||||
|
||||
binaryPath := getZitiBinaryPath(c, self.Version)
|
||||
binaryPath := GetZitiBinaryPath(c, self.Version)
|
||||
configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s.json", user, c.Id)
|
||||
logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
|
||||
|
||||
@@ -57,8 +83,18 @@ func (self *EchoServerType) Start(run model.Run, c *model.Component) error {
|
||||
ha = "--ha"
|
||||
}
|
||||
|
||||
serviceCmd := fmt.Sprintf("nohup %s demo echo-server --cli-agent-alias %s %s -i %s > %s 2>&1 &",
|
||||
binaryPath, c.Id, ha, configPath, logsPath)
|
||||
serviceHostingFlags := ""
|
||||
if self.BindService != "" {
|
||||
serviceHostingFlags = fmt.Sprintf("-i %s -s %s", configPath, self.BindService)
|
||||
}
|
||||
|
||||
portFlag := ""
|
||||
if self.Port > 0 {
|
||||
portFlag = fmt.Sprintf("-p %d", self.Port)
|
||||
}
|
||||
|
||||
serviceCmd := fmt.Sprintf("nohup %s demo echo-server --cli-agent-alias %s %s %s %s > %s 2>&1 &",
|
||||
binaryPath, c.Id, ha, serviceHostingFlags, portFlag, logsPath)
|
||||
|
||||
value, err := c.GetHost().ExecLogged(serviceCmd)
|
||||
if err != nil {
|
||||
|
||||
@@ -29,6 +29,14 @@ type IPerfServerType struct {
|
||||
Port uint16
|
||||
}
|
||||
|
||||
func (self *IPerfServerType) Label() string {
|
||||
return "iperf-server"
|
||||
}
|
||||
|
||||
func (self *IPerfServerType) GetVersion() string {
|
||||
return "os-provided"
|
||||
}
|
||||
|
||||
func (self *IPerfServerType) Dump() any {
|
||||
return map[string]string{
|
||||
"type_id": "iperf-server",
|
||||
|
||||
@@ -19,7 +19,6 @@ package zitilab
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/fablab/kernel/lib"
|
||||
"github.com/openziti/fablab/kernel/lib/actions/host"
|
||||
"github.com/openziti/fablab/kernel/model"
|
||||
zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions"
|
||||
"github.com/openziti/ziti/zititest/zitilab/stageziti"
|
||||
@@ -45,6 +44,14 @@ type RouterType struct {
|
||||
LocalPath string
|
||||
}
|
||||
|
||||
func (self *RouterType) Label() string {
|
||||
return "ziti-router"
|
||||
}
|
||||
|
||||
func (self *RouterType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *RouterType) InitType(*model.Component) {
|
||||
canonicalizeGoAppVersion(&self.Version)
|
||||
}
|
||||
@@ -68,12 +75,7 @@ func (self *RouterType) Dump() any {
|
||||
|
||||
func (self *RouterType) InitializeHost(run model.Run, c *model.Component) error {
|
||||
if self.isTunneler(c) {
|
||||
cmds := []string{
|
||||
"sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf",
|
||||
"sudo systemctl restart systemd-resolved",
|
||||
"mkdir -p /home/ubuntu/logs",
|
||||
}
|
||||
return host.Exec(c.GetHost(), cmds...).Execute(run)
|
||||
return setupDnsForTunneler(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -84,7 +86,7 @@ func (self *RouterType) StageFiles(r model.Run, c *model.Component) error {
|
||||
configSource = "router.yml.tmpl"
|
||||
}
|
||||
|
||||
configName := self.getConfigName(c)
|
||||
configName := self.GetConfigName(c)
|
||||
|
||||
if err := lib.GenerateConfigForComponent(c, self.ConfigSourceFS, configSource, configName, r); err != nil {
|
||||
return err
|
||||
@@ -97,7 +99,7 @@ func (self *RouterType) isTunneler(c *model.Component) bool {
|
||||
return c.HasLocalOrAncestralTag("tunneler")
|
||||
}
|
||||
|
||||
func (self *RouterType) getConfigName(c *model.Component) string {
|
||||
func (self *RouterType) GetConfigName(c *model.Component) string {
|
||||
configName := self.ConfigName
|
||||
if configName == "" {
|
||||
configName = c.Id + ".yml"
|
||||
@@ -126,7 +128,7 @@ func (self *RouterType) Start(r model.Run, c *model.Component) error {
|
||||
fmt.Printf("router %s already started\n", c.Id)
|
||||
return nil
|
||||
}
|
||||
return startZitiComponent(c, "router", self.Version, self.getConfigName(c))
|
||||
return startZitiComponent(c, "router", self.Version, self.GetConfigName(c))
|
||||
}
|
||||
|
||||
func (self *RouterType) Stop(run model.Run, c *model.Component) error {
|
||||
@@ -174,15 +176,15 @@ func (self *RouterType) CreateAndEnroll(run model.Run, c *model.Component) error
|
||||
}
|
||||
|
||||
tmpl := "set -o pipefail; %s router enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log "
|
||||
cmd := fmt.Sprintf(tmpl, getZitiBinaryPath(c, self.Version), self.getConfigName(c), remoteJwt, c.Id)
|
||||
cmd := fmt.Sprintf(tmpl, GetZitiBinaryPath(c, self.Version), self.GetConfigName(c), remoteJwt, c.Id)
|
||||
|
||||
return c.GetHost().ExecLogOnlyOnError(cmd)
|
||||
}
|
||||
|
||||
func (self *RouterType) ReEnroll(_ model.Run, c *model.Component) error {
|
||||
func (self *RouterType) ReEnroll(run model.Run, c *model.Component) error {
|
||||
jwtFileName := filepath.Join(model.ConfigBuild(), c.Id+".jwt")
|
||||
|
||||
args := []string{"re-enroll", "edge-router", c.Id, "-j", "--jwt-output-file", jwtFileName}
|
||||
args := []string{"re-enroll", "edge-router", "-j", "--jwt-output-file", jwtFileName, "--", c.Id}
|
||||
|
||||
if err := zitilib_actions.EdgeExec(c.GetModel(), args...); err != nil {
|
||||
return err
|
||||
@@ -193,8 +195,18 @@ func (self *RouterType) ReEnroll(_ model.Run, c *model.Component) error {
|
||||
return err
|
||||
}
|
||||
|
||||
zitiVersion := self.Version
|
||||
|
||||
ctrls := run.GetModel().SelectComponents(".ctrl")
|
||||
for _, ctrl := range ctrls {
|
||||
if ctrl.Type != nil {
|
||||
zitiVersion = ctrl.Type.GetVersion()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
tmpl := "set -o pipefail; %s router enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log "
|
||||
cmd := fmt.Sprintf(tmpl, getZitiBinaryPath(c, self.Version), self.getConfigName(c), remoteJwt, c.Id)
|
||||
cmd := fmt.Sprintf(tmpl, GetZitiBinaryPath(c, zitiVersion), self.GetConfigName(c), remoteJwt, c.Id)
|
||||
|
||||
return c.GetHost().ExecLogOnlyOnError(cmd)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright 2019 NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package zitilab
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/fablab/kernel/model"
|
||||
"github.com/openziti/ziti/zititest/zitilab/stageziti"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ model.ComponentType = (*SimpleSimType)(nil)
|
||||
|
||||
type SimpleSimType struct {
|
||||
LocalPath string
|
||||
ConfigPath string
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) Label() string {
|
||||
return "simple-sim"
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) GetVersion() string {
|
||||
return "local"
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) Dump() any {
|
||||
return map[string]string{
|
||||
"type_id": "simple-sim",
|
||||
"local_path": self.LocalPath,
|
||||
"config_path": self.ConfigPath,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) StageFiles(r model.Run, c *model.Component) error {
|
||||
return stageziti.StageLocalOnce(r, "simple-sim", c, self.LocalPath)
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) getProcessFilter() func(string) bool {
|
||||
return func(s string) bool {
|
||||
return strings.Contains(s, "simple-sim")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
|
||||
pids, err := c.GetHost().FindProcesses(self.getProcessFilter())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(pids) > 0, nil
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) Start(_ model.Run, c *model.Component) error {
|
||||
user := c.GetHost().GetSshUser()
|
||||
|
||||
binaryPath := getBinaryPath(c, "simple-sim", "")
|
||||
logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
|
||||
configPath := fmt.Sprintf("/home/%s/%s", user, self.ConfigPath)
|
||||
|
||||
serviceCmd := fmt.Sprintf("%s %s --log-formatter pfxlog > %s 2>&1 &",
|
||||
binaryPath, configPath, logsPath)
|
||||
|
||||
value, err := c.Host.ExecLogged(
|
||||
"rm -f "+logsPath,
|
||||
serviceCmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(value) > 0 {
|
||||
logrus.Infof("output [%s]", strings.Trim(value, " \t\r\n"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SimpleSimType) Stop(_ model.Run, c *model.Component) error {
|
||||
return c.GetHost().KillProcesses("-TERM", self.getProcessFilter())
|
||||
}
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright 2019 NetFoundry Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package zitilab
|
||||
|
||||
import (
|
||||
@@ -15,6 +31,14 @@ type ZCatType struct {
|
||||
LocalPath string
|
||||
}
|
||||
|
||||
func (self *ZCatType) Label() string {
|
||||
return "zcat"
|
||||
}
|
||||
|
||||
func (self *ZCatType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ZCatType) InitType(*model.Component) {
|
||||
canonicalizeGoAppVersion(&self.Version)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,14 @@ type ZitiEdgeTunnelType struct {
|
||||
ConfigPathF func(c *model.Component) string
|
||||
}
|
||||
|
||||
func (self *ZitiEdgeTunnelType) Label() string {
|
||||
return "ziti-edge-tunnel"
|
||||
}
|
||||
|
||||
func (self *ZitiEdgeTunnelType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ZitiEdgeTunnelType) GetActions() map[string]model.ComponentAction {
|
||||
return map[string]model.ComponentAction{
|
||||
ZitiTunnelActionsReEnroll: model.ComponentActionF(self.ReEnroll),
|
||||
@@ -125,5 +133,5 @@ func (self *ZitiEdgeTunnelType) Stop(_ model.Run, c *model.Component) error {
|
||||
}
|
||||
|
||||
func (self *ZitiEdgeTunnelType) ReEnroll(run model.Run, c *model.Component) error {
|
||||
return reEnrollIdentity(run, c, getZitiBinaryPath(c, self.ZitiVersion), self.GetConfigPath(c))
|
||||
return reEnrollIdentity(run, c, GetZitiBinaryPath(c, self.ZitiVersion), self.GetConfigPath(c))
|
||||
}
|
||||
|
||||
@@ -56,6 +56,14 @@ type ZitiTunnelType struct {
|
||||
ConfigPathF func(c *model.Component) string
|
||||
}
|
||||
|
||||
func (self *ZitiTunnelType) Label() string {
|
||||
return "ziti-tunnel"
|
||||
}
|
||||
|
||||
func (self *ZitiTunnelType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ZitiTunnelType) GetActions() map[string]model.ComponentAction {
|
||||
return map[string]model.ComponentAction{
|
||||
ZitiTunnelActionsReEnroll: model.ComponentActionF(self.ReEnroll),
|
||||
@@ -80,18 +88,7 @@ func (self *ZitiTunnelType) StageFiles(r model.Run, c *model.Component) error {
|
||||
|
||||
func (self *ZitiTunnelType) InitializeHost(_ model.Run, c *model.Component) error {
|
||||
if self.Mode == ZitiTunnelModeTproxy {
|
||||
key := "ziti_tunnel.resolve_setup_done"
|
||||
if _, found := c.Host.Data[key]; !found {
|
||||
cmds := []string{
|
||||
"sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf",
|
||||
"sudo systemctl restart systemd-resolved",
|
||||
}
|
||||
if err := c.Host.ExecLogOnlyOnError(cmds...); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Host.Data[key] = true
|
||||
return nil
|
||||
}
|
||||
return setupDnsForTunneler(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -120,7 +117,7 @@ func (self *ZitiTunnelType) Start(_ model.Run, c *model.Component) error {
|
||||
|
||||
user := c.GetHost().GetSshUser()
|
||||
|
||||
binaryPath := getZitiBinaryPath(c, self.Version)
|
||||
binaryPath := GetZitiBinaryPath(c, self.Version)
|
||||
configPath := self.GetConfigPath(c)
|
||||
logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
|
||||
|
||||
@@ -151,5 +148,5 @@ func (self *ZitiTunnelType) Stop(_ model.Run, c *model.Component) error {
|
||||
}
|
||||
|
||||
func (self *ZitiTunnelType) ReEnroll(run model.Run, c *model.Component) error {
|
||||
return reEnrollIdentity(run, c, getZitiBinaryPath(c, self.Version), self.GetConfigPath(c))
|
||||
return reEnrollIdentity(run, c, GetZitiBinaryPath(c, self.Version), self.GetConfigPath(c))
|
||||
}
|
||||
|
||||
@@ -47,6 +47,14 @@ type ZrokControllerType struct {
|
||||
PreCreateClients string
|
||||
}
|
||||
|
||||
func (self *ZrokControllerType) Label() string {
|
||||
return "zrok-controller"
|
||||
}
|
||||
|
||||
func (self *ZrokControllerType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ZrokControllerType) InitType(*model.Component) {
|
||||
canonicalizeGoAppVersion(&self.Version)
|
||||
}
|
||||
|
||||
@@ -46,6 +46,14 @@ type ZrokFrontendType struct {
|
||||
ZrokCtrlSelector string
|
||||
}
|
||||
|
||||
func (self *ZrokFrontendType) Label() string {
|
||||
return "zrok-frontend"
|
||||
}
|
||||
|
||||
func (self *ZrokFrontendType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ZrokFrontendType) InitType(*model.Component) {
|
||||
canonicalizeGoAppVersion(&self.Version)
|
||||
if self.ZrokCtrlSelector == "" {
|
||||
|
||||
@@ -39,6 +39,14 @@ type ZrokLoopTestType struct {
|
||||
Pacing time.Duration
|
||||
}
|
||||
|
||||
func (self *ZrokLoopTestType) Label() string {
|
||||
return "zrok-loop-test"
|
||||
}
|
||||
|
||||
func (self *ZrokLoopTestType) GetVersion() string {
|
||||
return self.Version
|
||||
}
|
||||
|
||||
func (self *ZrokLoopTestType) InitType(*model.Component) {
|
||||
canonicalizeGoAppVersion(&self.Version)
|
||||
if self.Iterations == 0 {
|
||||
|
||||
@@ -15,9 +15,12 @@ import (
|
||||
|
||||
type ZitiDbBuilderStrategy interface {
|
||||
GetDbFile(m *model.Model) string
|
||||
ProcessDbModel(tx *bbolt.Tx, m *model.Model, builder *ZitiDbBuilder) error
|
||||
}
|
||||
|
||||
type ZitiEdgeRouterStrategy interface {
|
||||
GetSite(router *db.EdgeRouter) (string, bool)
|
||||
PostProcess(router *db.EdgeRouter, c *model.Component)
|
||||
ProcessDbModel(tx *bbolt.Tx, m *model.Model, builder *ZitiDbBuilder) error
|
||||
}
|
||||
|
||||
type ZitiDbBuilder struct {
|
||||
@@ -63,7 +66,7 @@ func (self *ZitiDbBuilder) Build(m *model.Model) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *ZitiDbBuilder) CreateEdgeRouterHosts(tx *bbolt.Tx, m *model.Model) error {
|
||||
func (self *ZitiDbBuilder) CreateEdgeRouterHosts(tx *bbolt.Tx, m *model.Model, erStrategy ZitiEdgeRouterStrategy) error {
|
||||
ids, _, err := self.stores.EdgeRouter.QueryIds(tx, "true limit none")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -75,7 +78,7 @@ func (self *ZitiDbBuilder) CreateEdgeRouterHosts(tx *bbolt.Tx, m *model.Model) e
|
||||
return err
|
||||
}
|
||||
|
||||
if site, useEdgeRouter := self.Strategy.GetSite(er); useEdgeRouter {
|
||||
if site, useEdgeRouter := erStrategy.GetSite(er); useEdgeRouter {
|
||||
regionId := site[:len(site)-1]
|
||||
|
||||
var region *model.Region
|
||||
@@ -114,7 +117,7 @@ func (self *ZitiDbBuilder) CreateEdgeRouterHosts(tx *bbolt.Tx, m *model.Model) e
|
||||
}
|
||||
|
||||
host.Components[er.Id] = component
|
||||
self.Strategy.PostProcess(er, component)
|
||||
erStrategy.PostProcess(er, component)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -64,6 +64,15 @@ func StageZrok(run model.Run, component *model.Component, version string, source
|
||||
})
|
||||
}
|
||||
|
||||
func StageLocalOnce(run model.Run, executable string, component *model.Component, source string) error {
|
||||
op := fmt.Sprintf("install.%s-local", executable)
|
||||
return run.DoOnce(op, func() error {
|
||||
return StageExecutable(run, executable, component, "", source, func() error {
|
||||
return fmt.Errorf("unable to fetch %s, as it a local-only application", executable)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func StageExecutable(run model.Run, executable string, component *model.Component, version string, source string, fallbackF func() error) error {
|
||||
fileName := executable
|
||||
if version != "" {
|
||||
|
||||
Reference in New Issue
Block a user