<commit_before>// Copyright 2014 Google Inc. All Rights Reserved.
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package social

import (
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"code.google.com/p/goauth2/oauth"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/base"
	"github.com/gogits/gogs/modules/log"
)

type BasicUserInfo struct {
	Identity string
	Name     string
	Email    string
}

type SocialConnector interface {
	Type() int
	SetRedirectUrl(string)
	UserInfo(*oauth.Token, *url.URL) (*BasicUserInfo, error)

	AuthCodeURL(string) string
	Exchange(string) (*oauth.Token, error)
}

var (
	SocialBaseUrl = "/user/login"
	SocialMap     = make(map[string]SocialConnector)
)

func NewOauthService() {
	if !base.Cfg.MustBool("oauth", "ENABLED") {
		return
	}

	base.OauthService = &base.Oauther{}
	base.OauthService.OauthInfos = make(map[string]*base.OauthInfo)

	socialConfigs := make(map[string]*oauth.Config)
	allOauthes := []string{"github", "google", "qq", "twitter", "weibo"}
	// Load all OAuth config data.
	for _, name := range allOauthes {
		base.OauthService.OauthInfos[name] = &base.OauthInfo{
			ClientId:     base.Cfg.MustValue("oauth."+name, "CLIENT_ID"),
			ClientSecret: base.Cfg.MustValue("oauth."+name, "CLIENT_SECRET"),
			Scopes:       base.Cfg.MustValue("oauth."+name, "SCOPES"),
			AuthUrl:      base.Cfg.MustValue("oauth."+name, "AUTH_URL"),
			TokenUrl:     base.Cfg.MustValue("oauth."+name, "TOKEN_URL"),
		}
		socialConfigs[name] = &oauth.Config{
			ClientId:     base.OauthService.OauthInfos[name].ClientId,
			ClientSecret: base.OauthService.OauthInfos[name].ClientSecret,
			RedirectURL:  strings.TrimSuffix(base.AppUrl, "/") + SocialBaseUrl + name,
			Scope:        base.OauthService.OauthInfos[name].Scopes,
			AuthURL:      base.OauthService.OauthInfos[name].AuthUrl,
			TokenURL:     base.OauthService.OauthInfos[name].TokenUrl,
		}
	}

	enabledOauths := make([]string, 0, 10)

	// GitHub.
	if base.Cfg.MustBool("oauth.github", "ENABLED") {
		base.OauthService.GitHub = true
		newGitHubOauth(socialConfigs["github"])
		enabledOauths = append(enabledOauths, "GitHub")
	}

	// Google.
	if base.Cfg.MustBool("oauth.google", "ENABLED") {
		base.OauthService.Google = true
		newGoogleOauth(socialConfigs["google"])
		enabledOauths = append(enabledOauths, "Google")
	}

	// QQ.
	if base.Cfg.MustBool("oauth.qq", "ENABLED") {
		base.OauthService.Tencent = true
		newTencentOauth(socialConfigs["qq"])
		enabledOauths = append(enabledOauths, "QQ")
	}

	// Twitter.
	if base.Cfg.MustBool("oauth.twitter", "ENABLED") {
		base.OauthService.Twitter = true
		newTwitterOauth(socialConfigs["twitter"])
		enabledOauths = append(enabledOauths, "Twitter")
	}

	// Weibo.
	if base.Cfg.MustBool("oauth.weibo", "ENABLED") {
		base.OauthService.Weibo = true
		newWeiboOauth(socialConfigs["weibo"])
		enabledOauths = append(enabledOauths, "Weibo")
	}

	log.Info("Oauth Service Enabled %s", enabledOauths)
}

//   ________.__  __     ___ ___      ___.
//  /  _____/|__|/  |_  /   |   \ __ _\_ |__
// /   \  ___|  \   __\/    ~    \  |  \ __ \
// \    \_\  \  ||  |  \    Y    /  |  / \_\ \
//  \______  /__||__|   \___|_  /|____/|___  /
//         \/                 \/           \/

type SocialGithub struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialGithub) Type() int {
	return models.OT_GITHUB
}

func newGitHubOauth(config *oauth.Config) {
	SocialMap["github"] = &SocialGithub{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialGithub) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	transport := &oauth.Transport{
		Token: token,
	}
	var data struct {
		Id    int    `json:"id"`
		Name  string `json:"login"`
		Email string `json:"email"`
	}
	var err error
	r, err := transport.Client().Get(s.Transport.Scope)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: strconv.Itoa(data.Id),
		Name:     data.Name,
		Email:    data.Email,
	}, nil
}

//   ________                     .__
//  /  _____/  ____   ____   ____ |  |   ____
// /   \  ___ /  _ \ /  _ \ / ___\|  | _/ __ \
// \    \_\  (  <_> |  <_> ) /_/  >  |_\  ___/
//  \______  /\____/ \____/\___  /|____/\___  >
//         \/             /_____/           \/

type SocialGoogle struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialGoogle) Type() int {
	return models.OT_GOOGLE
}

func newGoogleOauth(config *oauth.Config) {
	SocialMap["google"] = &SocialGoogle{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialGoogle) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	transport := &oauth.Transport{Token: token}
	var data struct {
		Id    string `json:"id"`
		Name  string `json:"name"`
		Email string `json:"email"`
	}
	var err error

	reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
	r, err := transport.Client().Get(reqUrl)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: data.Id,
		Name:     data.Name,
		Email:    data.Email,
	}, nil
}

// ________   ________
// \_____  \  \_____  \
//  /  / \  \  /  / \  \
// /   \_/.  \/   \_/.  \
// \_____\ \_/\_____\ \_/
//        \__>       \__>

type SocialTencent struct {
	Token *oauth.Token
	*oauth.Transport
	reqUrl string
}

func (s *SocialTencent) Type() int {
	return models.OT_QQ
}

func newTencentOauth(config *oauth.Config) {
	SocialMap["qq"] = &SocialTencent{
		reqUrl: "https://open.t.qq.com/api/user/info",
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialTencent) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialTencent) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserInfo, error) {
	var data struct {
		Data struct {
			Id    string `json:"openid"`
			Name  string `json:"name"`
			Email string `json:"email"`
		} `json:"data"`
	}
	var err error
	// https://open.t.qq.com/api/user/info?
	//oauth_consumer_key=APP_KEY&
	//access_token=ACCESSTOKEN&openid=openid
	//clientip=CLIENTIP&oauth_version=2.a
	//scope=all
	var urls = url.Values{
		"oauth_consumer_key": {s.Transport.Config.ClientId},
		"access_token":       {token.AccessToken},
		"openid":             URL.Query()["openid"],
		"oauth_version":      {"2.a"},
		"scope":              {"all"},
	}
	r, err := http.Get(s.reqUrl + "?" + urls.Encode())
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: data.Data.Id,
		Name:     data.Data.Name,
		Email:    data.Data.Email,
	}, nil
}

// ___________       .__  __    __
// \__    ___/_  _  _|__|/  |__/  |_  ___________
//   |    |  \ \/ \/ /  \   __\   __\/ __ \_  __ \
//   |    |   \     /|  ||  |  |  | \  ___/|  | \/
//   |____|    \/\_/ |__||__|  |__|  \___  >__|
//                                       \/

type SocialTwitter struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialTwitter) Type() int {
	return models.OT_TWITTER
}

func newTwitterOauth(config *oauth.Config) {
	SocialMap["twitter"] = &SocialTwitter{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialTwitter) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

//https://github.com/mrjones/oauth
func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	// transport := &oauth.Transport{Token: token}
	// var data struct {
	// 	Id    string `json:"id"`
	// 	Name  string `json:"name"`
	// 	Email string `json:"email"`
	// }
	// var err error

	// reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
	// r, err := transport.Client().Get(reqUrl)
	// if err != nil {
	// 	return nil, err
	// }
	// defer r.Body.Close()
	// if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
	// 	return nil, err
	// }
	// return &BasicUserInfo{
	// 	Identity: data.Id,
	// 	Name:     data.Name,
	// 	Email:    data.Email,
	// }, nil
	return nil, nil
}

//  __      __       ._____.
// /  \    /  \ ____ |__\_ |__   ____
// \   \/\/   // __ \|  || __ \ /  _ \
//  \        /\  ___/|  || \_\ (  <_> )
//   \__/\  /  \___  >__||___  /\____/
//        \/       \/        \/

type SocialWeibo struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialWeibo) Type() int {
	return models.OT_WEIBO
}

func newWeiboOauth(config *oauth.Config) {
	SocialMap["weibo"] = &SocialWeibo{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialWeibo) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialWeibo) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserInfo, error) {
	transport := &oauth.Transport{Token: token}
	var data struct {
		Id   string `json:"id"`
		Name string `json:"name"`
	}
	var err error

	var urls = url.Values{
		"access_token": {token.AccessToken},
		"uid":          URL.Query()["uid"],
	}
	reqUrl := "https://api.weibo.com/2/users/show.json"
	r, err := transport.Client().Get(reqUrl + "?" + urls.Encode())
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: data.Id,
		Name:     data.Name,
	}, nil
	return nil, nil
}
<commit_msg>Weibo oauth<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package social

import (
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	oauth "github.com/gogits/oauth2"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/base"
	"github.com/gogits/gogs/modules/log"
)

type BasicUserInfo struct {
	Identity string
	Name     string
	Email    string
}

type SocialConnector interface {
	Type() int
	SetRedirectUrl(string)
	UserInfo(*oauth.Token, *url.URL) (*BasicUserInfo, error)

	AuthCodeURL(string) string
	Exchange(string) (*oauth.Token, error)
}

var (
	SocialBaseUrl = "/user/login"
	SocialMap     = make(map[string]SocialConnector)
)

func NewOauthService() {
	if !base.Cfg.MustBool("oauth", "ENABLED") {
		return
	}

	base.OauthService = &base.Oauther{}
	base.OauthService.OauthInfos = make(map[string]*base.OauthInfo)

	socialConfigs := make(map[string]*oauth.Config)
	allOauthes := []string{"github", "google", "qq", "twitter", "weibo"}
	// Load all OAuth config data.
	for _, name := range allOauthes {
		base.OauthService.OauthInfos[name] = &base.OauthInfo{
			ClientId:     base.Cfg.MustValue("oauth."+name, "CLIENT_ID"),
			ClientSecret: base.Cfg.MustValue("oauth."+name, "CLIENT_SECRET"),
			Scopes:       base.Cfg.MustValue("oauth."+name, "SCOPES"),
			AuthUrl:      base.Cfg.MustValue("oauth."+name, "AUTH_URL"),
			TokenUrl:     base.Cfg.MustValue("oauth."+name, "TOKEN_URL"),
		}
		socialConfigs[name] = &oauth.Config{
			ClientId:     base.OauthService.OauthInfos[name].ClientId,
			ClientSecret: base.OauthService.OauthInfos[name].ClientSecret,
			RedirectURL:  strings.TrimSuffix(base.AppUrl, "/") + SocialBaseUrl + name,
			Scope:        base.OauthService.OauthInfos[name].Scopes,
			AuthURL:      base.OauthService.OauthInfos[name].AuthUrl,
			TokenURL:     base.OauthService.OauthInfos[name].TokenUrl,
		}
	}

	enabledOauths := make([]string, 0, 10)

	// GitHub.
	if base.Cfg.MustBool("oauth.github", "ENABLED") {
		base.OauthService.GitHub = true
		newGitHubOauth(socialConfigs["github"])
		enabledOauths = append(enabledOauths, "GitHub")
	}

	// Google.
	if base.Cfg.MustBool("oauth.google", "ENABLED") {
		base.OauthService.Google = true
		newGoogleOauth(socialConfigs["google"])
		enabledOauths = append(enabledOauths, "Google")
	}

	// QQ.
	if base.Cfg.MustBool("oauth.qq", "ENABLED") {
		base.OauthService.Tencent = true
		newTencentOauth(socialConfigs["qq"])
		enabledOauths = append(enabledOauths, "QQ")
	}

	// Twitter.
	if base.Cfg.MustBool("oauth.twitter", "ENABLED") {
		base.OauthService.Twitter = true
		newTwitterOauth(socialConfigs["twitter"])
		enabledOauths = append(enabledOauths, "Twitter")
	}

	// Weibo.
	if base.Cfg.MustBool("oauth.weibo", "ENABLED") {
		base.OauthService.Weibo = true
		newWeiboOauth(socialConfigs["weibo"])
		enabledOauths = append(enabledOauths, "Weibo")
	}

	log.Info("Oauth Service Enabled %s", enabledOauths)
}

