Skip to content

Commit 0b14adf

Browse files
committed
image/layout/tar: Add a CreateTarFile helper
The NewEngine commands for the tar-backed image-layout engines (both the CAS and refs engines) open files O_RDWR and expect image-layout compatible content in the tarball. That makes sense, but for folks who *don't* have such a tarball, a helper like CreateTarFile makes it easy to explicitly create an empty one. The 0666 file modes and 0777 directory modes rely on the caller's umask to appropriately limit user/group/other permissions for the tarball itself and any content extracted to the filesystem from the tarball. Expose this new functionality on the command line as: $ oci-image-tool init image-layout PATH where 'init' and 'image-layout' are two separate levels in case we support initializing additional types of repositories in the future. Signed-off-by: W. Trevor King <[email protected]>
1 parent 932dc8b commit 0b14adf

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

cmd/oci-image-tool/init.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2016 The Linux Foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"io"
19+
"log"
20+
21+
"github.com/spf13/cobra"
22+
)
23+
24+
func newInitCmd(stdout io.Writer, stderr *log.Logger) *cobra.Command {
25+
cmd := &cobra.Command{
26+
Use: "init",
27+
Short: "Initialize an OCI image",
28+
}
29+
30+
cmd.AddCommand(newInitImageLayoutCmd(stdout, stderr))
31+
32+
return cmd
33+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2016 The Linux Foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"io"
19+
"log"
20+
"os"
21+
22+
"github.com/opencontainers/image-spec/image/layout"
23+
"github.com/spf13/cobra"
24+
"golang.org/x/net/context"
25+
)
26+
27+
type initImageLayout struct {
28+
stderr *log.Logger
29+
}
30+
31+
func newInitImageLayoutCmd(stdout io.Writer, stderr *log.Logger) *cobra.Command {
32+
state := &initImageLayout{
33+
stderr: stderr,
34+
}
35+
36+
return &cobra.Command{
37+
Use: "image-layout PATH",
38+
Short: "Initialize an OCI image-layout repository",
39+
Run: state.Run,
40+
}
41+
}
42+
43+
func (state *initImageLayout) Run(cmd *cobra.Command, args []string) {
44+
if len(args) != 1 {
45+
if err := cmd.Usage(); err != nil {
46+
state.stderr.Println(err)
47+
}
48+
os.Exit(1)
49+
}
50+
51+
path := args[0]
52+
53+
ctx := context.Background()
54+
55+
err := layout.CreateTarFile(ctx, path)
56+
if err != nil {
57+
state.stderr.Println(err)
58+
os.Exit(1)
59+
}
60+
61+
os.Exit(0)
62+
}

cmd/oci-image-tool/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func main() {
3030
stdout := log.New(os.Stdout, "", 0)
3131
stderr := log.New(os.Stderr, "", 0)
3232

33+
cmd.AddCommand(newInitCmd(os.Stdout, stderr))
3334
cmd.AddCommand(newValidateCmd(stdout, stderr))
3435
cmd.AddCommand(newUnpackCmd(stdout, stderr))
3536
cmd.AddCommand(newBundleCmd(stdout, stderr))

image/layout/tar.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,50 @@ func CheckTarVersion(ctx context.Context, reader io.ReadSeeker) (err error) {
187187

188188
return nil
189189
}
190+
191+
// CreateTarFile creates a new image-layout tar file at the given path.
192+
func CreateTarFile(ctx context.Context, path string) (err error) {
193+
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
194+
if err != nil {
195+
return err
196+
}
197+
defer file.Close()
198+
199+
tarWriter := tar.NewWriter(file)
200+
defer tarWriter.Close()
201+
202+
now := time.Now()
203+
for _, name := range []string{"./blobs/", "./refs/"} {
204+
header := &tar.Header{
205+
Name: name,
206+
Mode: 0777,
207+
ModTime: now,
208+
Typeflag: tar.TypeDir,
209+
}
210+
err = tarWriter.WriteHeader(header)
211+
if err != nil {
212+
return err
213+
}
214+
}
215+
216+
imageLayoutVersion := specs.ImageLayoutVersion{
217+
Version: "1.0.0",
218+
}
219+
imageLayoutVersionBytes, err := json.Marshal(imageLayoutVersion)
220+
if err != nil {
221+
return err
222+
}
223+
header := &tar.Header{
224+
Name: "./oci-layout",
225+
Mode: 0666,
226+
Size: int64(len(imageLayoutVersionBytes)),
227+
ModTime: now,
228+
Typeflag: tar.TypeReg,
229+
}
230+
err = tarWriter.WriteHeader(header)
231+
if err != nil {
232+
return err
233+
}
234+
_, err = tarWriter.Write(imageLayoutVersionBytes)
235+
return err
236+
}

0 commit comments

Comments
 (0)