• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MinaProtocol / mina / 1612

21 Oct 2024 08:28AM UTC coverage: 61.111% (+0.02%) from 61.093%
1612

push

buildkite

web-flow
Merge pull request #16255 from MinaProtocol/release/3.0.2

682 of 1335 new or added lines in 129 files covered. (51.09%)

148 existing lines in 47 files now uncovered.

47180 of 77204 relevant lines covered (61.11%)

555482.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.39
/src/lib/integration_test_local_engine/docker_network.ml
1
open Core_kernel
1✔
2
open Async
3
open Integration_test_lib
4

5
let get_container_id service_id =
6
  let%bind cwd = Unix.getcwd () in
×
7
  let open Malleable_error.Let_syntax in
×
8
  let%bind container_ids =
9
    Deferred.bind ~f:Malleable_error.or_hard_error
×
10
      (Integration_test_lib.Util.run_cmd_or_error cwd "docker"
×
11
         [ "ps"; "-f"; sprintf "name=%s" service_id; "--quiet" ] )
×
12
  in
13
  let container_id_list = String.split container_ids ~on:'\n' in
×
14
  match container_id_list with
×
15
  | [] ->
×
16
      Malleable_error.hard_error_format "No container id found for service %s"
17
        service_id
18
  | raw_container_id :: _ ->
×
19
      return (String.strip raw_container_id)
×
20

21
let run_in_container ?(exit_code = 10) container_id ~cmd =
×
22
  let%bind.Deferred cwd = Unix.getcwd () in
×
23
  Integration_test_lib.Util.run_cmd_or_hard_error ~exit_code cwd "docker"
×
24
    ([ "exec"; container_id ] @ cmd)
25

26
module Node = struct
27
  type config =
28
    { network_keypair : Network_keypair.t option
29
    ; service_id : string
30
    ; postgres_connection_uri : string option
31
    ; graphql_port : int
32
    }
33

34
  type t = { config : config; mutable should_be_running : bool }
35

36
  let id { config; _ } = config.service_id
×
37

38
  let infra_id { config; _ } = config.service_id
×
39

40
  let should_be_running { should_be_running; _ } = should_be_running
×
41

42
  let network_keypair { config; _ } = config.network_keypair
×
43

44
  let get_ingress_uri node =
45
    Uri.make ~scheme:"http" ~host:"127.0.0.1" ~path:"/graphql"
×
46
      ~port:node.config.graphql_port ()
47

48
  let get_container_index_from_service_name service_name =
49
    match String.split_on_chars ~on:[ '_' ] service_name with
×
50
    | _ :: value :: _ ->
×
51
        value
52
    | _ ->
×
53
        failwith "get_container_index_from_service_name: bad service name"
54

55
  let dump_archive_data ~logger (t : t) ~data_file =
56
    let service_name = t.config.service_id in
×
57
    match t.config.postgres_connection_uri with
58
    | None ->
×
59
        failwith
60
          (sprintf "dump_archive_data: %s not an archive container" service_name)
×
61
    | Some postgres_uri ->
×
62
        let open Malleable_error.Let_syntax in
63
        let%bind container_id = get_container_id service_name in
×
64
        [%log info] "Dumping archive data from (node: %s, container: %s)"
×
65
          service_name container_id ;
66
        let%map data =
67
          run_in_container container_id
×
68
            ~cmd:[ "pg_dump"; "--create"; "--no-owner"; postgres_uri ]
69
        in
70
        [%log info] "Dumping archive data to file %s" data_file ;
×
71
        Out_channel.with_file data_file ~f:(fun out_ch ->
×
72
            Out_channel.output_string out_ch data )
×
73

74
  let get_logs_in_container container_id =
75
    let%bind.Deferred cwd = Unix.getcwd () in
×
76
    Integration_test_lib.Util.run_cmd_or_hard_error ~exit_code:13 cwd "docker"
×
77
      [ "logs"; container_id ]
78

79
  let dump_mina_logs ~logger (t : t) ~log_file =
80
    let open Malleable_error.Let_syntax in
×
81
    let%bind container_id = get_container_id t.config.service_id in
×
82
    [%log info] "Dumping mina logs from (node: %s, container: %s)"
×
83
      t.config.service_id container_id ;
84
    let%map logs = get_logs_in_container container_id in
×
85
    [%log info] "Dumping mina logs to file %s" log_file ;
×
86
    Out_channel.with_file log_file ~f:(fun out_ch ->
×
87
        Out_channel.output_string out_ch logs )
×
88

89
  let cp_string_to_container_file container_id ~str ~dest =
90
    let tmp_file, oc =
×
91
      Caml.Filename.open_temp_file ~temp_dir:Filename.temp_dir_name
92
        "integration_test_cp_string" ".tmp"
93
    in
94
    Out_channel.output_string oc str ;
×
95
    Out_channel.close oc ;
×
96
    let%bind cwd = Unix.getcwd () in
×
97
    let dest_file = sprintf "%s:%s" container_id dest in