//   ________.__  __     ___ ___      ___.
//  /  _____/|__|/  |_  /   |   \ __ _\_ |__
// /   \  ___|  \   __\/    ~    \  |  \ __ \
// \    \_\  \  ||  |  \    Y    /  |  / \_\ \
//  \______  /__||__|   \___|_  /|____/|___  /
//         \/                 \/           \/

type SocialGithub struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialGithub) Type() int {
	return models.OT_GITHUB
}

func newGitHubOauth(config *oauth.Config) {
	SocialMap["github"] = &SocialGithub{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialGithub) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	transport := &oauth.Transport{
		Token: token,
	}
	var data struct {
		Id    int    `json:"id"`
		Name  string `json:"login"`
		Email string `json:"email"`
	}
	var err error
	r, err := transport.Client().Get(s.Transport.Scope)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: strconv.Itoa(data.Id),
		Name:     data.Name,
		Email:    data.Email,
	}, nil
}

//   ________                     .__
//  /  _____/  ____   ____   ____ |  |   ____
// /   \  ___ /  _ \ /  _ \ / ___\|  | _/ __ \
// \    \_\  (  <_> |  <_> ) /_/  >  |_\  ___/
//  \______  /\____/ \____/\___  /|____/\___  >
//         \/             /_____/           \/

type SocialGoogle struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialGoogle) Type() int {
	return models.OT_GOOGLE
}

func newGoogleOauth(config *oauth.Config) {
	SocialMap["google"] = &SocialGoogle{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialGoogle) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	transport := &oauth.Transport{Token: token}
	var data struct {
		Id    string `json:"id"`
		Name  string `json:"name"`
		Email string `json:"email"`
	}
	var err error

	reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
	r, err := transport.Client().Get(reqUrl)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: data.Id,
		Name:     data.Name,
		Email:    data.Email,
	}, nil
}

// ________   ________
// \_____  \  \_____  \
//  /  / \  \  /  / \  \
// /   \_/.  \/   \_/.  \
// \_____\ \_/\_____\ \_/
//        \__>       \__>

type SocialTencent struct {
	Token *oauth.Token
	*oauth.Transport
	reqUrl string
}

func (s *SocialTencent) Type() int {
	return models.OT_QQ
}

func newTencentOauth(config *oauth.Config) {
	SocialMap["qq"] = &SocialTencent{
		reqUrl: "https://open.t.qq.com/api/user/info",
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialTencent) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialTencent) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserInfo, error) {
	var data struct {
		Data struct {
			Id    string `json:"openid"`
			Name  string `json:"name"`
			Email string `json:"email"`
		} `json:"data"`
	}
	var err error
	// https://open.t.qq.com/api/user/info?
	//oauth_consumer_key=APP_KEY&
	//access_token=ACCESSTOKEN&openid=openid
	//clientip=CLIENTIP&oauth_version=2.a
	//scope=all
	var urls = url.Values{
		"oauth_consumer_key": {s.Transport.Config.ClientId},
		"access_token":       {token.AccessToken},
		"openid":             URL.Query()["openid"],
		"oauth_version":      {"2.a"},
		"scope":              {"all"},
	}
	r, err := http.Get(s.reqUrl + "?" + urls.Encode())
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: data.Data.Id,
		Name:     data.Data.Name,
		Email:    data.Data.Email,
	}, nil
}

// ___________       .__  __    __
// \__    ___/_  _  _|__|/  |__/  |_  ___________
//   |    |  \ \/ \/ /  \   __\   __\/ __ \_  __ \
//   |    |   \     /|  ||  |  |  | \  ___/|  | \/
//   |____|    \/\_/ |__||__|  |__|  \___  >__|
//                                       \/

type SocialTwitter struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialTwitter) Type() int {
	return models.OT_TWITTER
}

func newTwitterOauth(config *oauth.Config) {
	SocialMap["twitter"] = &SocialTwitter{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialTwitter) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

//https://github.com/mrjones/oauth
func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	// transport := &oauth.Transport{Token: token}
	// var data struct {
	// 	Id    string `json:"id"`
	// 	Name  string `json:"name"`
	// 	Email string `json:"email"`
	// }
	// var err error

	// reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
	// r, err := transport.Client().Get(reqUrl)
	// if err != nil {
	// 	return nil, err
	// }
	// defer r.Body.Close()
	// if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
	// 	return nil, err
	// }
	// return &BasicUserInfo{
	// 	Identity: data.Id,
	// 	Name:     data.Name,
	// 	Email:    data.Email,
	// }, nil
	return nil, nil
}

//  __      __       ._____.
// /  \    /  \ ____ |__\_ |__   ____
// \   \/\/   // __ \|  || __ \ /  _ \
//  \        /\  ___/|  || \_\ (  <_> )
//   \__/\  /  \___  >__||___  /\____/
//        \/       \/        \/

type SocialWeibo struct {
	Token *oauth.Token
	*oauth.Transport
}

func (s *SocialWeibo) Type() int {
	return models.OT_WEIBO
}

func newWeiboOauth(config *oauth.Config) {
	SocialMap["weibo"] = &SocialWeibo{
		Transport: &oauth.Transport{
			Config:    config,
			Transport: http.DefaultTransport,
		},
	}
}

func (s *SocialWeibo) SetRedirectUrl(url string) {
	s.Transport.Config.RedirectURL = url
}

func (s *SocialWeibo) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
	transport := &oauth.Transport{Token: token}
	var data struct {
		Id   string `json:"id"`
		Name string `json:"name"`
	}
	var err error

	var urls = url.Values{
		"access_token": {token.AccessToken},
		"uid":          {token.Extra["id_token"]},
	}
	reqUrl := "https://api.weibo.com/2/users/show.json"
	r, err := transport.Client().Get(reqUrl + "?" + urls.Encode())
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
		return nil, err
	}
	return &BasicUserInfo{
		Identity: data.Id,
		Name:     data.Name,
	}, nil
	return nil, nil
}
<|endoftext|>


<commit_before>// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// this file contains protocol<->span converters

package protocol

import (
	"fmt"
	"go/token"

	"golang.org/x/tools/internal/span"
)

// A ColumnMapper maps between UTF-8 oriented positions (e.g. token.Pos,
// span.Span) and the UTF-16 oriented positions used by the LSP.
type ColumnMapper struct {
	URI     span.URI
	TokFile *token.File
	Content []byte
}

// NewColumnMapper creates a new column mapper for the given uri and content.
func NewColumnMapper(uri span.URI, content []byte) *ColumnMapper {
	tf := span.NewTokenFile(uri.Filename(), content)
	return &ColumnMapper{
		URI:     uri,
		TokFile: tf,
		Content: content,
	}
}

func URIFromSpanURI(uri span.URI) DocumentURI {
	return DocumentURI(uri)
}

func URIFromPath(path string) DocumentURI {
	return URIFromSpanURI(span.URIFromPath(path))
}

func (u DocumentURI) SpanURI() span.URI {
	return span.URIFromURI(string(u))
}

func (m *ColumnMapper) Location(s span.Span) (Location, error) {
	rng, err := m.Range(s)
	if err != nil {
		return Location{}, err
	}
	return Location{URI: URIFromSpanURI(s.URI()), Range: rng}, nil
}

func (m *ColumnMapper) Range(s span.Span) (Range, error) {
	if span.CompareURI(m.URI, s.URI()) != 0 {
		return Range{}, fmt.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI())
	}
	s, err := s.WithAll(m.TokFile)
	if err != nil {
		return Range{}, err
	}
	start, err := m.Position(s.Start())
	if err != nil {
		return Range{}, err
	}
	end, err := m.Position(s.End())
	if err != nil {
		return Range{}, err
	}
	return Range{Start: start, End: end}, nil
}

// OffsetRange returns a Range for the byte-offset interval Content[start:end],
func (m *ColumnMapper) OffsetRange(start, end int) (Range, error) {
	// TODO(adonovan): this can surely be simplified by expressing
	// it terms of more primitive operations.

	// We use span.ToPosition for its "line+1 at EOF" workaround.
	startLine, startCol, err := span.ToPosition(m.TokFile, start)
	if err != nil {
		return Range{}, fmt.Errorf("start line/col: %v", err)
	}
	startPoint := span.NewPoint(startLine, startCol, start)
	startPosition, err := m.Position(startPoint)
	if err != nil {
		return Range{}, fmt.Errorf("start position: %v", err)
	}

	endLine, endCol, err := span.ToPosition(m.TokFile, end)
	if err != nil {
		return Range{}, fmt.Errorf("end line/col: %v", err)
	}
	endPoint := span.NewPoint(endLine, endCol, end)
	endPosition, err := m.Position(endPoint)
	if err != nil {
		return Range{}, fmt.Errorf("end position: %v", err)
	}

	return Range{Start: startPosition, End: endPosition}, nil
}

func (m *ColumnMapper) Position(p span.Point) (Position, error) {
	chr, err := span.ToUTF16Column(p, m.Content)
	if err != nil {
		return Position{}, err
	}
	return Position{
		Line:      uint32(p.Line() - 1),
		Character: uint32(chr - 1),
	}, nil
}

func (m *ColumnMapper) Span(l Location) (span.Span, error) {
	return m.RangeSpan(l.Range)
}

func (m *ColumnMapper) RangeSpan(r Range) (span.Span, error) {
	start, err := m.Point(r.Start)
	if err != nil {
		return span.Span{}, err
	}
	end, err := m.Point(r.End)
	if err != nil {
		return span.Span{}, err
	}
	return span.New(m.URI, start, end).WithAll(m.TokFile)
}

func (m *ColumnMapper) RangeToSpanRange(r Range) (span.Range, error) {
	spn, err := m.RangeSpan(r)
	if err != nil {
		return span.Range{}, err
	}
	return spn.Range(m.TokFile)
}

// Pos returns the token.Pos of p within the mapped file.
func (m *ColumnMapper) Pos(p Position) (token.Pos, error) {
	start, err := m.Point(p)
	if err != nil {
		return token.NoPos, err
	}
	// TODO: refactor the span package to avoid creating this unnecessary end position.
	spn, err := span.New(m.URI, start, start).WithAll(m.TokFile)
	if err != nil {
		return token.NoPos, err
	}
	rng, err := spn.Range(m.TokFile)
	if err != nil {
		return token.NoPos, err
	}
	return rng.Start, nil
}

// Offset returns the utf-8 byte offset of p within the mapped file.
func (m *ColumnMapper) Offset(p Position) (int, error) {
	start, err := m.Point(p)
	if err != nil {
		return 0, err
	}
	return start.Offset(), nil
}

