mirror of
https://github.com/rancher/os.git
synced 2025-09-04 00:04:25 +00:00
Extend write_files to run in all system services
This commit is contained in:
@@ -12,8 +12,10 @@ import (
|
|||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/coreos/coreos-cloudinit/system"
|
"github.com/coreos/coreos-cloudinit/system"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/rancher/os/config"
|
rancherConfig "github.com/rancher/os/config"
|
||||||
|
"github.com/rancher/os/docker"
|
||||||
"github.com/rancher/os/util"
|
"github.com/rancher/os/util"
|
||||||
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -38,7 +40,7 @@ func Main() {
|
|||||||
|
|
||||||
log.Infof("Running cloud-init-execute: pre-console=%v, console=%v", preConsole, console)
|
log.Infof("Running cloud-init-execute: pre-console=%v, console=%v", preConsole, console)
|
||||||
|
|
||||||
cfg := config.LoadConfig()
|
cfg := rancherConfig.LoadConfig()
|
||||||
|
|
||||||
if !console && !preConsole {
|
if !console && !preConsole {
|
||||||
console = true
|
console = true
|
||||||
@@ -53,21 +55,13 @@ func Main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyConsole(cfg *config.CloudConfig) {
|
func ApplyConsole(cfg *rancherConfig.CloudConfig) {
|
||||||
if len(cfg.SSHAuthorizedKeys) > 0 {
|
if len(cfg.SSHAuthorizedKeys) > 0 {
|
||||||
authorizeSSHKeys("rancher", cfg.SSHAuthorizedKeys, sshKeyName)
|
authorizeSSHKeys("rancher", cfg.SSHAuthorizedKeys, sshKeyName)
|
||||||
authorizeSSHKeys("docker", cfg.SSHAuthorizedKeys, sshKeyName)
|
authorizeSSHKeys("docker", cfg.SSHAuthorizedKeys, sshKeyName)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range cfg.WriteFiles {
|
WriteFiles(cfg, "console")
|
||||||
f := system.File{File: file}
|
|
||||||
fullPath, err := system.WriteFile(&f, "/")
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{"err": err, "path": fullPath}).Error("Error writing file")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Printf("Wrote file %s to filesystem", fullPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, configMount := range cfg.Mounts {
|
for _, configMount := range cfg.Mounts {
|
||||||
if len(configMount) != 4 {
|
if len(configMount) != 4 {
|
||||||
@@ -88,7 +82,29 @@ func ApplyConsole(cfg *config.CloudConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyPreConsole(cfg *config.CloudConfig) {
|
func WriteFiles(cfg *rancherConfig.CloudConfig, container string) {
|
||||||
|
for _, file := range cfg.WriteFiles {
|
||||||
|
fileContainer := file.Container
|
||||||
|
if fileContainer == "" {
|
||||||
|
fileContainer = "console"
|
||||||
|
}
|
||||||
|
if fileContainer != container {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
f := system.File{
|
||||||
|
File: file.File,
|
||||||
|
}
|
||||||
|
fullPath, err := system.WriteFile(&f, "/")
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{"err": err, "path": fullPath}).Error("Error writing file")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Printf("Wrote file %s to filesystem", fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyPreConsole(cfg *rancherConfig.CloudConfig) {
|
||||||
if _, err := os.Stat(resizeStamp); os.IsNotExist(err) && cfg.Rancher.ResizeDevice != "" {
|
if _, err := os.Stat(resizeStamp); os.IsNotExist(err) && cfg.Rancher.ResizeDevice != "" {
|
||||||
if err := resizeDevice(cfg); err == nil {
|
if err := resizeDevice(cfg); err == nil {
|
||||||
os.Create(resizeStamp)
|
os.Create(resizeStamp)
|
||||||
@@ -105,9 +121,20 @@ func applyPreConsole(cfg *config.CloudConfig) {
|
|||||||
log.Errorf("Failed to set sysctl key %s: %s", k, err)
|
log.Errorf("Failed to set sysctl key %s: %s", k, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client, err := docker.NewSystemClient()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, restart := range cfg.Rancher.RestartServices {
|
||||||
|
if err = client.ContainerRestart(context.Background(), restart, 10); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resizeDevice(cfg *config.CloudConfig) error {
|
func resizeDevice(cfg *rancherConfig.CloudConfig) error {
|
||||||
cmd := exec.Command("growpart", cfg.Rancher.ResizeDevice, "1")
|
cmd := exec.Command("growpart", cfg.Rancher.ResizeDevice, "1")
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -70,9 +70,6 @@ func Main() {
|
|||||||
|
|
||||||
func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadata) error {
|
func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadata) error {
|
||||||
os.MkdirAll(rancherConfig.CloudConfigDir, os.ModeDir|0600)
|
os.MkdirAll(rancherConfig.CloudConfigDir, os.ModeDir|0600)
|
||||||
os.Remove(rancherConfig.CloudConfigScriptFile)
|
|
||||||
os.Remove(rancherConfig.CloudConfigBootFile)
|
|
||||||
os.Remove(rancherConfig.MetaDataFile)
|
|
||||||
|
|
||||||
if len(scriptBytes) > 0 {
|
if len(scriptBytes) > 0 {
|
||||||
log.Infof("Writing to %s", rancherConfig.CloudConfigScriptFile)
|
log.Infof("Writing to %s", rancherConfig.CloudConfigScriptFile)
|
||||||
@@ -82,10 +79,12 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil {
|
if len(cloudConfigBytes) > 0 {
|
||||||
return err
|
if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes))
|
||||||
}
|
}
|
||||||
log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes))
|
|
||||||
|
|
||||||
metaDataBytes, err := yaml.Marshal(metadata)
|
metaDataBytes, err := yaml.Marshal(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -45,6 +45,12 @@ func Main() {
|
|||||||
SkipFlagParsing: true,
|
SkipFlagParsing: true,
|
||||||
Action: devAction,
|
Action: devAction,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "entrypoint",
|
||||||
|
HideHelp: true,
|
||||||
|
SkipFlagParsing: true,
|
||||||
|
Action: entrypointAction,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "env",
|
Name: "env",
|
||||||
ShortName: "e",
|
ShortName: "e",
|
||||||
|
74
cmd/control/entrypoint.go
Normal file
74
cmd/control/entrypoint.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/mount"
|
||||||
|
"github.com/rancher/os/cmd/cloudinitexecute"
|
||||||
|
"github.com/rancher/os/config"
|
||||||
|
"github.com/rancher/os/docker"
|
||||||
|
"github.com/rancher/os/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ca = "/etc/ssl/certs/ca-certificates.crt"
|
||||||
|
caBase = "/etc/ssl/certs/ca-certificates.crt.rancher"
|
||||||
|
)
|
||||||
|
|
||||||
|
func entrypointAction(c *cli.Context) error {
|
||||||
|
if err := mount.Mount("/host/dev", "/dev", "", "rbind"); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := util.FileCopy(caBase, ca); err != nil && !os.IsNotExist(err) {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := config.LoadConfig()
|
||||||
|
|
||||||
|
shouldWriteFiles := false
|
||||||
|
for _, file := range cfg.WriteFiles {
|
||||||
|
if file.Container != "" {
|
||||||
|
shouldWriteFiles = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldWriteFiles {
|
||||||
|
writeFiles(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
binary, err := exec.LookPath(os.Args[2])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.Exec(binary, os.Args[2:], os.Environ())
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeFiles(cfg *config.CloudConfig) error {
|
||||||
|
id, err := util.GetCurrentContainerId()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client, err := docker.NewSystemClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
info, err := client.ContainerInspect(context.Background(), id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudinitexecute.WriteFiles(cfg, info.Name[1:])
|
||||||
|
return nil
|
||||||
|
}
|
@@ -85,12 +85,17 @@ type Repositories map[string]Repository
|
|||||||
|
|
||||||
type CloudConfig struct {
|
type CloudConfig struct {
|
||||||
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
|
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
|
||||||
WriteFiles []config.File `yaml:"write_files"`
|
WriteFiles []File `yaml:"write_files"`
|
||||||
Hostname string `yaml:"hostname"`
|
Hostname string `yaml:"hostname"`
|
||||||
Mounts [][]string `yaml:"mounts,omitempty"`
|
Mounts [][]string `yaml:"mounts,omitempty"`
|
||||||
Rancher RancherConfig `yaml:"rancher,omitempty"`
|
Rancher RancherConfig `yaml:"rancher,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
config.File
|
||||||
|
Container string `yaml:"container,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type RancherConfig struct {
|
type RancherConfig struct {
|
||||||
Console string `yaml:"console,omitempty"`
|
Console string `yaml:"console,omitempty"`
|
||||||
Environment map[string]string `yaml:"environment,omitempty"`
|
Environment map[string]string `yaml:"environment,omitempty"`
|
||||||
@@ -119,6 +124,7 @@ type RancherConfig struct {
|
|||||||
Defaults Defaults `yaml:"defaults,omitempty"`
|
Defaults Defaults `yaml:"defaults,omitempty"`
|
||||||
ResizeDevice string `yaml:"resize_device,omitempty"`
|
ResizeDevice string `yaml:"resize_device,omitempty"`
|
||||||
Sysctl map[string]string `yaml:"sysctl,omitempty"`
|
Sysctl map[string]string `yaml:"sysctl,omitempty"`
|
||||||
|
RestartServices []string `yaml:"restart_services,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpgradeConfig struct {
|
type UpgradeConfig struct {
|
||||||
|
@@ -32,8 +32,7 @@ RUN rm /sbin/poweroff /sbin/reboot /sbin/halt && \
|
|||||||
adduser docker sudo && \
|
adduser docker sudo && \
|
||||||
echo '%sudo ALL=(ALL) ALL' >> /etc/sudoers
|
echo '%sudo ALL=(ALL) ALL' >> /etc/sudoers
|
||||||
COPY inputrc /etc/inputrc
|
COPY inputrc /etc/inputrc
|
||||||
COPY entry.sh /usr/sbin/entry.sh
|
|
||||||
COPY growpart /usr/bin/growpart
|
COPY growpart /usr/bin/growpart
|
||||||
RUN sed -i -e 's/duid/clientid/g' /etc/dhcpcd.conf
|
RUN sed -i -e 's/duid/clientid/g' /etc/dhcpcd.conf
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/sbin/entry.sh"]
|
ENTRYPOINT ["/usr/bin/ros", "entrypoint"]
|
||||||
|
@@ -250,6 +250,9 @@ rancher:
|
|||||||
uts: host
|
uts: host
|
||||||
privileged: true
|
privileged: true
|
||||||
restart: always
|
restart: always
|
||||||
|
volumes_from:
|
||||||
|
- command-volumes
|
||||||
|
- system-volumes
|
||||||
preload-system-images:
|
preload-system-images:
|
||||||
image: {{.OS_REPO}}/os-preload:{{.VERSION}}{{.SUFFIX}}
|
image: {{.OS_REPO}}/os-preload:{{.VERSION}}{{.SUFFIX}}
|
||||||
labels:
|
labels:
|
||||||
@@ -289,6 +292,7 @@ rancher:
|
|||||||
privileged: true
|
privileged: true
|
||||||
restart: always
|
restart: always
|
||||||
volumes_from:
|
volumes_from:
|
||||||
|
- command-volumes
|
||||||
- system-volumes
|
- system-volumes
|
||||||
system-volumes:
|
system-volumes:
|
||||||
image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}}
|
image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}}
|
||||||
@@ -325,9 +329,8 @@ rancher:
|
|||||||
uts: host
|
uts: host
|
||||||
privileged: true
|
privileged: true
|
||||||
volumes_from:
|
volumes_from:
|
||||||
|
- command-volumes
|
||||||
- system-volumes
|
- system-volumes
|
||||||
volumes:
|
|
||||||
- /usr/bin/ros:/usr/bin/ros:ro
|
|
||||||
udev:
|
udev:
|
||||||
image: {{.OS_REPO}}/os-udev:{{.VERSION}}{{.SUFFIX}}
|
image: {{.OS_REPO}}/os-udev:{{.VERSION}}{{.SUFFIX}}
|
||||||
environment:
|
environment:
|
||||||
@@ -340,6 +343,7 @@ rancher:
|
|||||||
privileged: true
|
privileged: true
|
||||||
restart: always
|
restart: always
|
||||||
volumes_from:
|
volumes_from:
|
||||||
|
- command-volumes
|
||||||
- system-volumes
|
- system-volumes
|
||||||
user-volumes:
|
user-volumes:
|
||||||
image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}}
|
image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}}
|
||||||
|
@@ -15,19 +15,19 @@ INITRD=${ARTIFACTS}/initrd
|
|||||||
|
|
||||||
mkdir -p ${ARTIFACTS} ${PREPOP_DIR}
|
mkdir -p ${ARTIFACTS} ${PREPOP_DIR}
|
||||||
|
|
||||||
if [ "$(docker info | grep 'Storage Driver: ' | sed 's/Storage Driver: //')" != "overlay" ]; then
|
#if [ "$(docker info | grep 'Storage Driver: ' | sed 's/Storage Driver: //')" != "overlay" ]; then
|
||||||
echo Overlay storage driver is require to prepackage exploded images
|
echo Overlay storage driver is require to prepackage exploded images
|
||||||
echo packaging images.tar instead
|
echo packaging images.tar instead
|
||||||
tar czf ${ARTIFACTS}/rootfs.tar.gz --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
tar czf ${ARTIFACTS}/rootfs.tar.gz --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
#fi
|
||||||
|
|
||||||
DFS=$(docker run -d --privileged -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) ${DFS_IMAGE}${SUFFIX} ${DFS_ARGS})
|
DFS=$(docker run -d --privileged -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) ${DFS_IMAGE}${SUFFIX} ${DFS_ARGS})
|
||||||
trap "docker rm -fv ${DFS_ARCH} ${DFS}" EXIT
|
trap "docker rm -fv ${DFS_ARCH} ${DFS}" EXIT
|
||||||
docker exec -i ${DFS} docker load < ${INITRD_DIR}/usr/share/ros/images.tar
|
docker exec -i ${DFS} docker load < ${INITRD_DIR}/usr/share/ros/images.tar
|
||||||
docker stop ${DFS}
|
docker stop ${DFS}
|
||||||
docker run --rm --volumes-from=${DFS} rancher/os-base tar -c -C /var/lib/docker ./image | tar -x -C ${PREPOP_DIR}
|
docker run --rm --volumes-from=${DFS} busybox tar -c -C /var/lib/docker ./image | tar -x -C ${PREPOP_DIR}
|
||||||
docker run --rm --volumes-from=${DFS} rancher/os-base tar -c -C /var/lib/docker ./overlay | tar -x -C ${PREPOP_DIR}
|
docker run --rm --volumes-from=${DFS} busybox tar -c -C /var/lib/docker ./overlay | tar -x -C ${PREPOP_DIR}
|
||||||
|
|
||||||
tar -cf ${ARTIFACTS}/rootfs.tar --exclude usr/share/ros/images.tar --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
tar -cf ${ARTIFACTS}/rootfs.tar --exclude usr/share/ros/images.tar --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
||||||
tar -rf ${ARTIFACTS}/rootfs.tar -C ${IMAGE_CACHE} .
|
tar -rf ${ARTIFACTS}/rootfs.tar -C ${IMAGE_CACHE} .
|
||||||
|
29
tests/assets/test_23/cloud-config.yml
Normal file
29
tests/assets/test_23/cloud-config.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#cloud-config
|
||||||
|
write_files:
|
||||||
|
- path: "/test"
|
||||||
|
permissions: "0644"
|
||||||
|
owner: "root"
|
||||||
|
content: |
|
||||||
|
console content
|
||||||
|
- path: "/test2"
|
||||||
|
container: console
|
||||||
|
permissions: "0644"
|
||||||
|
owner: "root"
|
||||||
|
content: |
|
||||||
|
console content
|
||||||
|
- path: "/test"
|
||||||
|
container: ntp
|
||||||
|
permissions: "0644"
|
||||||
|
owner: "root"
|
||||||
|
content: |
|
||||||
|
ntp content
|
||||||
|
- path: "/test"
|
||||||
|
container: syslog
|
||||||
|
permissions: "0644"
|
||||||
|
owner: "root"
|
||||||
|
content: |
|
||||||
|
syslog content
|
||||||
|
rancher:
|
||||||
|
restart_services: [syslog]
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC85w9stZyiLQp/DkVO6fqwiShYcj1ClKdtCqgHtf+PLpJkFReSFu8y21y+ev09gsSMRRrjF7yt0pUHV6zncQhVeqsZtgc5WbELY2DOYUGmRn/CCvPbXovoBrQjSorqlBmpuPwsStYLr92Xn+VVsMNSUIegHY22DphGbDKG85vrKB8HxUxGIDxFBds/uE8FhSy+xsoyT/jUZDK6pgq2HnGl6D81ViIlKecpOpWlW3B+fea99ADNyZNVvDzbHE5pcI3VRw8u59WmpWOUgT6qacNVACl8GqpBvQk8sw7O/X9DSZHCKafeD9G5k+GYbAUz92fKWrx/lOXfUXPS3+c8dRIF
|
@@ -7,6 +7,6 @@ func (s *QemuSuite) TestKernelHeaders(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
s.CheckCall(c, `
|
s.CheckCall(c, `
|
||||||
sleep 10
|
sleep 15
|
||||||
docker inspect kernel-headers`)
|
docker inspect kernel-headers`)
|
||||||
}
|
}
|
||||||
|
13
tests/write_files_test.go
Normal file
13
tests/write_files_test.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import . "gopkg.in/check.v1"
|
||||||
|
|
||||||
|
func (s *QemuSuite) TestWriteFiles(c *C) {
|
||||||
|
err := s.RunQemu("--cloud-config", "./tests/assets/test_23/cloud-config.yml")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
s.CheckCall(c, "sudo cat /test | grep 'console content'")
|
||||||
|
s.CheckCall(c, "sudo cat /test2 | grep 'console content'")
|
||||||
|
s.CheckCall(c, "sudo system-docker exec ntp cat /test | grep 'ntp content'")
|
||||||
|
s.CheckCall(c, "sudo system-docker exec syslog cat /test | grep 'syslog content'")
|
||||||
|
}
|
Reference in New Issue
Block a user