×
98
    Integration_test_lib.Util.run_cmd_or_error cwd "docker"
×
99
      [ "cp"; tmp_file; dest_file ]
100

101
  let run_replayer ?(start_slot_since_genesis = 0) ~logger (t : t) =
×
102
    let open Malleable_error.Let_syntax in
×
103
    let%bind container_id = get_container_id t.config.service_id in
×
104
    [%log info] "Running replayer on (node: %s, container: %s)"
×
105
      t.config.service_id container_id ;
106
    let%bind accounts =
107
      run_in_container container_id
×
108
        ~cmd:[ "jq"; "-c"; ".ledger.accounts"; "/root/runtime_config.json" ]
109
    in
110
    let replayer_input =
×
111
      sprintf
112
        {| { "start_slot_since_genesis": %d,
113
             "genesis_ledger": { "accounts": %s, "add_genesis_winner": true }} |}
114
        start_slot_since_genesis accounts
115
    in
116
    let dest = "replayer-input.json" in
×
117
    let%bind archive_container_id = get_container_id "archive" in
×
118
    let%bind () =
119
      Deferred.bind ~f:Malleable_error.return
×
120
        (cp_string_to_container_file archive_container_id ~str:replayer_input
×
121
           ~dest )
122
      >>| ignore
×
123
    in
124
    let postgres_url = Option.value_exn t.config.postgres_connection_uri in
×
125
    run_in_container container_id
×
126
      ~cmd:
127
        [ "mina-replayer"
128
        ; "--archive-uri"
129
        ; postgres_url
130
        ; "--input-file"
131
        ; dest
132
        ; "--output-file"
133
        ; "/dev/null"
134
        ; "--log-json"
135
        ; "--continue-on-error"
136
        ]
137

138
  let dump_precomputed_blocks ~logger (t : t) =
139
    let open Malleable_error.Let_syntax in
×
140
    let container_id = t.config.service_id in
141
    [%log info]
×
142
      "Dumping precomputed blocks from logs for (node: %s, container: %s)"
143
      t.config.service_id container_id ;
144
    let%bind logs = get_logs_in_container container_id in
×
145
    (* kubectl logs may include non-log output, like "Using password from environment variable" *)
146
    let log_lines =
×
147
      String.split logs ~on:'\n'
×
148
      |> List.filter ~f:(String.is_prefix ~prefix:"{\"timestamp\":")
149
    in
150
    let jsons = List.map log_lines ~f:Yojson.Safe.from_string in
×
151
    let metadata_jsons =
