| 1546 | } |
| 1547 | |
| 1548 | func (c *LocalCluster) CopyExportToHost(exportDir, hostDir string) (dataFiles, schemaFiles []string, err error) { |
| 1549 | ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) |
| 1550 | defer cancel() |
| 1551 | |
| 1552 | // Copy the exported data from the container to host |
| 1553 | ts, _, err := c.dcli.CopyFromContainer(ctx, c.alphas[0].cid(), exportDir) |
| 1554 | if err != nil { |
| 1555 | return nil, nil, errors.Wrapf(err, "error copying export dir from container [%v]", c.alphas[0].cname()) |
| 1556 | } |
| 1557 | defer func() { |
| 1558 | if err := ts.Close(); err != nil { |
| 1559 | log.Printf("[WARNING] error closing tared stream from docker cp for [%v]", c.alphas[0].cname()) |
| 1560 | } |
| 1561 | }() |
| 1562 | |
| 1563 | // Extract files from tar stream |
| 1564 | tr := tar.NewReader(ts) |
| 1565 | for { |
| 1566 | header, err := tr.Next() |
| 1567 | if stderrors.Is(err, io.EOF) { |
| 1568 | break |
| 1569 | } else if err != nil { |
| 1570 | return nil, nil, errors.Wrapf(err, "error reading file in tared stream: [%+v]", header) |
| 1571 | } |
| 1572 | if header.Typeflag != tar.TypeReg { |
| 1573 | continue |
| 1574 | } |
| 1575 | |
| 1576 | fileName := filepath.Base(header.Name) |
| 1577 | hostFile := filepath.Join(hostDir, fileName) |
| 1578 | |
| 1579 | if !strings.HasPrefix(filepath.Clean(hostFile), filepath.Clean(hostDir)+string(os.PathSeparator)) { |
| 1580 | return nil, nil, errors.Errorf("illegal file path in archive: %v", header.Name) |
| 1581 | } |
| 1582 | |
| 1583 | switch { |
| 1584 | case strings.HasSuffix(fileName, ".rdf.gz"): |
| 1585 | dataFiles = append(dataFiles, hostFile) |
| 1586 | case strings.HasSuffix(fileName, ".json.gz"): |
| 1587 | dataFiles = append(dataFiles, hostFile) |
| 1588 | case strings.HasSuffix(fileName, ".schema.gz"): |
| 1589 | schemaFiles = append(schemaFiles, hostFile) |
| 1590 | case strings.HasSuffix(fileName, ".gql_schema.gz"): |
| 1591 | // Skip gql schema files for now |
| 1592 | continue |
| 1593 | default: |
| 1594 | log.Printf("[WARNING] unexpected file in export: %v", fileName) |
| 1595 | continue |
| 1596 | } |
| 1597 | |
| 1598 | fd, err := os.Create(hostFile) |
| 1599 | if err != nil { |
| 1600 | return nil, nil, errors.Wrapf(err, "error creating file [%v]", hostFile) |
| 1601 | } |
| 1602 | defer fd.Close() |
| 1603 | |
| 1604 | if _, err := io.Copy(fd, tr); err != nil { |
| 1605 | return nil, nil, errors.Wrapf(err, "error writing to [%v] from: [%+v]", fd.Name(), header) |