// Point returns a span.Point for p within the mapped file. The resulting point
// always has an Offset.
func (m *ColumnMapper) Point(p Position) (span.Point, error) {
	line := int(p.Line) + 1
	offset, err := span.ToOffset(m.TokFile, line, 1)
	if err != nil {
		return span.Point{}, err
	}
	lineStart := span.NewPoint(line, 1, offset)
	return span.FromUTF16Column(lineStart, int(p.Character)+1, m.Content)
}

func IsPoint(r Range) bool {
	return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character
}

// CompareRange returns -1 if a is before b, 0 if a == b, and 1 if a is after
// b.
//
// A range a is defined to be 'before' b if a.Start is before b.Start, or
// a.Start == b.Start and a.End is before b.End.
func CompareRange(a, b Range) int {
	if r := ComparePosition(a.Start, b.Start); r != 0 {
		return r
	}
	return ComparePosition(a.End, b.End)
}

// ComparePosition returns -1 if a is before b, 0 if a == b, and 1 if a is
// after b.
func ComparePosition(a, b Position) int {
	if a.Line < b.Line {
		return -1
	}
	if a.Line > b.Line {
		return 1
	}
	if a.Character < b.Character {
		return -1
	}
	if a.Character > b.Character {
		return 1
	}
	return 0
}

func Intersect(a, b Range) bool {
	if a.Start.Line > b.End.Line || a.End.Line < b.Start.Line {
		return false
	}
	return !((a.Start.Line == b.End.Line) && a.Start.Character > b.End.Character ||
		(a.End.Line == b.Start.Line) && a.End.Character < b.Start.Character)
}

// Format implements fmt.Formatter.
//
// Note: Formatter is implemented instead of Stringer (presumably) for
// performance reasons, though it is not clear that it matters in practice.
func (r Range) Format(f fmt.State, _ rune) {
	fmt.Fprintf(f, "%v-%v", r.Start, r.End)
}

// Format implements fmt.Formatter.
//
// See Range.Format for discussion of why the Formatter interface is
// implemented rather than Stringer.
func (p Position) Format(f fmt.State, _ rune) {
	fmt.Fprintf(f, "%v:%v", p.Line, p.Character)
}
<commit_msg>gopls/internal/lsp/protocol: simplify OffsetRange, Position<commit_after>// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// this file contains protocol<->span converters

package protocol

import (
	"bytes"
	"fmt"
	"go/token"
	"unicode/utf8"

	"golang.org/x/tools/internal/span"
)

// A ColumnMapper maps between UTF-8 oriented positions (e.g. token.Pos,
// span.Span) and the UTF-16 oriented positions used by the LSP.
type ColumnMapper struct {
	URI     span.URI
	TokFile *token.File
	Content []byte

	// File content is only really needed for UTF-16 column
	// computation, which could be be achieved more compactly.
	// For example, one could record only the lines for which
	// UTF-16 columns differ from the UTF-8 ones, or only the
	// indices of the non-ASCII characters.
	//
	// TODO(adonovan): consider not retaining the entire file
	// content, or at least not exposing the fact that we
	// currently retain it.
}

// NewColumnMapper creates a new column mapper for the given uri and content.
func NewColumnMapper(uri span.URI, content []byte) *ColumnMapper {
	tf := span.NewTokenFile(uri.Filename(), content)
	return &ColumnMapper{
		URI:     uri,
		TokFile: tf,
		Content: content,
	}
}

func URIFromSpanURI(uri span.URI) DocumentURI {
	return DocumentURI(uri)
}

func URIFromPath(path string) DocumentURI {
	return URIFromSpanURI(span.URIFromPath(path))
}

func (u DocumentURI) SpanURI() span.URI {
	return span.URIFromURI(string(u))
}

func (m *ColumnMapper) Location(s span.Span) (Location, error) {
	rng, err := m.Range(s)
	if err != nil {
		return Location{}, err
	}
	return Location{URI: URIFromSpanURI(s.URI()), Range: rng}, nil
}

func (m *ColumnMapper) Range(s span.Span) (Range, error) {
	if span.CompareURI(m.URI, s.URI()) != 0 {
		return Range{}, fmt.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI())
	}
	s, err := s.WithAll(m.TokFile)
	if err != nil {
		return Range{}, err
	}
	start, err := m.Position(s.Start())
	if err != nil {
		return Range{}, err
	}
	end, err := m.Position(s.End())
	if err != nil {
		return Range{}, err
	}
	return Range{Start: start, End: end}, nil
}

// OffsetRange returns a Range for the byte-offset interval Content[start:end],
func (m *ColumnMapper) OffsetRange(start, end int) (Range, error) {
	startPosition, err := m.OffsetPosition(start)
	if err != nil {
		return Range{}, fmt.Errorf("start: %v", err)
	}

	endPosition, err := m.OffsetPosition(end)
	if err != nil {
		return Range{}, fmt.Errorf("end: %v", err)
	}

	return Range{Start: startPosition, End: endPosition}, nil
}

// Position returns the protocol position for the specified point,
// which must have a byte offset.
func (m *ColumnMapper) Position(p span.Point) (Position, error) {
	if !p.HasOffset() {
		return Position{}, fmt.Errorf("point is missing offset")
	}
	return m.OffsetPosition(p.Offset())
}

// OffsetPosition returns the protocol position of the specified
// offset within m.Content.
func (m *ColumnMapper) OffsetPosition(offset int) (Position, error) {
	// We use span.ToPosition for its "line+1 at EOF" workaround.
	// TODO(adonovan): ToPosition honors //line directives. It probably shouldn't.
	line, _, err := span.ToPosition(m.TokFile, offset)
	if err != nil {
		return Position{}, fmt.Errorf("OffsetPosition: %v", err)
	}
	// If that workaround executed, skip the usual column computation.
	char := 0
	if offset != m.TokFile.Size() {
		char = m.utf16Column(offset)
	}
	return Position{
		Line:      uint32(line - 1),
		Character: uint32(char),
	}, nil
}

// utf16Column returns the zero-based column index of the
// specified file offset, measured in UTF-16 codes.
// Precondition: 0 <= offset <= len(m.Content).
func (m *ColumnMapper) utf16Column(offset int) int {
	s := m.Content[:offset]
	if i := bytes.LastIndex(s, []byte("\n")); i >= 0 {
		s = s[i+1:]
	}
	// s is the prefix of the line before offset.
	return utf16len(s)
}

// utf16len returns the number of codes in the UTF-16 transcoding of s.
func utf16len(s []byte) int {
	var n int
	for len(s) > 0 {
		n++

		// Fast path for ASCII.
		if s[0] < 0x80 {
			s = s[1:]
			continue
		}

		r, size := utf8.DecodeRune(s)
		if r >= 0x10000 {
			n++ // surrogate pair
		}
		s = s[size:]
	}
	return n
}

func (m *ColumnMapper) Span(l Location) (span.Span, error) {
	return m.RangeSpan(l.Range)
}

func (m *ColumnMapper) RangeSpan(r Range) (span.Span, error) {
	start, err := m.Point(r.Start)
	if err != nil {
		return span.Span{}, err
	}
	end, err := m.Point(r.End)
	if err != nil {
		return span.Span{}, err
	}
	return span.New(m.URI, start, end).WithAll(m.TokFile)
}

func (m *ColumnMapper) RangeToSpanRange(r Range) (span.Range, error) {
	spn, err := m.RangeSpan(r)
	if err != nil {
		return span.Range{}, err
	}
	return spn.Range(m.TokFile)
}

// Pos returns the token.Pos of p within the mapped file.
func (m *ColumnMapper) Pos(p Position) (token.Pos, error) {
	start, err := m.Point(p)
	if err != nil {
		return token.NoPos, err
	}
	// TODO: refactor the span package to avoid creating this unnecessary end position.
	spn, err := span.New(m.URI, start, start).WithAll(m.TokFile)
	if err != nil {
		return token.NoPos, err
	}
	rng, err := spn.Range(m.TokFile)
	if err != nil {
		return token.NoPos, err
	}
	return rng.Start, nil
}

// Offset returns the utf-8 byte offset of p within the mapped file.
func (m *ColumnMapper) Offset(p Position) (int, error) {
	start, err := m.Point(p)
	if err != nil {
		return 0, err
	}
	return start.Offset(), nil
}

// Point returns a span.Point for p within the mapped file. The resulting point
// always has an Offset.
func (m *ColumnMapper) Point(p Position) (span.Point, error) {
	line := int(p.Line) + 1
	offset, err := span.ToOffset(m.TokFile, line, 1)
	if err != nil {
		return span.Point{}, err
	}
	lineStart := span.NewPoint(line, 1, offset)
	return span.FromUTF16Column(lineStart, int(p.Character)+1, m.Content)
}

func IsPoint(r Range) bool {
	return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character
}

// CompareRange returns -1 if a is before b, 0 if a == b, and 1 if a is after
// b.
//
// A range a is defined to be 'before' b if a.Start is before b.Start, or
// a.Start == b.Start and a.End is before b.End.
func CompareRange(a, b Range) int {
	if r := ComparePosition(a.Start, b.Start); r != 0 {
		return r
	}
	return ComparePosition(a.End, b.End)
}

// ComparePosition returns -1 if a is before b, 0 if a == b, and 1 if a is
// after b.
func ComparePosition(a, b Position) int {
	if a.Line < b.Line {
		return -1
	}
	if a.Line > b.Line {
		return 1
	}
	if a.Character < b.Character {
		return -1
	}
	if a.Character > b.Character {
		return 1
	}
	return 0
}

func Intersect(a, b Range) bool {
	if a.Start.Line > b.End.Line || a.End.Line < b.Start.Line {
		return false
	}
	return !((a.Start.Line == b.End.Line) && a.Start.Character > b.End.Character ||
		(a.End.Line == b.Start.Line) && a.End.Character < b.Start.Character)
}

// Format implements fmt.Formatter.
//
// Note: Formatter is implemented instead of Stringer (presumably) for
// performance reasons, though it is not clear that it matters in practice.
func (r Range) Format(f fmt.State, _ rune) {
	fmt.Fprintf(f, "%v-%v", r.Start, r.End)
}

// Format implements fmt.Formatter.
//
// See Range.Format for discussion of why the Formatter interface is
// implemented rather than Stringer.
func (p Position) Format(f fmt.State, _ rune) {
	fmt.Fprintf(f, "%v:%v", p.Line, p.Character)
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. 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.

// Handler for Docker containers.
package common

import (
	"fmt"
	"sync"
	"time"

	"github.com/google/cadvisor/fs"

	"k8s.io/klog"
)

type FsHandler interface {
	Start()
	Usage() FsUsage
	Stop()
}

type FsUsage struct {
	BaseUsageBytes  uint64
	TotalUsageBytes uint64
	InodeUsage      uint64
}

type realFsHandler struct {
	sync.RWMutex
	lastUpdate time.Time
	usage      FsUsage
	period     time.Duration
	minPeriod  time.Duration
	rootfs     string
	extraDir   string
	fsInfo     fs.FsInfo
	// Tells the container to stop.
	stopChan chan struct{}
}

const (
	maxBackoffFactor = 20
)

const DefaultPeriod = time.Minute

var _ FsHandler = &realFsHandler{}

func NewFsHandler(period time.Duration, rootfs, extraDir string, fsInfo fs.FsInfo) FsHandler {
	return &realFsHandler{
		lastUpdate: time.Time{},
		usage:      FsUsage{},
		period:     period,
		minPeriod:  period,
		rootfs:     rootfs,
		extraDir:   extraDir,
		fsInfo:     fsInfo,
		stopChan:   make(chan struct{}, 1),
	}
}

func (fh *realFsHandler) update() error {
	var (
		rootUsage, extraUsage fs.UsageInfo
		rootErr, extraErr     error
	)
	// TODO(vishh): Add support for external mounts.
	if fh.rootfs != "" {
		rootUsage, rootErr = fh.fsInfo.GetDirUsage(fh.rootfs)
	}

	if fh.extraDir != "" {
		extraUsage, extraErr = fh.fsInfo.GetDirUsage(fh.extraDir)
	}

	// Wait to handle errors until after all operartions are run.
	// An error in one will not cause an early return, skipping others
	fh.Lock()
	defer fh.Unlock()
	fh.lastUpdate = time.Now()
	if fh.rootfs != "" && rootErr == nil {
		fh.usage.InodeUsage = rootUsage.Inodes
		fh.usage.TotalUsageBytes = rootUsage.Bytes + extraUsage.Bytes
	}
	if fh.extraDir != "" && extraErr == nil {
		fh.usage.BaseUsageBytes = rootUsage.Bytes
	}

	// Combine errors into a single error to return
	if rootErr != nil || extraErr != nil {
		return fmt.Errorf("rootDiskErr: %v, extraDiskErr: %v", rootErr, extraErr)
	}
	return nil
}

func (fh *realFsHandler) trackUsage() {
	longOp := time.Second
	for {
		start := time.Now()
		if err := fh.update(); err != nil {
			klog.Errorf("failed to collect filesystem stats - %v", err)
			fh.period = fh.period * 2
			if fh.period > maxBackoffFactor*fh.minPeriod {
				fh.period = maxBackoffFactor * fh.minPeriod
			}
		} else {
			fh.period = fh.minPeriod
		}
		duration := time.Since(start)
		if duration > longOp {
			// adapt longOp time so that message doesn't continue to print
			// if the long duration is persistent either because of slow
			// disk or lots of containers.
			longOp = longOp + time.Second
			klog.V(2).Infof("fs: disk usage and inodes count on following dirs took %v: %v; will not log again for this container unless duration exceeds %v", duration, []string{fh.rootfs, fh.extraDir}, longOp)
		}
		select {
		case <-fh.stopChan:
			return
		case <-time.After(fh.period):
		}
	}
}

func (fh *realFsHandler) Start() {
	go fh.trackUsage()
}

func (fh *realFsHandler) Stop() {
	close(fh.stopChan)
}

func (fh *realFsHandler) Usage() FsUsage {
	fh.RLock()
	defer fh.RUnlock()
	return fh.usage
}
<commit_msg>Check extraErr before accessing extraUsage.Bytes (#2401)<commit_after>// Copyright 2015 Google Inc. 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.

// Handler for Docker containers.
package common

import (
	"fmt"
	"sync"
	"time"

	"github.com/google/cadvisor/fs"

	"k8s.io/klog"
)

type FsHandler interface {
	Start()
	Usage() FsUsage
	Stop()
}

type FsUsage struct {
	BaseUsageBytes  uint64
	TotalUsageBytes uint64
	InodeUsage      uint64
}

type realFsHandler struct {
	sync.RWMutex
	lastUpdate time.Time
	usage      FsUsage
	period     time.Duration
	minPeriod  time.Duration
	rootfs     string
	extraDir   string
	fsInfo     fs.FsInfo
	// Tells the container to stop.
	stopChan chan struct{}
}

const (
	maxBackoffFactor = 20
)

const DefaultPeriod = time.Minute

var _ FsHandler = &realFsHandler{}

func NewFsHandler(period time.Duration, rootfs, extraDir string, fsInfo fs.FsInfo) FsHandler {
	return &realFsHandler{
		lastUpdate: time.Time{},
		usage:      FsUsage{},
		period:     period,
		minPeriod:  period,
		rootfs:     rootfs,
		extraDir:   extraDir,
		fsInfo:     fsInfo,
		stopChan:   make(chan struct{}, 1),
	}
}

func (fh *realFsHandler) update() error {
	var (
		rootUsage, extraUsage fs.UsageInfo
		rootErr, extraErr     error
	)
	// TODO(vishh): Add support for external mounts.
	if fh.rootfs != "" {
		rootUsage, rootErr = fh.fsInfo.GetDirUsage(fh.rootfs)
	}

	if fh.extraDir != "" {
		extraUsage, extraErr = fh.fsInfo.GetDirUsage(fh.extraDir)
	}

	// Wait to handle errors until after all operartions are run.
	// An error in one will not cause an early return, skipping others
	fh.Lock()
	defer fh.Unlock()
	fh.lastUpdate = time.Now()
	if fh.rootfs != "" && rootErr == nil {
		fh.usage.InodeUsage = rootUsage.Inodes
		fh.usage.BaseUsageBytes = rootUsage.Bytes
		fh.usage.TotalUsageBytes = rootUsage.Bytes
	}
	if fh.extraDir != "" && extraErr == nil {
		fh.usage.TotalUsageBytes += extraUsage.Bytes
	}

	// Combine errors into a single error to return
	if rootErr != nil || extraErr != nil {
		return fmt.Errorf("rootDiskErr: %v, extraDiskErr: %v", rootErr, extraErr)
	}
	return nil
}

func (fh *realFsHandler) trackUsage() {
	longOp := time.Second
	for {
		start := time.Now()
		if err := fh.update(); err != nil {
			klog.Errorf("failed to collect filesystem stats - %v", err)
			fh.period = fh.period * 2
			if fh.period > maxBackoffFactor*fh.minPeriod {
				fh.period = maxBackoffFactor * fh.minPeriod
			}
		} else {
			fh.period = fh.minPeriod
		}
		duration := time.Since(start)
		if duration > longOp {
			// adapt longOp time so that message doesn't continue to print
			// if the long duration is persistent either because of slow
			// disk or lots of containers.
			longOp = longOp + time.Second
			klog.V(2).Infof("fs: disk usage and inodes count on following dirs took %v: %v; will not log again for this container unless duration exceeds %v", duration, []string{fh.rootfs, fh.extraDir}, longOp)
		}
		select {
		case <-fh.stopChan:
			return
		case <-time.After(fh.period):
		}
	}
}

func (fh *realFsHandler) Start() {
	go fh.trackUsage()
}

func (fh *realFsHandler) Stop() {
	close(fh.stopChan)
}

func (fh *realFsHandler) Usage() FsUsage {
	fh.RLock()
	defer fh.RUnlock()
	return fh.usage
}
<|endoftext|>


<commit_before>package network

import (
	"fmt"
	"math"

	ipv4 "github.com/mpreath/netcalc/utils"
)

type NetworkNode struct {
	Network *Network       `json:"network,omitempty"`
	Parent  *NetworkNode   `json:"-"`
	Subnets []*NetworkNode `json:"subnets,omitempty"`
}

func (node *NetworkNode) Split() error {
	bc := ipv4.GetBitsInMask(node.Network.Mask) + 1
	if bc < 31 {
		new_mask, err := ipv4.GetMaskFromBits(bc)
		if err != nil {
			return err
		}
		// left will contain the lower value
		left_network, err := GenerateNetworkFromBits(node.Network.Address, new_mask)
		if err != nil {
			return err
		}

		node.Subnets = append(node.Subnets, &NetworkNode{Parent: node, Network: left_network})

		// right will contain the larger value
		right_network, err := GenerateNetworkFromBits(left_network.BroadcastAddress+1, new_mask)
		if err != nil {
			return err
		}

		node.Subnets = append(node.Subnets, &NetworkNode{Parent: node, Network: right_network})

		// no usable hosts in this network
		node.Network.Hosts = nil
	} else {
		return fmt.Errorf("network doesn't support being split")
	}

	return nil
}

func SplitToHostCount(node *NetworkNode, host_count int) error {

	// FIXME: Doesn't support host_count of 2
	// TODO: Add error handling and edge case protection
	current_bc := 32 - ipv4.GetBitsInMask(node.Network.Mask)
	current_hc := int(math.Pow(2, float64(current_bc)))
	future_bc := current_bc - 1 // need to look ahead into the future
	future_hc := int(math.Pow(2, float64(future_bc)))

	if current_hc >= host_count && future_hc < host_count {
		// this is our recursive base case
		return nil
	} else if current_hc < host_count {
		// requirements too large, raise an error
		return fmt.Errorf("network can't support that many hosts")
	} else {
		err := node.Split()
		if err != nil {
			return err
		}
		err = SplitToHostCount(node.Subnets[0], host_count)
		if err != nil {
			return err
		}
		err = SplitToHostCount(node.Subnets[1], host_count)
		if err != nil {
			return err
		}
	}

	return nil
}

func SplitToNetCount(node *NetworkNode, net_count int) error {
	longest_valid_mask, _ := ipv4.GetMaskFromBits(30)
	if net_count <= 0 {
		// this is our recursive base case
		return nil
	} else if node.Network.Mask == longest_valid_mask {
		// can't split any more
		return fmt.Errorf("network can't support that many subnetworks")
	} else {
		err := node.Split()
		if err != nil {
			return err
		}
		err = SplitToNetCount(node.Subnets[0], net_count-2)
		if err != nil {
			return err
		}
		err = SplitToNetCount(node.Subnets[1], net_count-2)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>cleanup<commit_after>package network

import (
	"fmt"
	"math"

	"github.com/mpreath/netcalc/utils"
)

type NetworkNode struct {
	Network *Network       `json:"network,omitempty"`
	Parent  *NetworkNode   `json:"-"`
	Subnets []*NetworkNode `json:"subnets,omitempty"`
}

func (node *NetworkNode) Split() error {
	bc := utils.GetBitsInMask(node.Network.Mask) + 1
	if bc < 31 {
		new_mask, err := utils.GetMaskFromBits(bc)
		if err != nil {
			return err
		}
		// left will contain the lower value
		left_network, err := GenerateNetworkFromBits(node.Network.Address, new_mask)
		if err != nil {
			return err
		}

		node.Subnets = append(node.Subnets, &NetworkNode{Parent: node, Network: left_network})

		// right will contain the larger value
		right_network, err := GenerateNetworkFromBits(left_network.BroadcastAddress+1, new_mask)
		if err != nil {
			return err
		}

		node.Subnets = append(node.Subnets, &NetworkNode{Parent: node, Network: right_network})

		// no usable hosts in this network
		node.Network.Hosts = nil
	} else {
		return fmt.Errorf("network doesn't support being split")
	}

	return nil
}

func SplitToHostCount(node *NetworkNode, host_count int) error {
	current_mask_bc := utils.GetBitsInMask(node.Network.Mask)
	if current_mask_bc >= 30 {
		// this is the longest mask we support
		return nil
	}
	current_bc := 32 - current_mask_bc
	current_hc := int(math.Pow(2, float64(current_bc)))
	future_bc := current_bc - 1 // need to look ahead into the future
	future_hc := int(math.Pow(2, float64(future_bc)))

	if current_hc >= host_count && future_hc < host_count {
		// this is our recursive base case
		return nil
	} else if current_hc < host_count {
		// requirements too large, raise an error
		return fmt.Errorf("network can't support that many hosts")
	} else {
		err := node.Split()
		if err != nil {
			return err
		}
		err = SplitToHostCount(node.Subnets[0], host_count)
		if err != nil {
			return err
		}
		err = SplitToHostCount(node.Subnets[1], host_count)
		if err != nil {
			return err
		}
	}

	return nil
}

func SplitToNetCount(node *NetworkNode, net_count int) error {
	longest_valid_mask, _ := utils.GetMaskFromBits(30)
	if net_count <= 0 {
		// this is our recursive base case
		return nil
	} else if node.Network.Mask == longest_valid_mask {
		// can't split any more
		return fmt.Errorf("network can't support that many subnetworks")
	} else {
		err := node.Split()
		if err != nil {
			return err
		}
		err = SplitToNetCount(node.Subnets[0], net_count-2)
		if err != nil {
			return err
		}
		err = SplitToNetCount(node.Subnets[1], net_count-2)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"

	"github.com/v2ray/v2ray-core"
	_ "github.com/v2ray/v2ray-core/app/router/rules"
	"github.com/v2ray/v2ray-core/common/log"
	"github.com/v2ray/v2ray-core/shell/point"

	// The following are necessary as they register handlers in their init functions.
	_ "github.com/v2ray/v2ray-core/proxy/blackhole"
	_ "github.com/v2ray/v2ray-core/proxy/dokodemo"
	_ "github.com/v2ray/v2ray-core/proxy/freedom"
	_ "github.com/v2ray/v2ray-core/proxy/http"
	_ "github.com/v2ray/v2ray-core/proxy/shadowsocks"
	_ "github.com/v2ray/v2ray-core/proxy/socks"
	_ "github.com/v2ray/v2ray-core/proxy/vmess/inbound"
	_ "github.com/v2ray/v2ray-core/proxy/vmess/outbound"

	_ "github.com/v2ray/v2ray-core/transport/internet/kcp"
	_ "github.com/v2ray/v2ray-core/transport/internet/tcp"
	_ "github.com/v2ray/v2ray-core/transport/internet/udp"

	_ "github.com/v2ray/v2ray-core/transport/internet/authenticators/noop"
	_ "github.com/v2ray/v2ray-core/transport/internet/authenticators/srtp"
)

var (
	configFile string
	logLevel   = flag.String("loglevel", "warning", "Level of log info to be printed to console, available value: debug, info, warning, error")
	version    = flag.Bool("version", false, "Show current version of V2Ray.")
	test       = flag.Bool("test", false, "Test config file only, without launching V2Ray server.")
)

func init() {
	defaultConfigFile := ""
	workingDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err == nil {
		defaultConfigFile = filepath.Join(workingDir, "config.json")
	}
	flag.StringVar(&configFile, "config", defaultConfigFile, "Config file for this Point server.")
}

func startV2Ray() *point.Point {
	switch *logLevel {
	case "debug":
		log.SetLogLevel(log.DebugLevel)
	case "info":
		log.SetLogLevel(log.InfoLevel)
	case "warning":
		log.SetLogLevel(log.WarningLevel)
	case "error":
		log.SetLogLevel(log.ErrorLevel)
	default:
		fmt.Println("Unknown log level: " + *logLevel)
		return nil
	}

	if len(configFile) == 0 {
		log.Error("Config file is not set.")
		return nil
	}
	config, err := point.LoadConfig(configFile)
	if err != nil {
		log.Error("Failed to read config file (", configFile, "): ", configFile, err)
		return nil
	}

	if config.LogConfig != nil && len(config.LogConfig.AccessLog) > 0 {
		log.InitAccessLogger(config.LogConfig.AccessLog)
	}

	vPoint, err := point.NewPoint(config)
	if err != nil {
		log.Error("Failed to create Point server: ", err)
		return nil
	}

	if *test {
		fmt.Println("Configuration OK.")
		return nil
	}

	err = vPoint.Start()
	if err != nil {
		log.Error("Error starting Point server: ", err)
		return nil
	}

	return vPoint
}

func main() {
	flag.Parse()

	core.PrintVersion()

	if *version {
		return
	}

	if point := startV2Ray(); point != nil {
		osSignals := make(chan os.Signal, 1)
		signal.Notify(osSignals, os.Interrupt, os.Kill)

		<-osSignals
		point.Close()
	}
	log.Close()
}
<commit_msg>load ws transport on init<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"

	"github.com/v2ray/v2ray-core"
	_ "github.com/v2ray/v2ray-core/app/router/rules"
	"github.com/v2ray/v2ray-core/common/log"
	"github.com/v2ray/v2ray-core/shell/point"

	// The following are necessary as they register handlers in their init functions.
	_ "github.com/v2ray/v2ray-core/proxy/blackhole"
	_ "github.com/v2ray/v2ray-core/proxy/dokodemo"
	_ "github.com/v2ray/v2ray-core/proxy/freedom"
	_ "github.com/v2ray/v2ray-core/proxy/http"
	_ "github.com/v2ray/v2ray-core/proxy/shadowsocks"
	_ "github.com/v2ray/v2ray-core/proxy/socks"
	_ "github.com/v2ray/v2ray-core/proxy/vmess/inbound"
	_ "github.com/v2ray/v2ray-core/proxy/vmess/outbound"

	_ "github.com/v2ray/v2ray-core/transport/internet/kcp"
	_ "github.com/v2ray/v2ray-core/transport/internet/tcp"
	_ "github.com/v2ray/v2ray-core/transport/internet/udp"
	_ "github.com/v2ray/v2ray-core/transport/internet/ws"

	_ "github.com/v2ray/v2ray-core/transport/internet/authenticators/noop"
	_ "github.com/v2ray/v2ray-core/transport/internet/authenticators/srtp"
)

var (
	configFile string
	logLevel   = flag.String("loglevel", "warning", "Level of log info to be printed to console, available value: debug, info, warning, error")
	version    = flag.Bool("version", false, "Show current version of V2Ray.")
	test       = flag.Bool("test", false, "Test config file only, without launching V2Ray server.")
)

func init() {
	defaultConfigFile := ""
	workingDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err == nil {
		defaultConfigFile = filepath.Join(workingDir, "config.json")
	}
	flag.StringVar(&configFile, "config", defaultConfigFile, "Config file for this Point server.")
}

func startV2Ray() *point.Point {
	switch *logLevel {
	case "debug":
		log.SetLogLevel(log.DebugLevel)
	case "info":
		log.SetLogLevel(log.InfoLevel)
	case "warning":
		log.SetLogLevel(log.WarningLevel)
	case "error":
		log.SetLogLevel(log.ErrorLevel)
	default:
		fmt.Println("Unknown log level: " + *logLevel)
		return nil
	}

	if len(configFile) == 0 {
		log.Error("Config file is not set.")
		return nil
	}
	config, err := point.LoadConfig(configFile)
	if err != nil {
		log.Error("Failed to read config file (", configFile, "): ", configFile, err)
		return nil
	}

	if config.LogConfig != nil && len(config.LogConfig.AccessLog) > 0 {
		log.InitAccessLogger(config.LogConfig.AccessLog)
	}

	vPoint, err := point.NewPoint(config)
	if err != nil {
		log.Error("Failed to create Point server: ", err)
		return nil
	}

	if *test {
		fmt.Println("Configuration OK.")
		return nil
	}

	err = vPoint.Start()
	if err != nil {
		log.Error("Error starting Point server: ", err)
		return nil
	}

	return vPoint
}

func main() {
	flag.Parse()

	core.PrintVersion()

	if *version {
		return
	}

	if point := startV2Ray(); point != nil {
		osSignals := make(chan os.Signal, 1)
		signal.Notify(osSignals, os.Interrupt, os.Kill)

		<-osSignals
		point.Close()
	}
	log.Close()
}
<|endoftext|>


<commit_before>// Copyright 2016 The Minimal Configuration Manager Authors
//
// 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.

package shlib

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
)

type gen struct {
	ew     errWriter
	indent int
}

func newGen(w io.Writer) *gen {
	return &gen{ew: errWriter{w: w}}
}

var newline = []byte{'\n'}

func (g *gen) p(args ...interface{}) {
	if len(args) == 0 {
		g.ew.Write(newline)
		return
	}
	var buf []byte
	for i := 0; i < g.indent; i++ {
		buf = append(buf, ' ', ' ')
	}
	for i, a := range args {
		if i > 0 {
			buf = append(buf, ' ')
		}
		if a, ok := a.(heredoc); ok {
			if i != len(args)-1 {
				panic(errors.New("heredoc placed in non-final argument"))
			}
			g.ew.Write(buf)
			a.encode(&g.ew)
			g.ew.Write(newline)
			return
		}
		buf = appendPArg(buf, a)
	}
	buf = append(buf, '\n')
	g.ew.Write(buf)
}

func appendPArg(buf []byte, a interface{}) []byte {
	switch a := a.(type) {
	case string:
		return appendShellQuote(buf, a)
	case script:
		return append(buf, a...)
	case int:
		return strconv.AppendInt(buf, int64(a), 10)
	case assignment:
		// TODO(maybe): check name for shell safety?
		buf = append(buf, a.name...)
		buf = append(buf, '=')
		return appendPArg(buf, a.value)
	default:
		panic(fmt.Errorf("unknown type: %T", a))
	}
}

func (g *gen) in()  { g.indent++ }
func (g *gen) out() { g.indent-- }

type errWriter struct {
	w   io.Writer
	err error
}

func newErrWriter(w io.Writer) *errWriter {
	if ew, ok := w.(*errWriter); ok {
		return ew
	}
	return &errWriter{w: w}
}

func (ew *errWriter) Write(p []byte) (n int, err error) {
	if ew.err != nil {
		return 0, ew.err
	}
	n, ew.err = ew.w.Write(p)
	return n, ew.err
}

func (ew *errWriter) WriteString(s string) (n int, err error) {
	if ew.err != nil {
		return 0, ew.err
	}
	n, ew.err = io.WriteString(ew.w, s)
	return n, ew.err
}

// script is properly escaped bash.
type script string

func (s script) String() string {
	return string(s)
}

type heredoc struct {
	marker string
	// TODO(someday): use io.WriterTo to avoid copying in base64 case
	data []byte
}

func (hd heredoc) encode(w io.Writer) error {
	ew := newErrWriter(w)
	ew.WriteString("<<'")
	ew.WriteString(hd.marker)
	ew.WriteString("'\n")
	ew.Write(hd.data)
	ew.Write(newline)
	ew.WriteString(hd.marker)
	return ew.err
}

func (hd heredoc) String() string {
	var buf bytes.Buffer
	hd.encode(&buf)
	return buf.String()
}

type assignment struct {
	name  string
	value interface{}
}

func (a assignment) String() string {
	return string(appendPArg(nil, a))
}

func appendShellQuote(buf []byte, s string) []byte {
	if s == "" {
		return append(buf, '\'', '\'')
	}
	safe := true
	for i := 0; i < len(s); i++ {
		if !isShellSafe(s[i]) {
			safe = false
			break
		}
	}
	if safe {
		return append(buf, s...)
	}
	buf = append(buf, '\'')
	for i := 0; i < len(s); i++ {
		if s[i] == '\'' {
			buf = append(buf, '\'', '\\', '\'', '\'')
		} else {
			buf = append(buf, s[i])
		}
	}
	buf = append(buf, '\'')
	return buf
}

func isShellSafe(b byte) bool {
	return b >= 'A' && b <= 'Z' || b >= 'a' && b <= 'z' || b >= '0' && b <= '9' || b == '-' || b == '_' || b == '/' || b == '.'
}
<commit_msg>shellify: tabs >> spaces<commit_after>// Copyright 2016 The Minimal Configuration Manager Authors
//
// 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.

package shlib

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
)

type gen struct {
	ew     errWriter
	indent int
}

func newGen(w io.Writer) *gen {
	return &gen{ew: errWriter{w: w}}
}

var newline = []byte{'\n'}

func (g *gen) p(args ...interface{}) {
	if len(args) == 0 {
		g.ew.Write(newline)
		return
	}
	var buf []byte
	for i := 0; i < g.indent; i++ {
		buf = append(buf, '\t')
	}
	for i, a := range args {
		if i > 0 {
			buf = append(buf, ' ')
		}
		if a, ok := a.(heredoc); ok {
			if i != len(args)-1 {
				panic(errors.New("heredoc placed in non-final argument"))
			}
			g.ew.Write(buf)
			a.encode(&g.ew)
			g.ew.Write(newline)
			return
		}
		buf = appendPArg(buf, a)
	}
	buf = append(buf, '\n')
	g.ew.Write(buf)
}

func appendPArg(buf []byte, a interface{}) []byte {
	switch a := a.(type) {
	case string:
		return appendShellQuote(buf, a)
	case script:
		return append(buf, a...)
	case int:
		return strconv.AppendInt(buf, int64(a), 10)
	case assignment:
		// TODO(maybe): check name for shell safety?
		buf = append(buf, a.name...)
		buf = append(buf, '=')
		return appendPArg(buf, a.value)
	default:
		panic(fmt.Errorf("unknown type: %T", a))
	}
}

func (g *gen) in()  { g.indent++ }
func (g *gen) out() { g.indent-- }

type errWriter struct {
	w   io.Writer
	err error
}

func newErrWriter(w io.Writer) *errWriter {
	if ew, ok := w.(*errWriter); ok {
		return ew
	}
	return &errWriter{w: w}
}

func (ew *errWriter) Write(p []byte) (n int, err error) {
	if ew.err != nil {
		return 0, ew.err
	}
	n, ew.err = ew.w.Write(p)
	return n, ew.err
}

func (ew *errWriter) WriteString(s string) (n int, err error) {
	if ew.err != nil {
		return 0, ew.err
	}
	n, ew.err = io.WriteString(ew.w, s)
	return n, ew.err
}

// script is properly escaped bash.
type script string

func (s script) String() string {
	return string(s)
}

type heredoc struct {
	marker string
	// TODO(someday): use io.WriterTo to avoid copying in base64 case
	data []byte
}

func (hd heredoc) encode(w io.Writer) error {
	ew := newErrWriter(w)
	ew.WriteString("<<'")
	ew.WriteString(hd.marker)
	ew.WriteString("'\n")
	ew.Write(hd.data)
	ew.Write(newline)
	ew.WriteString(hd.marker)
	return ew.err
}

func (hd heredoc) String() string {
	var buf bytes.Buffer
	hd.encode(&buf)
	return buf.String()
}

type assignment struct {
	name  string
	value interface{}
}

func (a assignment) String() string {
	return string(appendPArg(nil, a))
}

func appendShellQuote(buf []byte, s string) []byte {
	if s == "" {
		return append(buf, '\'', '\'')
	}
	safe := true
	for i := 0; i < len(s); i++ {
		if !isShellSafe(s[i]) {
			safe = false
			break
		}
	}
	if safe {
		return append(buf, s...)
	}
	buf = append(buf, '\'')
	for i := 0; i < len(s); i++ {
		if s[i] == '\'' {
			buf = append(buf, '\'', '\\', '\'', '\'')
		} else {
			buf = append(buf, s[i])
		}
	}
	buf = append(buf, '\'')
	return buf
}

func isShellSafe(b byte) bool {
	return b >= 'A' && b <= 'Z' || b >= 'a' && b <= 'z' || b >= '0' && b <= '9' || b == '-' || b == '_' || b == '/' || b == '.'
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"time"

	"bytes"

	"github.com/mailgun/mailgun-go"
)

func genNoSleepMessage() string {
	return `
You have no sleep records from last night.
Were you wearing your Fitbit?
    `
}

func genSleepMessage(sleep SleepResponse) (string, error) {
	t, err := time.Parse("2006-01-02T15:04:05.999999999", sleep.Sleep[0].StartTime)

	if err != nil {
		return "", err
	}

	data := struct {
		Efficiency   int
		StartTime    string
		AwakeCount   int
		MinutesAwake int
	}{
		Efficiency:   sleep.Sleep[0].Efficiency,
		StartTime:    t.Format(time.Kitchen),
		AwakeCount:   sleep.Sleep[0].AwakeCount,
		MinutesAwake: sleep.Sleep[0].MinutesAwake,
	}

	tmpl := template.Must(template.ParseFiles("templates/email.tmpl"))

	var b bytes.Buffer

	err = tmpl.Execute(&b, data)

	if err != nil {
		return "", err
	}

	return b.String(), nil
}

func sendEmail(mg mailgun.Mailgun, sleep SleepResponse, u *User) error {
	fromAddr := "admin@" + mg.Domain()
	subject := "Last Night's Sleep"
	toAddr := u.Email
	var body string

	if sleep.Summary.TotalSleepRecords > 0 {
		var err error
		body, err = genSleepMessage(sleep)

		if err != nil {
			return err
		}
	} else {
		body = genNoSleepMessage()
	}

	msg := mg.NewMessage(fromAddr, subject, body, toAddr)
	_, _, err := mg.Send(msg)

	if err != nil {
		return err
	}

	return nil
}
<commit_msg>add logging<commit_after>package main

import (
	"html/template"
	"log"
	"time"

	"bytes"

	"github.com/mailgun/mailgun-go"
)

func genNoSleepMessage() string {
	return `
You have no sleep records from last night.
Were you wearing your Fitbit?
    `
}

func genSleepMessage(sleep SleepResponse) (string, error) {
	t, err := time.Parse("2006-01-02T15:04:05.999999999", sleep.Sleep[0].StartTime)

	if err != nil {
		return "", err
	}

	data := struct {
		Efficiency   int
		StartTime    string
		AwakeCount   int
		MinutesAwake int
	}{
		Efficiency:   sleep.Sleep[0].Efficiency,
		StartTime:    t.Format(time.Kitchen),
		AwakeCount:   sleep.Sleep[0].AwakeCount,
		MinutesAwake: sleep.Sleep[0].MinutesAwake,
	}

	tmpl := template.Must(template.ParseFiles("templates/email.tmpl"))

	var b bytes.Buffer

	err = tmpl.Execute(&b, data)

	if err != nil {
		return "", err
	}

	return b.String(), nil
}

func sendEmail(mg mailgun.Mailgun, sleep SleepResponse, u *User) error {
	fromAddr := "admin@" + mg.Domain()
	subject := "Last Night's Sleep"
	toAddr := u.Email
	var body string

	if sleep.Summary.TotalSleepRecords > 0 {
		var err error
		body, err = genSleepMessage(sleep)

		if err != nil {
			return err
		}
	} else {
		body = genNoSleepMessage()
	}

	log.Printf("Sending message to %s\n", u.Email)
	msg := mg.NewMessage(fromAddr, subject, body, toAddr)
	_, _, err := mg.Send(msg)

	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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.
*/

package fieldmanager

import (
	"fmt"

	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
	openapiproto "k8s.io/kube-openapi/pkg/util/proto"
	"sigs.k8s.io/structured-merge-diff/v3/fieldpath"
)

// DefaultMaxUpdateManagers defines the default maximum retained number of managedFields entries from updates
// if the number of update managers exceeds this, the oldest entries will be merged until the number is below the maximum.
// TODO(jennybuckley): Determine if this is really the best value. Ideally we wouldn't unnecessarily merge too many entries.
const DefaultMaxUpdateManagers int = 10

// DefaultTrackOnCreateProbability defines the default probability that the field management of an object
// starts being tracked from the object's creation, instead of from the first time the object is applied to.
const DefaultTrackOnCreateProbability float32 = 0.5

// Managed groups a fieldpath.ManagedFields together with the timestamps associated with each operation.
type Managed interface {
	// Fields gets the fieldpath.ManagedFields.
	Fields() fieldpath.ManagedFields

	// Times gets the timestamps associated with each operation.
	Times() map[string]*metav1.Time
}

// Manager updates the managed fields and merges applied configurations.
type Manager interface {
	// Update is used when the object has already been merged (non-apply
	// use-case), and simply updates the managed fields in the output
	// object.
	Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error)

	// Apply is used when server-side apply is called, as it merges the
	// object and updates the managed fields.
	Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error)
}

// FieldManager updates the managed fields and merge applied
// configurations.
type FieldManager struct {
	fieldManager Manager
}

// NewFieldManager creates a new FieldManager that decodes, manages, then re-encodes managedFields
// on update and apply requests.
func NewFieldManager(f Manager) *FieldManager {
	return &FieldManager{f}
}

// NewDefaultFieldManager creates a new FieldManager that merges apply requests
// and update managed fields for other types of requests.
func NewDefaultFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion) (*FieldManager, error) {
	f, err := NewStructuredMergeManager(models, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
	if err != nil {
		return nil, fmt.Errorf("failed to create field manager: %v", err)
	}
	return newDefaultFieldManager(f, objectCreater, kind), nil
}

// NewDefaultCRDFieldManager creates a new FieldManager specifically for
// CRDs. This allows for the possibility of fields which are not defined
// in models, as well as having no models defined at all.
func NewDefaultCRDFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, preserveUnknownFields bool) (_ *FieldManager, err error) {
	f, err := NewCRDStructuredMergeManager(models, objectConverter, objectDefaulter, kind.GroupVersion(), hub, preserveUnknownFields)
	if err != nil {
		return nil, fmt.Errorf("failed to create field manager: %v", err)
	}
	return newDefaultFieldManager(f, objectCreater, kind), nil
}

// newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
func newDefaultFieldManager(f Manager, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind) *FieldManager {
	f = NewStripMetaManager(f)
	f = NewBuildManagerInfoManager(f, kind.GroupVersion())
	f = NewCapManagersManager(f, DefaultMaxUpdateManagers)
	f = NewProbabilisticSkipNonAppliedManager(f, objectCreater, kind, DefaultTrackOnCreateProbability)
	return NewFieldManager(f)
}

// Update is used when the object has already been merged (non-apply
// use-case), and simply updates the managed fields in the output
// object.
func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (object runtime.Object, err error) {
	// If the object doesn't have metadata, we should just return without trying to
	// set the managedFields at all, so creates/updates/patches will work normally.
	if _, err = meta.Accessor(newObj); err != nil {
		return newObj, nil
	}

	// First try to decode the managed fields provided in the update,
	// This is necessary to allow directly updating managed fields.
	var managed Managed
	if managed, err = internal.DecodeObjectManagedFields(newObj); err != nil || len(managed.Fields()) == 0 {
		// If the managed field is empty or we failed to decode it,
		// let's try the live object. This is to prevent clients who
		// don't understand managedFields from deleting it accidentally.
		managed, err = internal.DecodeObjectManagedFields(liveObj)
		if err != nil {
			return nil, fmt.Errorf("failed to decode managed fields: %v", err)
		}
	}

	internal.RemoveObjectManagedFields(liveObj)
	internal.RemoveObjectManagedFields(newObj)

	if object, managed, err = f.fieldManager.Update(liveObj, newObj, managed, manager); err != nil {
		return nil, err
	}

	if err = internal.EncodeObjectManagedFields(object, managed); err != nil {
		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
	}

	return object, nil
}

// Apply is used when server-side apply is called, as it merges the
// object and updates the managed fields.
func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string, force bool) (object runtime.Object, err error) {
	// If the object doesn't have metadata, apply isn't allowed.
	if _, err = meta.Accessor(liveObj); err != nil {
		return nil, fmt.Errorf("couldn't get accessor: %v", err)
	}

	// Decode the managed fields in the live object, since it isn't allowed in the patch.
	var managed Managed
	if managed, err = internal.DecodeObjectManagedFields(liveObj); err != nil {
		return nil, fmt.Errorf("failed to decode managed fields: %v", err)
	}

	internal.RemoveObjectManagedFields(liveObj)

	if object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force); err != nil {
		return nil, err
	}

	if err = internal.EncodeObjectManagedFields(object, managed); err != nil {
		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
	}

	return object, nil
}
<commit_msg>Enable field management for all new objects<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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.
*/

package fieldmanager

import (
	"fmt"

	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
	openapiproto "k8s.io/kube-openapi/pkg/util/proto"
	"sigs.k8s.io/structured-merge-diff/v3/fieldpath"
)

// DefaultMaxUpdateManagers defines the default maximum retained number of managedFields entries from updates
// if the number of update managers exceeds this, the oldest entries will be merged until the number is below the maximum.
// TODO(jennybuckley): Determine if this is really the best value. Ideally we wouldn't unnecessarily merge too many entries.
const DefaultMaxUpdateManagers int = 10

// DefaultTrackOnCreateProbability defines the default probability that the field management of an object
// starts being tracked from the object's creation, instead of from the first time the object is applied to.
const DefaultTrackOnCreateProbability float32 = 1

// Managed groups a fieldpath.ManagedFields together with the timestamps associated with each operation.
type Managed interface {
	// Fields gets the fieldpath.ManagedFields.
	Fields() fieldpath.ManagedFields

	// Times gets the timestamps associated with each operation.
	Times() map[string]*metav1.Time
}

// Manager updates the managed fields and merges applied configurations.
type Manager interface {
	// Update is used when the object has already been merged (non-apply
	// use-case), and simply updates the managed fields in the output
	// object.
	Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error)

	// Apply is used when server-side apply is called, as it merges the
	// object and updates the managed fields.
	Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error)
}

// FieldManager updates the managed fields and merge applied
// configurations.
type FieldManager struct {
	fieldManager Manager
}

// NewFieldManager creates a new FieldManager that decodes, manages, then re-encodes managedFields
// on update and apply requests.
func NewFieldManager(f Manager) *FieldManager {
	return &FieldManager{f}
}

// NewDefaultFieldManager creates a new FieldManager that merges apply requests
// and update managed fields for other types of requests.
func NewDefaultFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion) (*FieldManager, error) {
	f, err := NewStructuredMergeManager(models, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
	if err != nil {
		return nil, fmt.Errorf("failed to create field manager: %v", err)
	}
	return newDefaultFieldManager(f, objectCreater, kind), nil
}

// NewDefaultCRDFieldManager creates a new FieldManager specifically for
// CRDs. This allows for the possibility of fields which are not defined
// in models, as well as having no models defined at all.
func NewDefaultCRDFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, preserveUnknownFields bool) (_ *FieldManager, err error) {
	f, err := NewCRDStructuredMergeManager(models, objectConverter, objectDefaulter, kind.GroupVersion(), hub, preserveUnknownFields)
	if err != nil {
		return nil, fmt.Errorf("failed to create field manager: %v", err)
	}
	return newDefaultFieldManager(f, objectCreater, kind), nil
}

// newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
func newDefaultFieldManager(f Manager, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind) *FieldManager {
	f = NewStripMetaManager(f)
	f = NewBuildManagerInfoManager(f, kind.GroupVersion())
	f = NewCapManagersManager(f, DefaultMaxUpdateManagers)
	f = NewProbabilisticSkipNonAppliedManager(f, objectCreater, kind, DefaultTrackOnCreateProbability)
	return NewFieldManager(f)
}

// Update is used when the object has already been merged (non-apply
// use-case), and simply updates the managed fields in the output
// object.
func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (object runtime.Object, err error) {
	// If the object doesn't have metadata, we should just return without trying to
	// set the managedFields at all, so creates/updates/patches will work normally.
	if _, err = meta.Accessor(newObj); err != nil {
		return newObj, nil
	}

	// First try to decode the managed fields provided in the update,
	// This is necessary to allow directly updating managed fields.
	var managed Managed
	if managed, err = internal.DecodeObjectManagedFields(newObj); err != nil || len(managed.Fields()) == 0 {
		// If the managed field is empty or we failed to decode it,
		// let's try the live object. This is to prevent clients who
		// don't understand managedFields from deleting it accidentally.
		managed, err = internal.DecodeObjectManagedFields(liveObj)
		if err != nil {
			return nil, fmt.Errorf("failed to decode managed fields: %v", err)
		}
	}

	internal.RemoveObjectManagedFields(liveObj)
	internal.RemoveObjectManagedFields(newObj)

	if object, managed, err = f.fieldManager.Update(liveObj, newObj, managed, manager); err != nil {
		return nil, err
	}

	if err = internal.EncodeObjectManagedFields(object, managed); err != nil {
		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
	}

	return object, nil
}

// Apply is used when server-side apply is called, as it merges the
// object and updates the managed fields.
func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string, force bool) (object runtime.Object, err error) {
	// If the object doesn't have metadata, apply isn't allowed.
	if _, err = meta.Accessor(liveObj); err != nil {
		return nil, fmt.Errorf("couldn't get accessor: %v", err)
	}

	// Decode the managed fields in the live object, since it isn't allowed in the patch.
	var managed Managed
	if managed, err = internal.DecodeObjectManagedFields(liveObj); err != nil {
		return nil, fmt.Errorf("failed to decode managed fields: %v", err)
	}

	internal.RemoveObjectManagedFields(liveObj)

	if object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force); err != nil {
		return nil, err
	}

	if err = internal.EncodeObjectManagedFields(object, managed); err != nil {
		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
	}

	return object, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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.
*/

package v1alpha1

import (
	"path/filepath"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kruntime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/kubernetes/pkg/kubelet/qos"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
	"k8s.io/kubernetes/pkg/master/ports"
	utilpointer "k8s.io/kubernetes/pkg/util/pointer"
)

const (
	DefaultRootDir = "/var/lib/kubelet"

	// DEPRECATED: auto detecting cloud providers goes against the initiative
	// for out-of-tree cloud providers as we'll now depend on cAdvisor integrations
	// with cloud providers instead of in the core repo.
	// More details here: https://github.com/kubernetes/kubernetes/issues/50986
	AutoDetectCloudProvider = "auto-detect"

	defaultIPTablesMasqueradeBit = 14
	defaultIPTablesDropBit       = 15
)

var (
	zeroDuration = metav1.Duration{}
	// Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information.
	defaultNodeAllocatableEnforcement = []string{"pods"}
)

func addDefaultingFuncs(scheme *kruntime.Scheme) error {
	return RegisterDefaults(scheme)
}

func SetDefaults_KubeletConfiguration(obj *KubeletConfiguration) {
	// pointer because the zeroDuration is valid - if you want to skip the trial period
	if obj.ConfigTrialDuration == nil {
		obj.ConfigTrialDuration = &metav1.Duration{Duration: 10 * time.Minute}
	}
	if obj.Authentication.Anonymous.Enabled == nil {
		obj.Authentication.Anonymous.Enabled = boolVar(true)
	}
	if obj.Authentication.Webhook.Enabled == nil {
		obj.Authentication.Webhook.Enabled = boolVar(false)
	}
	if obj.Authentication.Webhook.CacheTTL == zeroDuration {
		obj.Authentication.Webhook.CacheTTL = metav1.Duration{Duration: 2 * time.Minute}
	}
	if obj.Authorization.Mode == "" {
		obj.Authorization.Mode = KubeletAuthorizationModeAlwaysAllow
	}
	if obj.Authorization.Webhook.CacheAuthorizedTTL == zeroDuration {
		obj.Authorization.Webhook.CacheAuthorizedTTL = metav1.Duration{Duration: 5 * time.Minute}
	}
	if obj.Authorization.Webhook.CacheUnauthorizedTTL == zeroDuration {
		obj.Authorization.Webhook.CacheUnauthorizedTTL = metav1.Duration{Duration: 30 * time.Second}
	}

	if obj.Address == "" {
		obj.Address = "0.0.0.0"
	}
	if obj.CAdvisorPort == nil {
		obj.CAdvisorPort = utilpointer.Int32Ptr(4194)
	}
	if obj.VolumeStatsAggPeriod == zeroDuration {
		obj.VolumeStatsAggPeriod = metav1.Duration{Duration: time.Minute}
	}
	if obj.RuntimeRequestTimeout == zeroDuration {
		obj.RuntimeRequestTimeout = metav1.Duration{Duration: 2 * time.Minute}
	}
	if obj.CPUCFSQuota == nil {
		obj.CPUCFSQuota = boolVar(true)
	}
	if obj.EventBurst == 0 {
		obj.EventBurst = 10
	}
	if obj.EventRecordQPS == nil {
		temp := int32(5)
		obj.EventRecordQPS = &temp
	}
	if obj.EnableControllerAttachDetach == nil {
		obj.EnableControllerAttachDetach = boolVar(true)
	}
	if obj.EnableDebuggingHandlers == nil {
		obj.EnableDebuggingHandlers = boolVar(true)
	}
	if obj.EnableServer == nil {
		obj.EnableServer = boolVar(true)
	}
	if obj.FileCheckFrequency == zeroDuration {
		obj.FileCheckFrequency = metav1.Duration{Duration: 20 * time.Second}
	}
	if obj.HealthzBindAddress == "" {
		obj.HealthzBindAddress = "127.0.0.1"
	}
	if obj.HealthzPort == nil {
		obj.HealthzPort = utilpointer.Int32Ptr(10248)
	}
	if obj.HostNetworkSources == nil {
		obj.HostNetworkSources = []string{kubetypes.AllSource}
	}
	if obj.HostPIDSources == nil {
		obj.HostPIDSources = []string{kubetypes.AllSource}
	}
	if obj.HostIPCSources == nil {
		obj.HostIPCSources = []string{kubetypes.AllSource}
	}
	if obj.HTTPCheckFrequency == zeroDuration {
		obj.HTTPCheckFrequency = metav1.Duration{Duration: 20 * time.Second}
	}
	if obj.ImageMinimumGCAge == zeroDuration {
		obj.ImageMinimumGCAge = metav1.Duration{Duration: 2 * time.Minute}
	}
	if obj.ImageGCHighThresholdPercent == nil {
		// default is below docker's default dm.min_free_space of 90%
		temp := int32(85)
		obj.ImageGCHighThresholdPercent = &temp
	}
	if obj.ImageGCLowThresholdPercent == nil {
		temp := int32(80)
		obj.ImageGCLowThresholdPercent = &temp
	}
	if obj.MaxOpenFiles == 0 {
		obj.MaxOpenFiles = 1000000
	}
	if obj.MaxPods == 0 {
		obj.MaxPods = 110
	}
	if obj.VolumePluginDir == "" {
		obj.VolumePluginDir = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/"
	}
	if obj.NodeStatusUpdateFrequency == zeroDuration {
		obj.NodeStatusUpdateFrequency = metav1.Duration{Duration: 10 * time.Second}
	}
	if obj.CPUManagerPolicy == "" {
		obj.CPUManagerPolicy = "none"
	}
	if obj.CPUManagerReconcilePeriod == zeroDuration {
		obj.CPUManagerReconcilePeriod = obj.NodeStatusUpdateFrequency
	}
	if obj.OOMScoreAdj == nil {
		temp := int32(qos.KubeletOOMScoreAdj)
		obj.OOMScoreAdj = &temp
	}
	if obj.Port == 0 {
		obj.Port = ports.KubeletPort
	}
	if obj.ReadOnlyPort == nil {
		obj.ReadOnlyPort = utilpointer.Int32Ptr(ports.KubeletReadOnlyPort)
	}
	if obj.RegisterNode == nil {
		obj.RegisterNode = boolVar(true)
	}
	if obj.RegistryBurst == 0 {
		obj.RegistryBurst = 10
	}
	if obj.RegistryPullQPS == nil {
		temp := int32(5)
		obj.RegistryPullQPS = &temp
	}
	if obj.ResolverConfig == "" {
		obj.ResolverConfig = kubetypes.ResolvConfDefault
	}
	if obj.SerializeImagePulls == nil {
		obj.SerializeImagePulls = boolVar(true)
	}
	if obj.SeccompProfileRoot == "" {
		obj.SeccompProfileRoot = filepath.Join(DefaultRootDir, "seccomp")
	}
	if obj.StreamingConnectionIdleTimeout == zeroDuration {
		obj.StreamingConnectionIdleTimeout = metav1.Duration{Duration: 4 * time.Hour}
	}
	if obj.SyncFrequency == zeroDuration {
		obj.SyncFrequency = metav1.Duration{Duration: 1 * time.Minute}
	}
	if obj.ContentType == "" {
		obj.ContentType = "application/vnd.kubernetes.protobuf"
	}
	if obj.KubeAPIQPS == nil {
		temp := int32(5)
		obj.KubeAPIQPS = &temp
	}
	if obj.KubeAPIBurst == 0 {
		obj.KubeAPIBurst = 10
	}
	if string(obj.HairpinMode) == "" {
		obj.HairpinMode = PromiscuousBridge
	}
	if obj.EvictionHard == nil {
		temp := "memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%,imagefs.available<15%"
		obj.EvictionHard = &temp
	}
	if obj.EvictionPressureTransitionPeriod == zeroDuration {
		obj.EvictionPressureTransitionPeriod = metav1.Duration{Duration: 5 * time.Minute}
	}
	if obj.SystemReserved == nil {
		obj.SystemReserved = make(map[string]string)
	}
	if obj.KubeReserved == nil {
		obj.KubeReserved = make(map[string]string)
	}
	if obj.MakeIPTablesUtilChains == nil {
		obj.MakeIPTablesUtilChains = boolVar(true)
	}
	if obj.IPTablesMasqueradeBit == nil {
		temp := int32(defaultIPTablesMasqueradeBit)
		obj.IPTablesMasqueradeBit = &temp
	}
	if obj.IPTablesDropBit == nil {
		temp := int32(defaultIPTablesDropBit)
		obj.IPTablesDropBit = &temp
	}
	if obj.CgroupsPerQOS == nil {
		temp := true
		obj.CgroupsPerQOS = &temp
	}
	if obj.CgroupDriver == "" {
		obj.CgroupDriver = "cgroupfs"
	}
	if obj.EnforceNodeAllocatable == nil {
		obj.EnforceNodeAllocatable = defaultNodeAllocatableEnforcement
	}
	if obj.FeatureGates == nil {
		obj.FeatureGates = make(map[string]bool)
	}
}

func boolVar(b bool) *bool {
	return &b
}

var (
	defaultCfg = KubeletConfiguration{}
)
<commit_msg>Allocate map for ManifestURLHeader<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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.
*/

package v1alpha1

import (
	"path/filepath"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kruntime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/kubernetes/pkg/kubelet/qos"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
	"k8s.io/kubernetes/pkg/master/ports"
	utilpointer "k8s.io/kubernetes/pkg/util/pointer"
)

const (
	DefaultRootDir = "/var/lib/kubelet"

	// DEPRECATED: auto detecting cloud providers goes against the initiative
	// for out-of-tree cloud providers as we'll now depend on cAdvisor integrations
	// with cloud providers instead of in the core repo.
	// More details here: https://github.com/kubernetes/kubernetes/issues/50986
	AutoDetectCloudProvider = "auto-detect"

	defaultIPTablesMasqueradeBit = 14
	defaultIPTablesDropBit       = 15
)

var (
	zeroDuration = metav1.Duration{}
	// Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information.
	defaultNodeAllocatableEnforcement = []string{"pods"}
)

func addDefaultingFuncs(scheme *kruntime.Scheme) error {
	return RegisterDefaults(scheme)
}

func SetDefaults_KubeletConfiguration(obj *KubeletConfiguration) {
	// pointer because the zeroDuration is valid - if you want to skip the trial period
	if obj.ConfigTrialDuration == nil {
		obj.ConfigTrialDuration = &metav1.Duration{Duration: 10 * time.Minute}
	}
	if obj.Authentication.Anonymous.Enabled == nil {
		obj.Authentication.Anonymous.Enabled = boolVar(true)
	}
	if obj.Authentication.Webhook.Enabled == nil {
		obj.Authentication.Webhook.Enabled = boolVar(false)
	}
	if obj.Authentication.Webhook.CacheTTL == zeroDuration {
		obj.Authentication.Webhook.CacheTTL = metav1.Duration{Duration: 2 * time.Minute}
	}
	if obj.Authorization.Mode == "" {
		obj.Authorization.Mode = KubeletAuthorizationModeAlwaysAllow
	}
	if obj.Authorization.Webhook.CacheAuthorizedTTL == zeroDuration {
		obj.Authorization.Webhook.CacheAuthorizedTTL = metav1.Duration{Duration: 5 * time.Minute}
	}
	if obj.Authorization.Webhook.CacheUnauthorizedTTL == zeroDuration {
		obj.Authorization.Webhook.CacheUnauthorizedTTL = metav1.Duration{Duration: 30 * time.Second}
	}

	if obj.Address == "" {
		obj.Address = "0.0.0.0"
	}
	if obj.CAdvisorPort == nil {
		obj.CAdvisorPort = utilpointer.Int32Ptr(4194)
	}
	if obj.VolumeStatsAggPeriod == zeroDuration {
		obj.VolumeStatsAggPeriod = metav1.Duration{Duration: time.Minute}
	}
	if obj.RuntimeRequestTimeout == zeroDuration {
		obj.RuntimeRequestTimeout = metav1.Duration{Duration: 2 * time.Minute}
	}
	if obj.CPUCFSQuota == nil {
		obj.CPUCFSQuota = boolVar(true)
	}
	if obj.EventBurst == 0 {
		obj.EventBurst = 10
	}
	if obj.EventRecordQPS == nil {
		temp := int32(5)
		obj.EventRecordQPS = &temp
	}
	if obj.EnableControllerAttachDetach == nil {
		obj.EnableControllerAttachDetach = boolVar(true)
	}
	if obj.EnableDebuggingHandlers == nil {
		obj.EnableDebuggingHandlers = boolVar(true)
	}
	if obj.EnableServer == nil {
		obj.EnableServer = boolVar(true)
	}
	if obj.FileCheckFrequency == zeroDuration {
		obj.FileCheckFrequency = metav1.Duration{Duration: 20 * time.Second}
	}
	if obj.HealthzBindAddress == "" {
		obj.HealthzBindAddress = "127.0.0.1"
	}
	if obj.HealthzPort == nil {
		obj.HealthzPort = utilpointer.Int32Ptr(10248)
	}
	if obj.HostNetworkSources == nil {
		obj.HostNetworkSources = []string{kubetypes.AllSource}
	}
	if obj.HostPIDSources == nil {
		obj.HostPIDSources = []string{kubetypes.AllSource}
	}
	if obj.HostIPCSources == nil {
		obj.HostIPCSources = []string{kubetypes.AllSource}
	}
	if obj.HTTPCheckFrequency == zeroDuration {
		obj.HTTPCheckFrequency = metav1.Duration{Duration: 20 * time.Second}
	}
	if obj.ImageMinimumGCAge == zeroDuration {
		obj.ImageMinimumGCAge = metav1.Duration{Duration: 2 * time.Minute}
	}
	if obj.ImageGCHighThresholdPercent == nil {
		// default is below docker's default dm.min_free_space of 90%
		temp := int32(85)
		obj.ImageGCHighThresholdPercent = &temp
	}
	if obj.ImageGCLowThresholdPercent == nil {
		temp := int32(80)
		obj.ImageGCLowThresholdPercent = &temp
	}
	if obj.MaxOpenFiles == 0 {
		obj.MaxOpenFiles = 1000000
	}
	if obj.MaxPods == 0 {
		obj.MaxPods = 110
	}
	if obj.VolumePluginDir == "" {
		obj.VolumePluginDir = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/"
	}
	if obj.NodeStatusUpdateFrequency == zeroDuration {
		obj.NodeStatusUpdateFrequency = metav1.Duration{Duration: 10 * time.Second}
	}
	if obj.CPUManagerPolicy == "" {
		obj.CPUManagerPolicy = "none"
	}
	if obj.CPUManagerReconcilePeriod == zeroDuration {
		obj.CPUManagerReconcilePeriod = obj.NodeStatusUpdateFrequency
	}
	if obj.OOMScoreAdj == nil {
		temp := int32(qos.KubeletOOMScoreAdj)
		obj.OOMScoreAdj = &temp
	}
	if obj.Port == 0 {
		obj.Port = ports.KubeletPort
	}
	if obj.ReadOnlyPort == nil {
		obj.ReadOnlyPort = utilpointer.Int32Ptr(ports.KubeletReadOnlyPort)
	}
	if obj.RegisterNode == nil {
		obj.RegisterNode = boolVar(true)
	}
	if obj.RegistryBurst == 0 {
		obj.RegistryBurst = 10
	}
	if obj.RegistryPullQPS == nil {
		temp := int32(5)
		obj.RegistryPullQPS = &temp
	}
	if obj.ResolverConfig == "" {
		obj.ResolverConfig = kubetypes.ResolvConfDefault
	}
	if obj.SerializeImagePulls == nil {
		obj.SerializeImagePulls = boolVar(true)
	}
	if obj.SeccompProfileRoot == "" {
		obj.SeccompProfileRoot = filepath.Join(DefaultRootDir, "seccomp")
	}
	if obj.StreamingConnectionIdleTimeout == zeroDuration {
		obj.StreamingConnectionIdleTimeout = metav1.Duration{Duration: 4 * time.Hour}
	}
	if obj.SyncFrequency == zeroDuration {
		obj.SyncFrequency = metav1.Duration{Duration: 1 * time.Minute}
	}
	if obj.ContentType == "" {
		obj.ContentType = "application/vnd.kubernetes.protobuf"
	}
	if obj.KubeAPIQPS == nil {
		temp := int32(5)
		obj.KubeAPIQPS = &temp
	}
	if obj.KubeAPIBurst == 0 {
		obj.KubeAPIBurst = 10
	}
	if string(obj.HairpinMode) == "" {
		obj.HairpinMode = PromiscuousBridge
	}
	if obj.EvictionHard == nil {
		temp := "memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%,imagefs.available<15%"
		obj.EvictionHard = &temp
	}
	if obj.EvictionPressureTransitionPeriod == zeroDuration {
		obj.EvictionPressureTransitionPeriod = metav1.Duration{Duration: 5 * time.Minute}
	}
	if obj.SystemReserved == nil {
		obj.SystemReserved = make(map[string]string)
	}
	if obj.KubeReserved == nil {
		obj.KubeReserved = make(map[string]string)
	}
	if obj.MakeIPTablesUtilChains == nil {
		obj.MakeIPTablesUtilChains = boolVar(true)
	}
	if obj.IPTablesMasqueradeBit == nil {
		temp := int32(defaultIPTablesMasqueradeBit)
		obj.IPTablesMasqueradeBit = &temp
	}
	if obj.IPTablesDropBit == nil {
		temp := int32(defaultIPTablesDropBit)
		obj.IPTablesDropBit = &temp
	}
	if obj.CgroupsPerQOS == nil {
		temp := true
		obj.CgroupsPerQOS = &temp
	}
	if obj.CgroupDriver == "" {
		obj.CgroupDriver = "cgroupfs"
	}
	if obj.EnforceNodeAllocatable == nil {
		obj.EnforceNodeAllocatable = defaultNodeAllocatableEnforcement
	}
	if obj.FeatureGates == nil {
		obj.FeatureGates = make(map[string]bool)
	}
	if obj.ManifestURLHeader == nil {
		obj.ManifestURLHeader = make(map[string][]string)
	}
}

func boolVar(b bool) *bool {
	return &b
}

var (
	defaultCfg = KubeletConfiguration{}
)
<|endoftext|>