agent/association/model/model.go (69 lines of code) (raw):
// Copyright 2016 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 model provides model definition for association
package model
import (
"fmt"
"time"
"github.com/aws/amazon-ssm-agent/agent/association/scheduleexpression"
"github.com/aws/amazon-ssm-agent/agent/contracts"
"github.com/aws/amazon-ssm-agent/agent/log"
"github.com/aws/amazon-ssm-agent/agent/times"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ssm"
)
// InstanceAssociation represents detail information of an association
type InstanceAssociation struct {
DocumentID string
CreateDate time.Time
NextScheduledDate *time.Time
Association *ssm.InstanceAssociationSummary
ParsedExpression scheduleexpression.ScheduleExpression
Document *string
Errors []error
}
// ParseExpression parses the expression with the given association
func (newAssoc *InstanceAssociation) ParseExpression(log log.T) error {
parsedScheduleExpression, err := scheduleexpression.CreateScheduleExpression(log, *newAssoc.Association.ScheduleExpression)
if err != nil {
return fmt.Errorf("Failed to parse schedule expression %v, %v", *newAssoc.Association.ScheduleExpression, err)
}
newAssoc.ParsedExpression = parsedScheduleExpression
return nil
}
// IsRunOnceAssociation return true for the association that doesn't have schedule expression and will run only once
func (assoc *InstanceAssociation) IsRunOnceAssociation() bool {
return assoc.Association.ScheduleExpression == nil || *assoc.Association.ScheduleExpression == ""
}
// RunNow sets the NextScheduledDate to current time
func (newAssoc *InstanceAssociation) RunNow() {
newAssoc.NextScheduledDate = aws.Time(time.Now().UTC())
}
// SetNextScheduledDate sets next scheduled date for the given association
func (newAssoc *InstanceAssociation) SetNextScheduledDate(log log.T) {
// Run association immediately if DetailedStatus is Pending
if newAssoc.Association.DetailedStatus != nil &&
*newAssoc.Association.DetailedStatus == contracts.AssociationStatusPending {
newAssoc.RunNow()
return
}
if newAssoc.IsRunOnceAssociation() {
if newAssoc.Association.DetailedStatus != nil &&
*newAssoc.Association.DetailedStatus == contracts.AssociationStatusAssociated {
// Run association immediately if RunOnceAssociation has not been run before
newAssoc.RunNow()
} else {
log.Infof("Skipping association %v as it has been processed", *newAssoc.Association.Name)
newAssoc.NextScheduledDate = nil
}
return
}
// Run association immediately if association has not been run before
if newAssoc.Association.LastExecutionDate == nil {
newAssoc.RunNow()
return
}
if newAssoc.ParsedExpression == nil {
if err := newAssoc.ParseExpression(log); err != nil {
log.Errorf("Skipping association %v as there was an error parsing schedule expression %v."+
" Error received while parsing was %v.",
*newAssoc.Association.AssociationId, *newAssoc.Association.ScheduleExpression, err)
newAssoc.NextScheduledDate = nil
return
}
}
// Set next schedule date of association according to it's schedule
newAssoc.NextScheduledDate = aws.Time(
newAssoc.ParsedExpression.Next(newAssoc.Association.LastExecutionDate.UTC()).UTC())
log.Infof("Based upon expression %v and last execution date %v, next scheduled date for association %v is %v",
*newAssoc.Association.ScheduleExpression, times.ToIsoDashUTC(*newAssoc.Association.LastExecutionDate),
*newAssoc.Association.AssociationId, times.ToIsoDashUTC(*newAssoc.NextScheduledDate))
}