github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/k8s/pkg/cdk8s/blockscout/blockscout.go (about) 1 package blockscout 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2" 8 "github.com/rs/zerolog/log" 9 10 "github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/client" 11 "github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/config" 12 "github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/environment" 13 "github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/imports/k8s" 14 "github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/pkg" 15 a "github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/pkg/alias" 16 "github.com/smartcontractkit/chainlink-testing-framework/libs/utils/ptr" 17 ) 18 19 const ( 20 URLsKey = "blockscout" 21 ) 22 23 type Chart struct { 24 Props *Props 25 } 26 27 func (m Chart) IsDeploymentNeeded() bool { 28 return true 29 } 30 31 func (m Chart) GetName() string { 32 if m.Props == nil || m.Props.Name == "" { 33 return "blockscout" 34 } 35 return m.Props.Name 36 } 37 38 func (m Chart) GetProps() interface{} { 39 return m.Props 40 } 41 42 func (m Chart) GetPath() string { 43 return "" 44 } 45 46 func (m Chart) GetVersion() string { 47 return "" 48 } 49 50 func (m Chart) GetValues() *map[string]interface{} { 51 return nil 52 } 53 54 func (m Chart) ExportData(e *environment.Environment) error { 55 bsURL, err := e.Fwd.FindPort( 56 fmt.Sprintf("%s:0", m.GetName()), 57 fmt.Sprintf("%s-node", m.GetName()), "explorer"). 58 As(client.LocalConnection, client.HTTP) 59 if err != nil { 60 return err 61 } 62 log.Info().Str("URL", bsURL).Msg("Blockscout explorer") 63 e.URLs[URLsKey] = []string{bsURL} 64 return nil 65 } 66 67 func New(props *Props) func(root cdk8s.Chart) environment.ConnectedChart { 68 return func(root cdk8s.Chart) environment.ConnectedChart { 69 dp := defaultProps() 70 config.MustMerge(dp, props) 71 c := &Chart{ 72 Props: dp, 73 } 74 vars := vars{ 75 Labels: &map[string]*string{ 76 "app": ptr.Ptr(c.GetName()), 77 }, 78 ConfigMapName: fmt.Sprintf("%s-cm", c.GetName()), 79 BaseName: c.GetName(), 80 Port: 4000, 81 Props: dp, 82 } 83 service(root, vars) 84 deployment(root, vars) 85 return c 86 } 87 } 88 89 type Props struct { 90 Name string 91 HttpURL string `envconfig:"http_url"` 92 WsURL string `envconfig:"ws_url"` 93 } 94 95 func defaultProps() *Props { 96 return &Props{ 97 HttpURL: "http://geth:8544", 98 WsURL: "ws://geth:8546", 99 } 100 } 101 102 // vars some shared labels/selectors and names that must match in resources 103 type vars struct { 104 Labels *map[string]*string 105 BaseName string 106 ConfigMapName string 107 Port float64 108 Props *Props 109 } 110 111 func service(chart cdk8s.Chart, vars vars) { 112 k8s.NewKubeService(chart, ptr.Ptr(fmt.Sprintf("%s-service", vars.BaseName)), &k8s.KubeServiceProps{ 113 Metadata: &k8s.ObjectMeta{ 114 Name: ptr.Ptr(vars.BaseName), 115 }, 116 Spec: &k8s.ServiceSpec{ 117 Ports: &[]*k8s.ServicePort{ 118 { 119 Name: ptr.Ptr("explorer"), 120 Port: ptr.Ptr(vars.Port), 121 TargetPort: k8s.IntOrString_FromNumber(ptr.Ptr[float64](4000)), 122 }, 123 }, 124 Selector: vars.Labels, 125 }, 126 }) 127 } 128 129 func postgresContainer(p vars) *k8s.Container { 130 internalRepo := os.Getenv(config.EnvVarInternalDockerRepo) 131 postgresRepo := "postgres" 132 if internalRepo != "" { 133 postgresRepo = fmt.Sprintf("%s/postgres", internalRepo) 134 } 135 return &k8s.Container{ 136 Name: ptr.Ptr(fmt.Sprintf("%s-db", p.BaseName)), 137 Image: ptr.Ptr(fmt.Sprintf("%s:13.6", postgresRepo)), 138 Ports: &[]*k8s.ContainerPort{ 139 { 140 Name: ptr.Ptr("postgres"), 141 ContainerPort: ptr.Ptr[float64](5432), 142 }, 143 }, 144 Env: &[]*k8s.EnvVar{ 145 a.EnvVarStr("POSTGRES_PASSWORD", "postgres"), 146 a.EnvVarStr("POSTGRES_DB", "blockscout"), 147 }, 148 LivenessProbe: &k8s.Probe{ 149 Exec: &k8s.ExecAction{ 150 Command: pkg.PGIsReadyCheck()}, 151 InitialDelaySeconds: ptr.Ptr[float64](60), 152 PeriodSeconds: ptr.Ptr[float64](60), 153 }, 154 ReadinessProbe: &k8s.Probe{ 155 Exec: &k8s.ExecAction{ 156 Command: pkg.PGIsReadyCheck()}, 157 InitialDelaySeconds: ptr.Ptr[float64](2), 158 PeriodSeconds: ptr.Ptr[float64](2), 159 }, 160 Resources: a.ContainerResources("1000m", "2048Mi", "1000m", "2048Mi"), 161 } 162 } 163 164 func deployment(chart cdk8s.Chart, vars vars) { 165 k8s.NewKubeDeployment( 166 chart, 167 ptr.Ptr(fmt.Sprintf("%s-deployment", vars.BaseName)), 168 &k8s.KubeDeploymentProps{ 169 Metadata: &k8s.ObjectMeta{ 170 Name: ptr.Ptr(vars.BaseName), 171 }, 172 Spec: &k8s.DeploymentSpec{ 173 Selector: &k8s.LabelSelector{ 174 MatchLabels: vars.Labels, 175 }, 176 Template: &k8s.PodTemplateSpec{ 177 Metadata: &k8s.ObjectMeta{ 178 Labels: vars.Labels, 179 }, 180 Spec: &k8s.PodSpec{ 181 ServiceAccountName: ptr.Ptr("default"), 182 Containers: &[]*k8s.Container{ 183 container(vars), 184 postgresContainer(vars), 185 }, 186 }, 187 }, 188 }, 189 }) 190 } 191 192 func container(vars vars) *k8s.Container { 193 internalRepo := os.Getenv(config.EnvVarInternalDockerRepo) 194 blockscoutRepo := "f4hrenh9it/blockscout" 195 if internalRepo != "" { 196 blockscoutRepo = fmt.Sprintf("%s/blockscout", internalRepo) 197 } 198 return &k8s.Container{ 199 Name: ptr.Ptr(fmt.Sprintf("%s-node", vars.BaseName)), 200 Image: ptr.Ptr(fmt.Sprintf("%s:v1", blockscoutRepo)), 201 ImagePullPolicy: ptr.Ptr("Always"), 202 Command: &[]*string{ptr.Ptr(`/bin/bash`)}, 203 Args: &[]*string{ 204 ptr.Ptr("-c"), 205 ptr.Ptr("mix ecto.create && mix ecto.migrate && mix phx.server"), 206 }, 207 Ports: &[]*k8s.ContainerPort{ 208 { 209 Name: ptr.Ptr("explorer"), 210 ContainerPort: ptr.Ptr(vars.Port), 211 }, 212 }, 213 ReadinessProbe: &k8s.Probe{ 214 HttpGet: &k8s.HttpGetAction{ 215 Port: k8s.IntOrString_FromNumber(ptr.Ptr(vars.Port)), 216 Path: ptr.Ptr("/"), 217 }, 218 InitialDelaySeconds: ptr.Ptr[float64](20), 219 PeriodSeconds: ptr.Ptr[float64](5), 220 }, 221 Env: &[]*k8s.EnvVar{ 222 a.EnvVarStr("MIX_ENV", "prod"), 223 a.EnvVarStr("ECTO_USE_SSL", "'false'"), 224 a.EnvVarStr("COIN", "DAI"), 225 a.EnvVarStr("ETHEREUM_JSONRPC_VARIANT", "geth"), 226 a.EnvVarStr("ETHEREUM_JSONRPC_HTTP_URL", vars.Props.HttpURL), 227 a.EnvVarStr("ETHEREUM_JSONRPC_WS_URL", vars.Props.WsURL), 228 a.EnvVarStr("DATABASE_URL", "postgresql://postgres:@localhost:5432/blockscout?ssl=false"), 229 }, 230 Resources: a.ContainerResources("2000m", "2048Mi", "2000m", "2048Mi"), 231 } 232 }