# Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Rules for creating password files and entries."""
load("@bazel_skylib//lib:paths.bzl", "paths")
_join_path = paths.join
PasswdFileContentProviderInfo = provider(
fields = [
"username",
"uid",
"gid",
"info",
"home",
"create_home",
"shell",
"name",
],
)
def _passwd_entry_impl(ctx):
"""Creates a passwd_file_content_provider containing a single entry."""
return [PasswdFileContentProviderInfo(
username = ctx.attr.username,
uid = ctx.attr.uid,
gid = ctx.attr.gid,
info = ctx.attr.info,
home = ctx.attr.home,
create_home = ctx.attr.create_home,
shell = ctx.attr.shell,
name = ctx.attr.name,
)]
def _passwd_file_impl(ctx):
"""Core implementation of passwd_file."""
f = "".join(["%s:x:%s:%s:%s:%s:%s\n" % (
entry[PasswdFileContentProviderInfo].username,
entry[PasswdFileContentProviderInfo].uid,
entry[PasswdFileContentProviderInfo].gid,
entry[PasswdFileContentProviderInfo].info,
entry[PasswdFileContentProviderInfo].home,
entry[PasswdFileContentProviderInfo].shell,
) for entry in ctx.attr.entries])
passwd_file = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(output = passwd_file, content = f)
return DefaultInfo(files = depset([passwd_file]))
def _format_onwer(t):
return ("--owners=%s=%s" % (t[0], t[1]))
def _build_homedirs_tar(ctx, passwd_file):
homedirs = []
owners_map = {}
for entry in ctx.attr.entries:
if entry[PasswdFileContentProviderInfo].create_home:
homedir = entry[PasswdFileContentProviderInfo].home
owners_map[homedir] = "{uid}.{gid}".format(
uid = entry[PasswdFileContentProviderInfo].uid,
gid = entry[PasswdFileContentProviderInfo].gid,
)
homedirs.append(homedir)
dest_file = _join_path(
ctx.attr.passwd_file_pkg_dir,
ctx.label.name,
)
args = ctx.actions.args()
args.add(ctx.outputs.passwd_tar, format = "--output=%s")
args.add("--mode=0o700")
args.add(passwd_file, format = "--file=%s=" + dest_file)
args.add(dest_file, format = "--modes=%s=" + ctx.attr.passwd_file_mode)
args.add_all(homedirs, format_each = "--empty_dir=%s")
args.add_all(owners_map.items(), map_each = _format_onwer)
ctx.actions.run(
executable = ctx.executable.build_tar,
inputs = [passwd_file],
outputs = [ctx.outputs.passwd_tar],
mnemonic = "PasswdTar",
arguments = [args],
)
def _passwd_tar_impl(ctx):
"""Core implementation of passwd_tar."""
f = "".join(["%s:x:%s:%s:%s:%s:%s\n" % (
entry[PasswdFileContentProviderInfo].username,
entry[PasswdFileContentProviderInfo].uid,
entry[PasswdFileContentProviderInfo].gid,
entry[PasswdFileContentProviderInfo].info,
entry[PasswdFileContentProviderInfo].home,
entry[PasswdFileContentProviderInfo].shell,
) for entry in ctx.attr.entries])
passwd_file = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(output = passwd_file, content = f)
_build_homedirs_tar(ctx, passwd_file)
return DefaultInfo(files = depset([ctx.outputs.passwd_tar]))
passwd_entry = rule(
attrs = {
"create_home": attr.bool(default = True),
"gid": attr.int(default = 1000),
"home": attr.string(default = "/home"),
"info": attr.string(default = "user"),
"shell": attr.string(default = "/bin/bash"),
"uid": attr.int(default = 1000),
"username": attr.string(mandatory = True),
},
implementation = _passwd_entry_impl,
)
passwd_file = rule(
attrs = {
"entries": attr.label_list(
allow_empty = False,
providers = [PasswdFileContentProviderInfo],
),
},
executable = False,
implementation = _passwd_file_impl,
)
passwd_tar = rule(
attrs = {
"build_tar": attr.label(
default = Label("//container:build_tar"),
cfg = "exec",
executable = True,
allow_files = True,
),
"entries": attr.label_list(
allow_empty = False,
providers = [PasswdFileContentProviderInfo],
),
"passwd_file_mode": attr.string(default = "0o644"),
"passwd_file_pkg_dir": attr.string(mandatory = True),
},
executable = False,
outputs = {
"passwd_tar": "%{name}.tar",
},
implementation = _passwd_tar_impl,
)