Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

corecfg: add proxy configuration via snap set core proxy.{http,https,ftp}=... #3594

Merged
merged 17 commits into from Aug 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions cmd/snapctl/main.go
Expand Up @@ -24,6 +24,7 @@ import (
"os"

"github.com/snapcore/snapd/client"
"github.com/snapcore/snapd/corecfg"
"github.com/snapcore/snapd/dirs"
)

Expand All @@ -38,6 +39,19 @@ var clientConfig = client.Config{
}

func main() {
// check for internal commands
if len(os.Args) > 2 && os.Args[1] == "internal" {
switch os.Args[2] {
case "configure-core":
if err := corecfg.Run(); err != nil {
fmt.Fprintf(os.Stderr, "core configuration error: %v\n", err)
os.Exit(1)
}
os.Exit(0)
}
}

// no internal command, route via snapd
stdout, stderr, err := run()
if err != nil {
fmt.Fprintf(os.Stderr, "error: %s\n", err)
Expand Down
83 changes: 83 additions & 0 deletions corecfg/corecfg.go
@@ -0,0 +1,83 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package corecfg

import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/snapcore/snapd/osutil"
"github.com/snapcore/snapd/release"
"github.com/snapcore/snapd/systemd"
)

var (
Stdout = os.Stdout
Stderr = os.Stderr
)

// ensureSupportInterface checks that the system has the core-support
// interface. An error is returned if this is not the case
func ensureSupportInterface() error {
_, err := systemd.SystemctlCmd("--version")
return err
}

func snapctlGet(key string) (string, error) {
raw, err := exec.Command("snapctl", "get", key).CombinedOutput()
if err != nil {
return "", fmt.Errorf("cannot run snapctl: %s", osutil.OutputErr(raw, err))
}

output := strings.TrimRight(string(raw), "\n")
return output, nil
}

func Run() error {
// see if it makes sense to run at all
if release.OnClassic {
return fmt.Errorf("cannot run core-configure on classic distribution")
}
if err := ensureSupportInterface(); err != nil {
return fmt.Errorf("cannot run systemctl - core-support interface seems disconnected: %v", err)
}

// handle the various core config options:
// service.*.disable
if err := handleServiceDisableConfiguration(); err != nil {
return err
}
// system.power-key-action
if err := handlePowerButtonConfiguration(); err != nil {
return err
}
// pi-config.*
if err := handlePiConfiguration(); err != nil {
return err
}
// proxy.{http,https,ftp}
if err := handleProxyConfiguration(); err != nil {
return err
}

return nil
}
58 changes: 58 additions & 0 deletions corecfg/corecfg_test.go
@@ -0,0 +1,58 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package corecfg_test

import (
"testing"

. "gopkg.in/check.v1"

"github.com/snapcore/snapd/corecfg"
"github.com/snapcore/snapd/release"
"github.com/snapcore/snapd/testutil"
)

func Test(t *testing.T) { TestingT(t) }

type coreCfgSuite struct{}

var _ = Suite(&coreCfgSuite{})

func (s *coreCfgSuite) TestConfigureErrorsOnClassic(c *C) {
restore := release.MockOnClassic(true)
defer restore()

err := corecfg.Run()
c.Check(err, ErrorMatches, "cannot run core-configure on classic distribution")
}

func (s *coreCfgSuite) TestConfigureErrorOnMissingCoreSupport(c *C) {
restore := release.MockOnClassic(false)
defer restore()

mockSystemctl := testutil.MockCommand(c, "systemctl", `
echo "simulate missing core-support"
exit 1
`)
defer mockSystemctl.Restore()

err := corecfg.Run()
c.Check(err, ErrorMatches, `(?m)cannot run systemctl - core-support interface seems disconnected: \[--version\] failed with exit status 1: simulate missing core-support`)
}
27 changes: 27 additions & 0 deletions corecfg/export_test.go
@@ -0,0 +1,27 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package corecfg

var (
UpdatePiConfig = updatePiConfig
SwitchHandlePowerKey = switchHandlePowerKey
SwitchDisableService = switchDisableService
UpdateKeyValueStream = updateKeyValueStream
)
98 changes: 98 additions & 0 deletions corecfg/picfg.go
@@ -0,0 +1,98 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package corecfg

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/osutil"
)

// valid pi config keys
var piConfigKeys = map[string]bool{
"disable_overscan": true,
"framebuffer_width": true,
"framebuffer_height": true,
"framebuffer_depth": true,
"framebuffer_ignore_alpha": true,
"overscan_left": true,
"overscan_right": true,
"overscan_top": true,
"overscan_bottom": true,
"overscan_scale": true,
"display_rotate": true,
"hdmi_group": true,
"hdmi_mode": true,
"hdmi_drive": true,
"avoid_warnings": true,
"gpu_mem_256": true,
"gpu_mem_512": true,
"gpu_mem": true,
"sdtv_aspect": true,
"config_hdmi_boost": true,
"hdmi_force_hotplug": true,
}

func updatePiConfig(path string, config map[string]string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()

toWrite, err := updateKeyValueStream(f, piConfigKeys, config)
if err != nil {
return err
}

if toWrite != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hold on, if there is nothing to write does that mean we should remove the original file or do nothing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do nothing, the original file may contain data that is opaque to us (like more entries in /etc/environment that we do not manage ourselfs).

s := strings.Join(toWrite, "\n")
return osutil.AtomicWriteFile(path, []byte(s), 0644, 0)
}

return nil
}

func piConfigFile() string {
return filepath.Join(dirs.GlobalRootDir, "/boot/uboot/config.txt")
}

func handlePiConfiguration() error {
if osutil.FileExists(piConfigFile()) {
// snapctl can actually give us the whole dict in
// JSON, in a single call; use that instead of this.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason we're not doing this?

config := map[string]string{}
for key := range piConfigKeys {
output, err := snapctlGet(fmt.Sprintf("pi-config.%s", strings.Replace(key, "_", "-", -1)))
if err != nil {
return err
}
config[key] = output
}
if err := updatePiConfig(piConfigFile(), config); err != nil {
return err
}
}
return nil
}