×
152
      List.map jsons ~f:(fun json ->
153
          match json with
×
154
          | `Assoc items -> (
×
155
              match List.Assoc.find items ~equal:String.equal "metadata" with
156
              | Some md ->
×
157
                  md
158
              | None ->
×
159
                  failwithf "Log line is missing metadata: %s"
160
                    (Yojson.Safe.to_string json)
×
161
                    () )
162
          | other ->
×
163
              failwithf "Expected log line to be a JSON record, got: %s"
164
                (Yojson.Safe.to_string other)
×
165
                () )
166
    in
167
    let state_hash_and_blocks =
×
168
      List.fold metadata_jsons ~init:[] ~f:(fun acc json ->
169
          match json with
×
170
          | `Assoc items -> (
×
171
              match
172
                List.Assoc.find items ~equal:String.equal "precomputed_block"
173
              with
174
              | Some block -> (
×
175
                  match
176
                    List.Assoc.find items ~equal:String.equal "state_hash"
177
                  with
178
                  | Some state_hash ->
×
179
                      (state_hash, block) :: acc
180
                  | None ->
×
181
                      failwith
182
                        "Log metadata contains a precomputed block, but no \
183
                         state hash" )
184
              | None ->
×
185
                  acc )
186
          | other ->
×
187
              failwithf "Expected log line to be a JSON record, got: %s"
188
                (Yojson.Safe.to_string other)
×
189
                () )
190
    in
191
    let%bind.Deferred () =
192
      Deferred.List.iter state_hash_and_blocks
×
193
        ~f:(fun (state_hash_json, block_json) ->
194
          let double_quoted_state_hash =
×
195
            Yojson.Safe.to_string state_hash_json
196
          in
197
          let state_hash =
×
198
            String.sub double_quoted_state_hash ~pos:1
199
              ~len:(String.length double_quoted_state_hash - 2)
×
200
          in
201
          let block = Yojson.Safe.pretty_to_string block_json in
×
202
          let filename = state_hash ^ ".json" in
×
203
          match%map.Deferred Sys.file_exists filename with
×
204
          | `Yes ->
×
205
              [%log info]
×
206
                "File already exists for precomputed block with state hash %s"
207
                state_hash
208
          | _ ->
×
209
              [%log info]
×
210
                "Dumping precomputed block with state hash %s to file %s"
211
                state_hash filename ;
212
              Out_channel.with_file filename ~f:(fun out_ch ->
×
213
                  Out_channel.output_string out_ch block ) )
×
214
    in
215
    Malleable_error.return ()
×
216

217
  let start ~fresh_state node : unit Malleable_error.t =
218
    let open Malleable_error.Let_syntax in
×
219
    let%bind container_id = get_container_id node.config.service_id in
×
220
    node.should_be_running <- true ;
×
221
    let%bind () =
222
      if fresh_state then
223
        run_in_container container_id ~cmd:[ "rm"; "-rf"; ".mina-config/*" ]
×
224
        >>| ignore
×
225
      else Malleable_error.return ()
×
226
    in
227
    run_in_container ~exit_code:11 container_id ~cmd:[ "/start.sh" ] >>| ignore
×
228

229
  let stop node =
230
    let open Malleable_error.Let_syntax in
×
231
    let%bind container_id = get_container_id node.config.service_id in
×
232
    node.should_be_running <- false ;
×
233
    run_in_container ~exit_code:12 container_id ~cmd:[ "/stop.sh" ] >>| ignore
×
234
end
235

236
module Service_to_deploy = struct
237
  type config =
238
    { network_keypair : Network_keypair.t option
239
    ; postgres_connection_uri : string option
240
    ; graphql_port : int
241
    }
242

243
  type t = { stack_name : string; service_name : string; config : config }
244

245
  let construct_service stack_name service_name config : t =
246
    { stack_name; service_name; config }
×
247

248
  let init_service_to_deploy_config ?(network_keypair = None)
×
249
      ?(postgres_connection_uri = None) ~graphql_port =
×
250
    { network_keypair; postgres_connection_uri; graphql_port }
×
251

252
  let get_node_from_service t =
253
    let open Malleable_error.Let_syntax in
×
254
    let service_id = sprintf "%s_%s" t.stack_name t.service_name in
255
    let%bind container_id = get_container_id service_id in
×
256
    if String.is_empty container_id then
×
257
      Malleable_error.hard_error_format "No container id found for service %s"
×
258
        t.service_name
259
    else
260
      return
×
261
        { Node.config =
262
            { service_id
263
            ; network_keypair = t.config.network_keypair
264
            ; postgres_connection_uri = t.config.postgres_connection_uri
265
            ; graphql_port = t.config.graphql_port
266
            }
267
        ; should_be_running = false
268
        }
269
end
270

271
type t =
272
  { namespace : string
273
  ; constants : Test_config.constants
274
  ; seeds : Node.t Core.String.Map.t
275
  ; block_producers : Node.t Core.String.Map.t
276
  ; snark_coordinators : Node.t Core.String.Map.t
277
  ; snark_workers : Node.t Core.String.Map.t
278
  ; archive_nodes : Node.t Core.String.Map.t
279
  ; genesis_keypairs : Network_keypair.t Core.String.Map.t
280
  }
281

282
let constants { constants; _ } = constants
×
283

NEW
284
let constraint_constants { constants; _ } = constants.constraint_constants
×
285

NEW
286
let genesis_constants { constants; _ } = constants.genesis_constants
×
287

NEW
288
let compile_config { constants; _ } = constants.compile_config
×
289

290
let seeds { seeds; _ } = seeds
×
291

292
let block_producers { block_producers; _ } = block_producers
×
293

294
let snark_coordinators { snark_coordinators; _ } = snark_coordinators
×
295

296
let archive_nodes { archive_nodes; _ } = archive_nodes
×
297

298
let all_mina_nodes { seeds; block_producers; snark_coordinators; _ } =
299
  List.concat
×
300
    [ Core.String.Map.to_alist seeds
×
301
    ; Core.String.Map.to_alist block_producers
×
302
    ; Core.String.Map.to_alist snark_coordinators
×
303
    ]
304
  |> Core.String.Map.of_alist_exn
305

306
let all_nodes t =
307
  List.concat
×
308
    [ Core.String.Map.to_alist t.seeds
×
309
    ; Core.String.Map.to_alist t.block_producers
×
310
    ; Core.String.Map.to_alist t.snark_coordinators
×
311
    ; Core.String.Map.to_alist t.snark_workers
×
312
    ]
313
  |> Core.String.Map.of_alist_exn
314

315
let all_non_seed_nodes t =
316
  List.concat
×
317
    [ Core.String.Map.to_alist t.block_producers
×
318
    ; Core.String.Map.to_alist t.snark_coordinators
×
319
    ; Core.String.Map.to_alist t.snark_workers
×
320
    ]
321
  |> Core.String.Map.of_alist_exn
322

323
let genesis_keypairs { genesis_keypairs; _ } = genesis_keypairs
×
324

325
let all_ids t =
326
  let deployments = all_nodes t |> Core.Map.to_alist in
×
327
  List.fold deployments ~init:[] ~f:(fun acc (_, node) ->
×
328
      List.cons node.config.service_id acc )
×
329

330
let initialize_infra ~logger network =
331
  let _ = logger in
×
332
  let _ = network in
333
  Malleable_error.return ()
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc