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