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  }