package cmd
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
coreosetcdclient "github.com/coreos/etcd/client"
"github.com/spf13/cobra"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"github.com/openshift/origin/pkg/cmd/admin/policy"
"github.com/openshift/origin/pkg/cmd/flagtypes"
configapi "github.com/openshift/origin/pkg/cmd/server/api"
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
"github.com/openshift/origin/pkg/cmd/server/etcd"
"github.com/openshift/origin/pkg/cmd/server/etcd/etcdserver"
"github.com/openshift/origin/pkg/cmd/server/origin"
"github.com/openshift/origin/pkg/cmd/server/start"
testutil "github.com/openshift/origin/test/util"
testserver "github.com/openshift/origin/test/util/server"
)
const RecommendedLoadEtcdDumpName = "start-api"
type DebugAPIServerOptions struct {
Out io.Writer
EtcdDumpFile string
AllowAll bool
}
func NewDebugAPIServerCommand() *cobra.Command {
o := &DebugAPIServerOptions{Out: os.Stdout}
cmd := &cobra.Command{
Use: RecommendedLoadEtcdDumpName + " etcd_dump.json",
Short: "Start API server using etcddump",
Run: func(cmd *cobra.Command, args []string) {
kcmdutil.CheckErr(o.Complete(args))
kcmdutil.CheckErr(o.Run())
},
}
cmd.Flags().BoolVar(&o.AllowAll, "allow-all", true, "change policy to grant system:authenticated cluster-admin powers")
flagtypes.GLog(cmd.PersistentFlags())
return cmd
}
func (o *DebugAPIServerOptions) Complete(args []string) error {
if len(args) != 1 {
return errors.New("etcd_dump.json file is required")
}
o.EtcdDumpFile = args[0]
return nil
}
func (o *DebugAPIServerOptions) Run() error {
masterConfig, err := testserver.DefaultMasterOptionsWithTweaks(true /*start etcd server*/, true /*use default ports*/)
if err != nil {
return err
}
etcdConfig := masterConfig.EtcdConfig
masterConfig.EtcdConfig = nil
masterConfig.DNSConfig = nil
etcdserver.RunEtcd(etcdConfig)
if err := o.ImportEtcdDump(masterConfig.EtcdClientInfo); err != nil {
return err
}
if err := o.StartAPIServer(*masterConfig); err != nil {
return err
}
if o.AllowAll {
osClient, err := testutil.GetClusterAdminClient(testutil.GetBaseDir() + "/openshift.local.config/master/admin.kubeconfig")
if err != nil {
return err
}
addClusterAdmin := &policy.RoleModificationOptions{
RoleName: bootstrappolicy.ClusterAdminRoleName,
RoleBindingAccessor: policy.ClusterRoleBindingAccessor{Client: osClient},
Groups: []string{"system:authenticated"},
}
if err := addClusterAdmin.AddRole(); err != nil {
return err
}
}
select {}
}
func (o *DebugAPIServerOptions) StartAPIServer(masterConfig configapi.MasterConfig) error {
openshiftConfig, err := origin.BuildMasterConfig(masterConfig)
if err != nil {
return err
}
kubeMasterConfig, err := start.BuildKubernetesMasterConfig(openshiftConfig)
if err != nil {
return err
}
fmt.Printf("Starting master on %s\n", masterConfig.ServingInfo.BindAddress)
fmt.Printf("Public master address is %s\n", masterConfig.AssetConfig.MasterPublicURL)
return start.StartAPI(openshiftConfig, kubeMasterConfig)
}
func (o *DebugAPIServerOptions) ImportEtcdDump(etcdClientInfo configapi.EtcdConnectionInfo) error {
infile, err := os.Open(o.EtcdDumpFile)
if err != nil {
return err
}
etcdDump := &coreosetcdclient.Response{}
if err := json.NewDecoder(infile).Decode(etcdDump); err != nil {
return err
}
// Connect and setup etcd interfaces
etcdClient, err := etcd.GetAndTestEtcdClient(etcdClientInfo)
if err != nil {
return err
}
nodeList := []*coreosetcdclient.Node{}
nodeList = append(nodeList, etcdDump.Node)
for i := 0; i < len(nodeList); i++ {
node := nodeList[i]
if node == nil {
continue
}
for j := range node.Nodes {
nodeList = append(nodeList, node.Nodes[j])
}
if len(node.Key) == 0 {
continue
}
if node.Dir {
if _, err := etcdClient.CreateDir(node.Key, uint64(0)); err != nil {
return err
}
continue
}
if _, err := etcdClient.Create(node.Key, node.Value, uint64(0)); err != nil {
return err
}
}
return nil
}