<commit_before>package main

import (
	"fmt"
	"log"
	"log/syslog"
	"os"
	"os/signal"
	"sort"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/nodefs"
	"github.com/hanwen/go-fuse/fuse/pathfs"
	"github.com/hanwen/go-fuse/unionfs"
	"github.com/jessevdk/go-flags"
	"github.com/jszwedko/ec2-metadatafs/internal/logging"
	"github.com/jszwedko/ec2-metadatafs/metadatafs"
	"github.com/jszwedko/ec2-metadatafs/tagsfs"
	"github.com/sevlyar/go-daemon"
)

const (
	verbose     = 1
	moreVerbose = 2
)

var (
	// VersionString is the git tag this binary is associated with
	VersionString string

	facilityMap = map[string]syslog.Priority{
		"KERN":     syslog.LOG_KERN,
		"USER":     syslog.LOG_USER,
		"MAIL":     syslog.LOG_MAIL,
		"DAEMON":   syslog.LOG_DAEMON,
		"AUTH":     syslog.LOG_AUTH,
		"SYSLOG":   syslog.LOG_SYSLOG,
		"LPR":      syslog.LOG_LPR,
		"NEWS":     syslog.LOG_NEWS,
		"UUCP":     syslog.LOG_UUCP,
		"CRON":     syslog.LOG_CRON,
		"AUTHPRIV": syslog.LOG_AUTHPRIV,
		"FTP":      syslog.LOG_FTP,

		"LOCAL0": syslog.LOG_LOCAL0,
		"LOCAL1": syslog.LOG_LOCAL1,
		"LOCAL2": syslog.LOG_LOCAL2,
		"LOCAL3": syslog.LOG_LOCAL3,
		"LOCAL4": syslog.LOG_LOCAL4,
		"LOCAL5": syslog.LOG_LOCAL5,
		"LOCAL6": syslog.LOG_LOCAL6,
		"LOCAL7": syslog.LOG_LOCAL7,
	}
)

func sortedValidFacilities() []string {
	facilities := FacilityNamesSlice(make([]string, 0, len(facilityMap)))
	for k := range facilityMap {
		facilities = append(facilities, k)
	}
	sort.Sort(facilities)
	return facilities
}

// FacilityNamesSlice supports sorting of facility names
type FacilityNamesSlice []string

func (f FacilityNamesSlice) Len() int {
	return len(f)
}

func (f FacilityNamesSlice) Less(i, j int) bool {
	return facilityMap[f[i]] < facilityMap[f[j]]
}

func (f FacilityNamesSlice) Swap(i, j int) {
	f[i], f[j] = f[j], f[i]
}

// Options holds the command line arguments and flags
// Intended for use with go-flags
type Options struct {
	Verbose      []bool       `short:"v" long:"verbose"     description:"Print verbose logs, can be specified multiple times (up to 2)"`
	Foreground   bool         `short:"f" long:"foreground"  description:"Run in foreground"`
	Version      bool         `short:"V" long:"version"     description:"Display version info"`
	Endpoint     string       `short:"e" long:"endpoint"    description:"EC2 metadata service HTTP endpoint" default:"http://169.254.169.254/latest/"`
	CacheSec     int          `short:"c" long:"cachesec"    description:"Number of seconds to cache files attributes and directory listings. 0 to disable, -1 for indefinite." default:"0"`
	Tags         bool         `short:"t" long:"tags"        description:"Mount EC2 instance tags at <mount point>/tags"`
	MountOptions mountOptions `short:"o" long:"options"     description:"Mount options, see below for description"`

	DisableSyslog  bool   `short:"n" long:"no-syslog"        description:"Disable syslog when daemonized"`
	SyslogFacility string `short:"F" long:"syslog-facility"  description:"Syslog facility to use when daemonized (see below for options)" default:"USER"`

	AWSCredentials awsCredentials `group:"AWS Credentials (only used when mounting tags)"`

	Args struct {
		Mountpoint string `positional-arg-name:"mountpoint"   description:"Directory to mount the filesystem at"`
	} `positional-args:"yes"`
}

type awsCredentials struct {
	AWSAccessKeyID     string `long:"aws-access-key-id"     description:"AWS Access Key ID (adds to credential chain, see below)"`
	AWSSecretAccessKey string `long:"aws-secret-access-key" description:"AWS Secret Access key (adds to credential chain, see below)"`
	AWSSessionToken    string `long:"aws-session-token"     description:"AWS session token (adds to credential chain, see below)"`
}

func (a *awsCredentials) credentialChain() *credentials.Credentials {
	return credentials.NewChainCredentials([]credentials.Provider{
		&credentials.StaticProvider{Value: credentials.Value{
			AccessKeyID:     a.AWSAccessKeyID,
			SecretAccessKey: a.AWSAccessKeyID,
			SessionToken:    a.AWSSessionToken}},
		&credentials.EnvProvider{},
		&credentials.SharedCredentialsProvider{},
		&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(session.New())},
	})
}

// mountOptions implements flags.Marshaller and flags.Unmarshaller interface to
// read `mount` style options from the user<commit_msg>Fix issue with passing static AWS credentials<commit_after>package main

import (
	"fmt"
	"log"
	"log/syslog"
	"os"
	"os/signal"
	"sort"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/nodefs"
	"github.com/hanwen/go-fuse/fuse/pathfs"
	"github.com/hanwen/go-fuse/unionfs"
	"github.com/jessevdk/go-flags"
	"github.com/jszwedko/ec2-metadatafs/internal/logging"
	"github.com/jszwedko/ec2-metadatafs/metadatafs"
	"github.com/jszwedko/ec2-metadatafs/tagsfs"
	"github.com/sevlyar/go-daemon"
)

const (
	verbose     = 1
	moreVerbose = 2
)

var (
	// VersionString is the git tag this binary is associated with
	VersionString string

	facilityMap = map[string]syslog.Priority{
		"KERN":     syslog.LOG_KERN,
		"USER":     syslog.LOG_USER,
		"MAIL":     syslog.LOG_MAIL,
		"DAEMON":   syslog.LOG_DAEMON,
		"AUTH":     syslog.LOG_AUTH,
		"SYSLOG":   syslog.LOG_SYSLOG,
		"LPR":      syslog.LOG_LPR,
		"NEWS":     syslog.LOG_NEWS,
		"UUCP":     syslog.LOG_UUCP,
		"CRON":     syslog.LOG_CRON,
		"AUTHPRIV": syslog.LOG_AUTHPRIV,
		"FTP":      syslog.LOG_FTP,

		"LOCAL0": syslog.LOG_LOCAL0,
		"LOCAL1": syslog.LOG_LOCAL1,
		"LOCAL2": syslog.LOG_LOCAL2,
		"LOCAL3": syslog.LOG_LOCAL3,
		"LOCAL4": syslog.LOG_LOCAL4,
		"LOCAL5": syslog.LOG_LOCAL5,
		"LOCAL6": syslog.LOG_LOCAL6,
		"LOCAL7": syslog.LOG_LOCAL7,
	}
)

func sortedValidFacilities() []string {
	facilities := FacilityNamesSlice(make([]string, 0, len(facilityMap)))
	for k := range facilityMap {
		facilities = append(facilities, k)
	}
	sort.Sort(facilities)
	return facilities
}

// FacilityNamesSlice supports sorting of facility names
type FacilityNamesSlice []string

func (f FacilityNamesSlice) Len() int {
	return len(f)
}

func (f FacilityNamesSlice) Less(i, j int) bool {
	return facilityMap[f[i]] < facilityMap[f[j]]
}

func (f FacilityNamesSlice) Swap(i, j int) {
	f[i], f[j] = f[j], f[i]
}

// Options holds the command line arguments and flags
// Intended for use with go-flags
type Options struct {
	Verbose      []bool       `short:"v" long:"verbose"     description:"Print verbose logs, can be specified multiple times (up to 2)"`
	Foreground   bool         `short:"f" long:"foreground"  description:"Run in foreground"`
	Version      bool         `short:"V" long:"version"     description:"Display version info"`
	Endpoint     string       `short:"e" long:"endpoint"    description:"EC2 metadata service HTTP endpoint" default:"http://169.254.169.254/latest/"`
	CacheSec     int          `short:"c" long:"cachesec"    description:"Number of seconds to cache files attributes and directory listings. 0 to disable, -1 for indefinite." default:"0"`
	Tags         bool         `short:"t" long:"tags"        description:"Mount EC2 instance tags at <mount point>/tags"`
	MountOptions mountOptions `short:"o" long:"options"     description:"Mount options, see below for description"`

	DisableSyslog  bool   `short:"n" long:"no-syslog"        description:"Disable syslog when daemonized"`
	SyslogFacility string `short:"F" long:"syslog-facility"  description:"Syslog facility to use when daemonized (see below for options)" default:"USER"`

	AWSCredentials awsCredentials `group:"AWS Credentials (only used when mounting tags)"`

	Args struct {
		Mountpoint string `positional-arg-name:"mountpoint"   description:"Directory to mount the filesystem at"`
	} `positional-args:"yes"`
}

type awsCredentials struct {
	AWSAccessKeyID     string `long:"aws-access-key-id"     description:"AWS Access Key ID (adds to credential chain, see below)"`
	AWSSecretAccessKey string `long:"aws-secret-access-key" description:"AWS Secret Access key (adds to credential chain, see below)"`
	AWSSessionToken    string `long:"aws-session-token"     description:"AWS session token (adds to credential chain, see below)"`
}

func (a *awsCredentials) credentialChain() *credentials.Credentials {
	return credentials.NewChainCredentials([]credentials.Provider{
		&credentials.StaticProvider{
			Value: credentials.Value{
				AccessKeyID:     a.AWSAccessKeyID,
				SecretAccessKey: a.AWSSecretAccessKey,
				SessionToken:    a.AWSSessionToken,
			},
		},
		&credentials.EnvProvider{},
		&credentials.SharedCredentialsProvider{},
		&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(session.New())},
	})
}

// mountOptions implements flags.Marshaller and flags.Unmarshaller interface to
// read `mount` style options from the user
{'fraction_non_alphanumeric': 0.13025751072961372, 'fraction_numerical': 0.009871244635193134, 'mean_word_length': 4.269078575466366, 'pattern_counts': {'":': 40, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '384426', 'n_tokens_mistral': 3340, 'n_tokens_neox': 3214, 'n_words': 718}