github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/check_factory.go (about) 1 package db 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "code.cloudfoundry.org/lager/lagerctx" 9 sq "github.com/Masterminds/squirrel" 10 "github.com/pf-qiu/concourse/v6/atc" 11 "github.com/pf-qiu/concourse/v6/atc/creds" 12 "github.com/pf-qiu/concourse/v6/atc/db/lock" 13 ) 14 15 //go:generate counterfeiter . Checkable 16 17 type Checkable interface { 18 PipelineRef 19 20 Name() string 21 TeamID() int 22 ResourceConfigScopeID() int 23 TeamName() string 24 Type() string 25 Source() atc.Source 26 Tags() atc.Tags 27 CheckEvery() string 28 CheckTimeout() string 29 LastCheckEndTime() time.Time 30 CurrentPinnedVersion() atc.Version 31 32 HasWebhook() bool 33 34 CheckPlan(atc.Version, time.Duration, ResourceTypes, atc.Source) atc.CheckPlan 35 CreateBuild(context.Context, bool, atc.Plan) (Build, bool, error) 36 } 37 38 //go:generate counterfeiter . CheckFactory 39 40 type CheckFactory interface { 41 TryCreateCheck(context.Context, Checkable, ResourceTypes, atc.Version, bool) (Build, bool, error) 42 Resources() ([]Resource, error) 43 ResourceTypes() ([]ResourceType, error) 44 } 45 46 type checkFactory struct { 47 conn Conn 48 lockFactory lock.LockFactory 49 50 secrets creds.Secrets 51 varSourcePool creds.VarSourcePool 52 53 planFactory atc.PlanFactory 54 55 defaultCheckTimeout time.Duration 56 defaultCheckInterval time.Duration 57 defaultWithWebhookCheckInterval time.Duration 58 } 59 60 type CheckDurations struct { 61 Timeout time.Duration 62 Interval time.Duration 63 IntervalWithWebhook time.Duration 64 } 65 66 func NewCheckFactory( 67 conn Conn, 68 lockFactory lock.LockFactory, 69 secrets creds.Secrets, 70 varSourcePool creds.VarSourcePool, 71 durations CheckDurations, 72 ) CheckFactory { 73 return &checkFactory{ 74 conn: conn, 75 lockFactory: lockFactory, 76 77 secrets: secrets, 78 varSourcePool: varSourcePool, 79 80 planFactory: atc.NewPlanFactory(time.Now().Unix()), 81 82 defaultCheckTimeout: durations.Timeout, 83 defaultCheckInterval: durations.Interval, 84 defaultWithWebhookCheckInterval: durations.IntervalWithWebhook, 85 } 86 } 87 88 func (c *checkFactory) TryCreateCheck(ctx context.Context, checkable Checkable, resourceTypes ResourceTypes, from atc.Version, manuallyTriggered bool) (Build, bool, error) { 89 logger := lagerctx.FromContext(ctx) 90 91 var err error 92 93 sourceDefaults := atc.Source{} 94 parentType, found := resourceTypes.Parent(checkable) 95 if found { 96 if parentType.Version() == nil { 97 return nil, false, fmt.Errorf("resource type '%s' has no version", parentType.Name()) 98 } 99 sourceDefaults = parentType.Defaults() 100 } else { 101 defaults, found := atc.FindBaseResourceTypeDefaults(checkable.Type()) 102 if found { 103 sourceDefaults = defaults 104 } 105 } 106 107 interval := c.defaultCheckInterval 108 if checkable.HasWebhook() { 109 interval = c.defaultWithWebhookCheckInterval 110 } 111 if every := checkable.CheckEvery(); every != "" { 112 interval, err = time.ParseDuration(every) 113 if err != nil { 114 return nil, false, fmt.Errorf("check interval: %s", err) 115 } 116 } 117 118 if !manuallyTriggered && time.Now().Before(checkable.LastCheckEndTime().Add(interval)) { 119 // skip creating the check if its interval hasn't elapsed yet 120 return nil, false, nil 121 } 122 123 checkPlan := checkable.CheckPlan(from, interval, resourceTypes.Filter(checkable), sourceDefaults) 124 125 plan := c.planFactory.NewPlan(checkPlan) 126 127 build, created, err := checkable.CreateBuild(ctx, manuallyTriggered, plan) 128 if err != nil { 129 return nil, false, fmt.Errorf("create build: %w", err) 130 } 131 132 if !created { 133 return nil, false, nil 134 } 135 136 logger.Info("created-build", build.LagerData()) 137 138 return build, true, nil 139 } 140 141 func (c *checkFactory) Resources() ([]Resource, error) { 142 var resources []Resource 143 144 rows, err := resourcesQuery. 145 Join("(select DISTINCT(resource_id) FROM job_inputs) ji ON ji.resource_id = r.id"). 146 Where(sq.Eq{"p.paused": false}). 147 RunWith(c.conn). 148 Query() 149 150 if err != nil { 151 return nil, err 152 } 153 154 defer Close(rows) 155 156 for rows.Next() { 157 r := newEmptyResource(c.conn, c.lockFactory) 158 err = scanResource(r, rows) 159 if err != nil { 160 return nil, err 161 } 162 163 resources = append(resources, r) 164 } 165 166 return resources, nil 167 } 168 169 func (c *checkFactory) ResourceTypes() ([]ResourceType, error) { 170 var resourceTypes []ResourceType 171 172 rows, err := resourceTypesQuery. 173 RunWith(c.conn). 174 Query() 175 176 if err != nil { 177 return nil, err 178 } 179 180 defer Close(rows) 181 182 for rows.Next() { 183 r := newEmptyResourceType(c.conn, c.lockFactory) 184 err = scanResourceType(r, rows) 185 if err != nil { 186 return nil, err 187 } 188 189 resourceTypes = append(resourceTypes, r) 190 } 191 192 return resourceTypes, nil 193 }